Tasks shouldn't normally hog the actor context indefinitely after making a call that's bound to
that actor, since that prevents the actor from potentially taking on other jobs it needs to
be able to address. Set up SILGen so that it saves the current executor (using a new runtime
entry point) and hops back to it after every actor call, not only ones where the caller context
is also actor-bound.
The added executor hopping here also exposed a bug in the runtime implementation while processing
DefaultActor jobs, where if an actor job returned to the processing loop having already yielded
the thread back to a generic executor, we would still attempt to make the actor give up the thread
again, corrupting its state.
rdar://71905765
The strategy for implementing them is integrated with the
PathComponent infrastructure in SILGen in order to correctly
support mixtures of chained accesses and forced optionals, etc.
The actor isolation information is only piped into LValues from
the expressions that might be marked implicitly-async.
* Refactoring: replace "Destination" and the ownership qualifier by a single "Mode". This represents much better the mode how the instruction is to be lowered. NFC
* Make assign_by_wrapper printable and parseable.
* Fix lowering of the assign modes for indirect results of the init-closure: The indirect result was initialized and not assigned to. The fix is to insert a destroy_addr before calling the init closure. This fixes a memory lifetime error and/or a memory leak. Found by inspection.
* Fix an iterator-invalidation crash in RawSILInstLowering
* Add tests for lowering assign_by_wrapper.
LifetimeChecker::shouldEmitError in order to avoid incorrectly
populating EmittedErrorLocs when no error is emitted.
This fixes a few corner cases where DI would error out or crash
while assigning to a wrapped property with a nonmutating setter.
Implement SIL generation for "async let" constructs, which involves:
1. Creating a child task future at the point of declaration of the "async let",
which runs the initializer in an async closure.
2. Entering a cleanup to destroy the child task.
3. Entering a cleanup to cancel the child task.
4. Waiting for the child task when any of the variables is reference.
5. Decomposing the result of the child task to write the results into the
appropriate variables.
Implements rdar://71123479.
Add AccesssedStorage::compute and computeInScope to mirror AccessPath.
Allow recovering the begin_access for Nested storage.
Adds AccessedStorage.visitRoots().
captured local variables for the assign_by_wrapper setter.
Since assign_by_wrapper will always be re-written to initialization
if the captured local variable is uninitialized, it's unnecessary
to mark the capture as an escape. This lets us support out-of-line
initialization for local property wrappers.
```
class Generic<T> {
@objc dynamic func method() {}
}
extension Generic {
@_dynamicReplacement(for:method())
func replacement() {}
}
```
The standard mechanism of using Objective-C categories for dynamically
replacing @objc methods in generic classes does not work.
Instead we mark the native entry point as replaceable.
Because this affects all @objc methods in generic classes (whether there
is a replacement or not) by making the native entry point
`[dynamically_replaceable]` (regardless of optimization mode) we guard this by
the -enable-implicit-dynamic flag because we are late in the release cycle.
* Replace isNativeDynamic and isObjcDynamic by calls to shouldUse*Dispatch and
shouldUse*Replacement
This disambiguates between which dispatch method we should use at call
sites and how these methods should implement dynamic function
replacement.
* Don't emit the method entry for @_dynamicReplacement(for:) of generic class
methods
There is not way to call this entry point since we can't generate an
objective-c category for generic classes.
rdar://63679357
This became necessary after recent function type changes that keep
substituted generic function types abstract even after substitution to
correctly handle automatic opaque result type substitution.
Instead of performing the opaque result type substitution as part of
substituting the generic args the underlying type will now be reified as
part of looking at the parameter/return types which happens as part of
the function convention apis.
rdar://62560867
This is achieved in 3 steps:
1. CSApply detects assignments to property wrappers inside constructors, and produces an `inout` expr instead of a `load`, which it normally would because nonmutating setters take the `self` by-value. This is necessary becasue the assign_by_wrapper instruction expects an address type for its $1 operand.
2. SILGenLValue now emits the assign_by_wrapper pattern for such setters, ignoring the fact that they capture `self` by value. It also introduces an additional load instruction for the setter patrial_apply because the setter signature still expects a value and we now have an address (because of (1)).
3. DefiniteInitialization specifically ignores load instructions used to produce a `self` value for a setter referenced on assign_by_wrapper because it will be deleted by lowering anyway.
Resolves rdar://problem/60600911 and rdar://problem/52280477
GetterSetterComponent::hasPropertyWrapper() now checks for more
stuff than just whether there's a property wrapper or not.
It's therefore renamed to canRewriteSetAsPropertyWrapperInit().
When assigning to a wrapped variable in 'init()', if the property wrapper's
'wrappedValue:' parameter is an escaping autoclosure, the initializer and
setter have incompatible types -- the setter takes a value, and initializer
takes a closure returning that value.
An assign_by_wrapper with incompatible types causes SIL verification to fail.
This commit makes the SIL not use assign_by_wrapper in such cases, and use the
setter directly, resulting in a definitive initialization (DI) error instead.
struct S {
@Lazy var n: Int // Lazy.init(wrappedValue: @autoclosure ... )
init() {
n = 1 // error: 'self' used before all stored properties are initialized
}
}
This means that it can only have a guaranteed object as an operandand that we
validate that all uses of the result address of open_existential_box occur only
within the lifetime of said object's borrow scope.
This fixes an immediate bug with subst-to-orig conversion of
parameter functions that I'm surprised isn't otherwise tested.
More importantly, it preserves valuable information that should
let us handle a much wider variety of variant representations
that aren't necessarily expressed in the AbstractionPattern.
Use the substitution map for the LValue component to properly handle the
case where we need to re-abstract the argument to the assign_by_wrapper
setter.
Resolves rdar://59553318
Codegen for the assign_by_wrapper instruction emits prepared arguments
directly into the initializer or accessor functions. This means it
misses out on the CC matching code that the general apply path uses.
In this particular case, an enum value was constructed within the
resilience boundary, but passed to the setter for a wrapper property
that expected it to be in memory.
Check the calling convention before we emit the assign_by_wrapper
instruction, and materialize an address for indirect CCs as required.
resolves rdar://59071930
The original design was to make it so that end_borrow tied at the use level its
original/borrowed value. So we would have:
```
%borrowedVal = begin_borrow %original
...
end_borrow %borrowedVal from %original
```
In the end we decided not to use that design and instead just use:
```
%borrowedVal = begin_borrow %original
...
end_borrow %borrowedVal
```
In order to enable that transition, I left the old API for end_borrow that took
both original and borrowedVal and reimplemented it on top of the new API that
just took the borrowedVal (i.e. the original was just a dead arg).
Now given where we are in the development, it makes sense to get rid of that
transition API and move to just use the new API.
This reverts commit a3b68e6df5.
Speculative revert because I believe it is the cause of the failures on
the swift-master-source-compat-suite-enable-verify-exclusivity bot.
rdar://58529726
https://forums.swift.org/t/improving-the-representation-of-polymorphic-interfaces-in-sil-with-substituted-function-types/29711
This prepares SIL to be able to more accurately preserve the calling convention of
polymorphic generic interfaces by letting the type system represent "substituted function types".
We add a couple of fields to SILFunctionType to support this:
- A substitution map, accessed by `getSubstitutions()`, which maps the generic signature
of the function to its concrete implementation. This will allow, for instance, a protocol
witness for a requirement of type `<Self: P> (Self, ...) -> ...` for a concrete conforming
type `Foo` to express its type as `<Self: P> (Self, ...) -> ... for <Foo>`, preserving the relation
to the protocol interface without relying on the pile of hacks that is the `witness_method`
protocol.
- A bool for whether the generic signature of the function is "implied" by the substitutions.
If true, the generic signature isn't really part of the calling convention of the function.
This will allow closure types to distinguish a closure being passed to a generic function, like
`<T, U> in (*T, *U) -> T for <Int, String>`, from the concrete type `(*Int, *String) -> Int`,
which will make it easier for us to differentiate the representation of those as types, for
instance by giving them different pointer authentication discriminators to harden arm64e
code.
This patch is currently NFC, it just introduces the new APIs and takes a first pass at updating
code to use them. Much more work will need to be done once we start exercising these new
fields.
This does bifurcate some existing APIs:
- SILFunctionType now has two accessors to get its generic signature.
`getSubstGenericSignature` gets the generic signature that is used to apply its
substitution map, if any. `getInvocationGenericSignature` gets the generic signature
used to invoke the function at apply sites. These differ if the generic signature is
implied.
- SILParameterInfo and SILResultInfo values carry the unsubstituted types of the parameters
and results of the function. They now have two APIs to get that type. `getInterfaceType`
returns the unsubstituted type of the generic interface, and
`getArgumentType`/`getReturnValueType` produce the substituted type that is used at
apply sites.
Use the newly-introduced property wrapper backing initializer function
in definite initialization (DI) to form the assign_by_wrapper
instruction, rather than forming a reference to the (only) property
wrapper's `init(wrappedValue:)`. This allows DI to work on properties
that have multiple, composed property wrappers applied to them.
Fixes a crash when a function, which assigns to a wrapped property has additional generic parameters.
https://bugs.swift.org/browse/SR-11484
rdar://problem/55442328
This mostly requires changing various entry points to pass around a
TypeConverter instead of a SILModule. I've left behind entry points
that take a SILModule for a few methods like SILType::subst() to
avoid creating even more churn.
This will ensure that the optimizer never eliminates the strong_retain. This
operation is meant to be unmanaged, we should respect the user's choice here
even in optimized builds.
We've fixed a number of bugs recently where callers did not expect
to get a null Type out of subst(). This occurs particularly often
in SourceKit, where the input AST is often invalid and the types
resulting from substitution are mostly used for display.
Let's fix all these potential problems in one fell swoop by changing
subst() to always return a Type, possibly one containing ErrorTypes.
Only a couple of places depended on the old behavior, and they were
easy enough to change from checking for a null Type to checking if
the result responds with true to hasError().
Also while we're at it, simplify a few call sites of subst().
Since the return value of getAccessor() depends on mutable state, it
does not make sense in the request evaluator world. Let's begin by
removing some utility methods derived from getAccessor(), replacing
calls to them with calls to getAccessor().