If a subscript uses a read accessor to yield a noncopyable value,
we'd emit an `end_apply` that's too tightly scoped to allow for
a subsequent borrowing access on the yielded value.
resolves rdar://159079818
There's no need for two separate types here. Fully separate the addressable buffer
tracking from VarLocs as well, in order to set up for a fix to addressable references
to `if let` and `guard let` bindings.
functions to compute them directly without a TypeLowering object, and
change a lot of getTypeLowering call sites to just use that.
There is one subtle change here that I think is okay: SILBuilder used to
use different TypeExpansionContexts when inserting into a global:
- getTypeLowering() always used a minimal context when inserting into
a global
- getTypeExpansionContext() always returned a maximal context for the
module scope
The latter seems more correct, as AFAIK global initializers are never
inlinable. If they are, we probably need to configure the builder with
an actual context properly rather than making global assumptions.
This is incremental progress towards computing this for most types
without a TypeLowering, and hopefully eventually removing TL entirely.
Specifically, we were not inserting the implicit isolated parameter and were not
setting up the actor prologue. To keep this specific to nonisolated(nonsending)
code, I only setup the actor prologue if we know that we have something that is
nonisolated(nonsending).
I also ported some async initializer tests to run with/without
nonisolated(nonsending) just to increase code coverage.
rdar://156919493
Specifically:
1. When we convert a function to nonisolated(nonsending), we need to
make sure that in the thunk we hop upon return since nonisolated(nonsending)
functions are assumed to preserve the caller's isolation.
2. When we convert a function from nonisolated(nonsending), we need to
make sure that in the thunk we hop onto the actor that we are passing in as the
isolated parameter of the nonisolated(nonsending) function. This ensures that
the nonisolated(nonsending) function can assume that it is already on its
isolated parameter's actor at function entry.
rdar://155905383
In order to accommodate case bodies with multiple case labels, the AST
represents the bindings in each pattern as a distinct declaration from
the matching binding in the case body, and SILGen shares the variable
representation between the two declarations. That means that the two
declarations also need to be able to share an addressable representation.
Add an "alias" state to the addressable buffer data structures so that
we can refer back to the original case label var decl when the case body
var decl is brought into scope, so that accesses through either decl
properly force the addressable representation.
Fixes rdar://154543619.
Also, I discovered that we don't apply nonisolated(nonsending) to
function types in the new mode. That's one for a different patch.
Fixes rdar://154401813 and rdar://154137740
When accessing stored properties out of an addressable variable or parameter
binding, the stored property's address inside the addressable storage of the
aggregate is itself addressable. Also, if a computed property is implemented
using an addressor, treat that as a sign that the returned address should be
used as addressable storage as well. rdar://152280207
This ensures that when we generate the vtable thunk for a
nonisolated(nonsending) override (or vis-a-versa), we get the ABI correct. I
also added tests for all of the relevant cases for vtables that we check for
protocols.
rdar://151394209
Now that coroutine kind (and consequently ABI) for the accessors is
keyed off a SIL option, it's no longer possible to read whether a given
SILFunction arose from a read/modify coroutine just by checking its
coroutine kind. Regardless of ABI, read/modify coroutines may only
unwind (i.e. are only permitted not to "run to completion") if the
relevant experimental (soon to be deleted) feature is enabled.
This involved cleaning up and generalizing the work from
f245389bb3. I followed the same approach: hide the
implicit parameter while we run things through translateArgument and friends and
then put it back in manually.
As an additional benefit, I think I found a good place to put FunctionIsolation
onto lowered AnyFunctionTypes that will not cause cycles in the evaluator since
it is done in TypeLowering.
rdar://148785846
Specifically:
1. I made it so that thunks from caller -> concurrent properly ignore the
isolated parameter of the thunk when calling the concurrent function.
rdar://148112362
2. I made it so that thunks from concurrent -> caller properly create a
Optional<any Actor>.none and pass that into the caller function.
rdar://148112384
3. I made it so that in cases where we are assigning an @Sendable caller to a
non-sendable caller variable, we allow for the conversion as long as the
parameters/results are sendable as well.
rdar://148112532
4. I made it so that when we generate a thunk from @execution(caller) ->
@GlobalActor, we mangle in @GlobalActor into the thunk.
rdar://148112569
5. I discovered that due to the way we handle function conversion expr/decl ref
expr, we were emitted two thunks when we assigned a global @caller function to a
local @caller variable. The result is that we would first cast from @caller ->
@concurrent and then back to @caller. The result of this would be that the
@caller function would always be called on the global queue.
rdar://148112646
I also added a bunch of basic tests as well that showed that this behavior was
broken.
To ensure that dependent values have a persistent-enough memory representation
to point into, when an immutable binding is referenced as an addressable
argument to a call, have SILGen retroactively emit a stack allocation and
materialization that covers the binding's scope.
To ensure that dependent values have a persistent-enough memory representation
to point into, when an immutable binding is referenced as an addressable
argument to a call, have SILGen retroactively emit a stack allocation and
materialization that covers the binding's scope.
Revisit the optimization that provides a fast path for instances of
`NSError` when erasing the `Error` type in `emitExistentialErasure`. It
generated references to `NSError` when the `Foundation` module was
loaded, no matter how it was imported. This lead to deserialization
failures at reading the swiftmodule when that reference was added to
inlinable code while `Foundation` was not a public dependency.
Fix this crash by limiting the optimization to all non-inlinable code
and only inlinable code from a module with a public dependency on
`Foundation`. This is the similar check we apply to user written
inlinable code, however here we use the module-wide dependency instead
of per file imports.
rdar://142438679
This attribute makes it so that a parameter of the annotated type, as well as
any type structurally containing that type as a field, becomes passed as
if `@_addressable` if the return value of the function has a dependency on
the parameter. This allows nonescapable values to take interior pointers into
such types.
the async self-isolated actor initializer case.
Fixes rdar://138394497, a bug where we didn't set up isolation correctly for
an async parameter-isolated initializer, but also probably a non-trivial number
of other latent differences between initializers and normal functions.
When the CoroutineAccessors feature is enabled, `begin_apply`
instructions produce an additional result representing the allocation
done by the callee. Fix a couple of cases where this additional result
was not being handled.
This requires two major changes.
The first is that we need to teach SILGen that the isolation of an initializer
is essentially dynamic (as far as SILGen is concerned) --- that it needs to emit
code in order to get the isolation reference. To make this work, I needed to
refactor how we store the expected executor of a function so that it's not
always a constant value; instead, we'll need to emit code that DI will lower
properly. Fortunately, I can largely build on top of the work that Doug previously
did to support #isolation in these functions. The SIL we emit here around delegating
initializer calls is not ideal --- the breadcrumb hop ends up jumping to the
generic executor, and then DI actually emits the hop to the actor. This is a little
silly, but it's hard to eliminate without special-casing the self-rebinding, which
honestly we should consider rather than the weirdly global handling of that in
SILGen today. The optimizer should eliminate this hop pretty reliably, at least.
The second is that we need to teach DI to handle the pattern of code we get in
delegating initializers, where the builtin actually has to be passed the self var
rather than a class reference. This is because we don't *have* a class reference
that's consistently correct in these cases. This ended up being a fairly
straightforward generalization.
I also taught the hop_to_executor optimizer to skip over the initialization of
the default-actor header; there are a lot of simple cases where we still do emit
the prologue generic-executor hop, but at least the most trivial case is handled.
To do this better, we'd need to teach this bit of the optimizer that the properties
of self can be stored to in an initializer prior to the object having escaped, and
we don't have that information easily at hand, I think.
Fixes rdar://87485045.
For synchronous isolated closures passed to unsafe APIs
(the ones that have not been fully concurrency checked)
emit an expected executor check in prolog that would make
sure that they are always used in the expected context.
Resolves: rdar://133415157