Commit Graph

13 Commits

Author SHA1 Message Date
John McCall
787cca9e37 Rewrite the type of nonisolated(nonsending) closures.
The constraint solver does not reliably give closures a function type
that includes `nonisolated(noncaller)`, even when the immediate context
requires a conversion to such a type. We were trying to work around this
in SILGen, but the peephole only kicked in if the types matched exactly,
so a contextual conversion that e.g. added `throws` was still emitting
the closure as `@concurrent`, which is of course the wrong semantics.
It's relatively easy to avoid all this by just rewriting the closure's
type to include `nonisolated(nonsending)` at a point where we can reliably
decide that, and then SILGen doesn't have to peephole anything for
correctness.

Fixes rdar://155313349
2025-07-28 22:22:54 -04:00
Michael Gottesman
82b0ec3de0 [silgen] Make sure that thunks that convert to/from nonisolated(nonsending) handle hopping correctly.
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
2025-07-17 10:55:59 -07:00
Michael Gottesman
35c3b9e12c [concurrency] Perform some fixes so that transfernonsendable_closureliterals_isolationinference.swift now passes.
The reason why this failed is that concurrently to @xedin landing
79af04ccc4, I enabled
NonisolatedNonsendingByDefault on a bunch of other tests. That change broke the
test and so we needed to fix it.

This commit fixes a few issues that were exposed:

1. We do not propagate nonisolated(nonsending) into a closure if its inferred
context isolation is global actor isolated or if the closure captures an
isolated parameter. We previously just always inferred
nonisolated(nonsending). Unfortunately since we do not yet have capture
information in CSApply, this required us to put the isolation change into
TypeCheckConcurrency.cpp and basically have function conversions of the form:

```
(function_conversion_expr type="nonisolated(nonsending) () async -> Void"
   (closure_expr type="() async -> ()" isolated_to_caller_isolation))
```

Notice how we have a function conversion to nonisolated(nonsending) from a
closure expr that has an isolation that is isolated_to_caller.

2. With this in hand, we found that this pattern caused us to first thunk a
nonisolated(nonsending) function to an @concurrent function and then thunk that
back to nonisolated(nonsending), causing the final function to always be
concurrent. I put into SILGen a peephole that recognizes this pattern and emits
the correct code.

3. With that in hand, we found that we were emitting nonisolated(nonsending)
parameters for inheritActorContext functions. This was then fixed by @xedin in

With all this in hand, closure literal isolation and all of the other RBI tests
with nonisolated(nonsending) enabled pass.

rdar://154969621
(cherry picked from commit 648bb8fe30)
2025-07-10 17:24:48 -07:00
Slava Pestov
7ed5d2bfc2 ASTDemangler: Round-trip @isolated @sil_implicit_leading_param parameter attributes
We sometimes mangle SILFunctionTypes when generating debug info
for reabstraction thunks, and these can have various exotic
parameter and result attributes. Two recent additions were
never plumbed through the mangler, causing assertion failures
when emitting debug info.

Fixes rdar://153730847.
2025-06-26 15:00:44 -04:00
Pavel Yaskevich
b79e922a50 [CSApply] Don't inject global actor into closure type if it's marked as @concurrent
When the attribute is specified explicitly passing a `@concurrent`
closure to a global actor-isolated parameter or contextual type
should result in a conversion and closure itself should be nonisolated.

Resolves: rdar://151797372
(cherry picked from commit efc6efc4ed)
2025-05-22 10:15:39 -07:00
Pavel Yaskevich
1336dd4cb5 [Concurrency] Diagnose loss of global actor isolation in async function conversions
Perform `Sendable` checking on parameter/result of the function
type when conversion between asynchroneous functions results in
a loss of global actor isolation attribute because access would
result in data crossing an isolation boundary.

This is a warning until Swift language mode 6.

Resolves: rdar://130168104
(cherry picked from commit a058ffc998)
2025-05-16 15:21:03 -07:00
Pavel Yaskevich
f50695ba32 [Concurrency] Account for explicit @concurrent on closures
If closure is stated as `@concurrent` is has to be treated as
nonisolated.

Resolves: rdar://150397825
(cherry picked from commit ef65f26457)
2025-05-01 13:08:35 -07:00
Pavel Yaskevich
3c321ec5b4 [SILGen] Concurrency: Fix caller isolated closures to hop to the right actor
Closures that are caller isolated used to still hop to the generic
executor, which is incorrect.

(cherry picked from commit bb62e961b8)
2025-04-18 16:41:34 -07:00
Pavel Yaskevich
134f5def36 [TypeChecker] Allow closures to assume nonisolated(nonsending)
Always infer `nonisolated(nonsending)` from context directly on
a closure unless the closure is marked as `@concurrent`, otherwise
the closure is not going to get correct isolation and going to hop
to the wrong executor in its preamble.

Resolves: rdar://149107104
(cherry picked from commit 3de72c5452)
2025-04-18 16:41:34 -07:00
Pavel Yaskevich
3896f8fd77 [AST] Remove ExecutionAttribute experimental feature
SE-0461 has been accepted and `@concurrent` and `nonisolated(nonsending)`
can be make generally available now.
2025-04-16 13:20:12 -07:00
Pavel Yaskevich
06f880e65c [AST/ASTGen/Sema/Serialization] Remove @execution attribute
Complete the transition from `@execution` to `@concurrent` and `nonisolated(nonsending)`
2025-04-16 13:18:52 -07:00
Pavel Yaskevich
4a973f7b4b [AST/Sema] Replace @execution(concurrent) with @concurrent 2025-04-16 10:06:08 -07:00
Michael Gottesman
769673d002 [concurrency] Implement protocol witness thunking in SILGen for @execution(caller)/@execution(concurrent).
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
(cherry picked from commit 04b845cc97)
2025-04-10 15:38:17 -07:00