Commit Graph

68 Commits

Author SHA1 Message Date
Michael Gottesman
d1e3dfe5c9 [silgen] Look through conversions that combine a Sendable and nonisolated(nonsending) conversion.
These conversions are artificial conversions inserted by Sema since isolation is
not represented on interface types. We previously looked though:

1. A single conversion that added nonisolated(nonsending).
2. A two level conversion where the first conversion added Sendable and the
second added nonisolated(nonsending).

In this case, Sema is generating a single conversion that combines the Sendable
and isolation conversion.

To be consistent, I also updated the code that involved conversion from
execution caller to global actor as well in case we hit the same case there.

https://github.com/swiftlang/swift/issues/83812
rdar://158685169
2026-01-15 13:29:21 -08:00
Pavel Yaskevich
df109f857b [AST] ASTPrinter: Don't attempt to print nonisolated(nonsending) on non-function parameters
Don't look through sugar when checking whether to print
`nonisolated(nonsending)` in parameter positions, because
underlying types would already be marked appropriately
and parameters themselves doesn't require the modifier
transfer even when the sugar is stripped.

Resolves: rdar://167050741
2026-01-06 15:16:12 -08:00
Pavel Yaskevich
e819c9fcfe [Concurrency] NonisolatedNonsendingByDefault: Turn inferred nonisolated into nonisolated(nonsending)
Inferred `nonisolated` from the context i.e. an extension should
mark the member as `@concurrent` instead it should behave as
`nonisolated(nonsending)` when `NonisolatedNonsendingByDefault`
is enabled.

Resolves: rdar://157789572
2025-12-19 17:28:13 -08:00
Pavel Yaskevich
d6ffad06e1 [Tests] NFC: Add a test-case for https://github.com/swiftlang/swift/issues/84509
Looks like the issue has been fixed already, so adding a
test-case to make sure that it doesn't regress in the future.

Resolves: https://github.com/swiftlang/swift/issues/84509
Resolves: rdar://161307898
2025-12-04 13:39:07 -08:00
Pavel Yaskevich
cfb11a3f4d [SILGen] Account for an implicit isolation parameter while emitting native->foreign thunk arguments
This is an "off-by-one" error because the code to emit bridged
arguments didn't account for the fact that "native" function
type can have a leading implicit isolation parameter if declaration
is `nonisolated(nonsending)`.

Resolves: rdar://164561176
2025-11-24 10:59:00 -08:00
Pavel Yaskevich
2335293f0d [Concurrency] Allow transferring nonisolated(nonsending) to isolation boundary closures
Isolation boundary closures don't assume parent isolation and should
be able to get `nonisolated(nonsending)` transferred to them jus
like regular nonisolated closures do.

Resolves: rdar://163792371
2025-11-19 14:56:40 -08:00
Pavel Yaskevich
8ea8a99e99 [AST] Make sure that nonisolated(nonsending) works together with @autoclosure 2025-11-10 11:31:24 -08:00
Pavel Yaskevich
c3ea3031b9 [AST] Fix printing of nonisolated(nonsending) in parameter type positions
Printing shouldn't rely on parameter declaration bit because it only
works in cases when there is an explicit `nonisolated(nonsending)`
modifier on the type.

Always print `nonisolated(nonsending)` before `sending`, `@escaping`
and other declaration attributes/modifiers to avoid parsing issues.

Resolves: rdar://164267736
2025-11-10 11:31:24 -08:00
Pavel Yaskevich
9f7d31e118 [AST] NonisolatedNonsendingByDefault: Print @concurrent on nonisolated async function types
With the feature enabled any function type without an explicit `@concurrent`
is going to be inferred to be `nonisolated(nonsending)`. `@concurrent` should
always be printed for diagnostic and other purposes because the isolation
checking would consider them to be `nonisolated(nonsending)` otherwise, especially
important to code produced by fix-its.

Resolves: rdar://161739470
2025-11-03 09:13:02 -08:00
Michael Gottesman
dc193063cf Test updates for previous commit. 2025-10-16 10:52:05 -07:00
Michael Gottesman
81885a67d0 [silgen] Change two places we used Builtin.Executor to instead use Optional<any Actor> as an expected executor.
We want SILGen to have a simplified view of its executor and know that whenever
one sees an Actor, it is an actual actor instead of a Builtin.Executor. This
just simplifies code. Also, we should eventually have an invariant that
Builtin.Executor should only be allowed in LoweredSIL after LowerHopToExecutor
has run. But that is a change for another day.
2025-10-16 10:51:13 -07:00
Pavel Yaskevich
ce3310050b [Concurrency] Prevent extraneous sendability checking when applying nonisolated(nonsending)
`nonisolated(nonsending)` is not presented in interface types
which means that references to declarations that have this attribute
require a function conversion to apply it. Function conversion
checking should detect that and avoid sendability checking for
situations like that but there is really no conversion there.
2025-09-19 14:13:28 -07:00
Pavel Yaskevich
40c9674dfd [Concurrency] Avoid Sendable checking for conversions that strip @Sendable from nonisolated(nonsending) function type
The isolation doesn't change in this cause and making function type
non-Sendable means that it woun't be able to leave the current concurrency
domain and the compiler won't generate a thunk.
2025-09-19 13:42:08 -07:00
Pavel Yaskevich
3ae34e8e68 [Concurrency] Fix @Sendable closures not inferring nonisolated(nonsending)
If there are no explicit concurrency attributes, isolated parameters,
or captures associated with the closure it should infer `nonisolated(nonsending)`
for the parent conversion injected by the solver (this conversion is injected
because the solver cannot check captures to elide it).

The change pushes `isIsolationInferenceBoundaryClosure` check down
with added benefit of getting preconcurrency context from the parent.
2025-09-04 16:51:45 -07:00
Michael Gottesman
c085cb77e4 Merge pull request #83405 from gottesmm/pr-fc0af1c444a7961af452c813a9bdc4cc2b5adbd8
[concurrency] Emit nonisolated(nonsending) async throw initializers correctly
2025-07-31 16:27:55 -07:00
Michael Gottesman
3871d22257 [concurrency] Emit nonisolated(nonsending) async throw initializers correctly.
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
2025-07-29 19:15:08 -07:00
John McCall
92b9857e6a 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:20:38 -04:00
Michael Gottesman
0da22388cb [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-18 10:08:21 -07:00
Pavel Yaskevich
358869ff54 [Concurrency] NonisolatedNonsendingByDefault: Extend nonisolated(nonsending) to _openExistential
`_openExistential` is type-checked in a special way which
means that we need to explicitly inject `nonisolated(nonsending)`
isolation when forming a reference to this builtin.
2025-07-17 17:35:12 -07:00
Pavel Yaskevich
48f4d7b688 [Concurrency] NonisolatedNonsendingByDefault: Extend nonisolated(nonsending) to withoutActuallyEscaping
`withoutActuallyEscaping` is type-checked in a special way which
means that we need to explicitly inject `nonisolated(nonsending)`
isolation when forming a reference to this builtin.
2025-07-17 17:35:08 -07:00
Anthony Latsis
d7ec3a34bb Merge pull request #83094 from swiftlang/jepa-main
Sema: Make `@concurrent` not imply `async` on closures
2025-07-17 01:54:04 +01:00
Anthony Latsis
58d5059617 Sema: Make @concurrent not imply async on closures
The present approach is not prudent because `@concurrent` synchronous
functions, a natural extension, are a likely-to-happen future direction,
whereas the current inference rule is entirely grounded on `@concurrent`
being exclusive to async functions.

If we were to ship this rule, we would have to keep the promise for
backwards compatibility when implementing the aforementioned future
direction, replacing one inconsistency with another, and possibly
introducing new bug-prone expression checking code.

```swift
func foo(_: () -> Void) {}
func foo(_: () async -> Void) {}

// In a future without this change and  `@concurrent` synchronous
// functions accepted, the first call resolves to the first overload,
// and the second call resolves to the second, despite `@concurrent` no
// longer implying `async`.
foo { }
foo { @concurrent in }
```

This change also drops the fix-it for removing `@concurrent` when used
on a synchronous closure. With the inference rule gone, and the
diagnosis delayed until after solution application, this error raises a
fairly balanced choice between removing the attribute and being
explicit about the effect, where a unilateral suggestion is quite
possibly more harmful than useful.
2025-07-16 20:46:29 +01:00
Pavel Yaskevich
a28d065893 Merge pull request #83056 from xedin/rdar-155847011
[Concurrency] Replace `nonisolated` with `nonisolated(nonsending)` wh…
2025-07-15 10:08:00 -07:00
Pavel Yaskevich
b519c07428 [Concurrency] Replace nonisolated with nonisolated(nonsending) when isolation is inferred
With `NonisolatedNonsendingByDefault` an explicit `nonisolated`
attribute in declaration context is inferred to mean `nonisolated(nonsending)`
and it should be printed as such in interface files and other places.

The inference logic that did didn't remove the original attribute
which meant that it would be printed twice i.e.
`nonisolated nonisolated(nonsending) func test() async` which is
incorrect and would fail swift interface validation.

Resolves: rdar://155847011
2025-07-15 00:42:53 -07:00
Pavel Yaskevich
ace6f738ba [Serialization] Move nonisolated(nonsending) isolation kind above global actor one
Global actor kind also appends type offset that indicates what
global actor to use with the type. All of the isolation kinds
should be placed above it to make sure that there is never a
clash when i.e. `MainActor` is serialized as id `1`.

Resolves: rdar://153487603
2025-07-14 14:24:08 -07:00
Michael Gottesman
ea4d0440f4 Revert "[Concurrency] Prevent use of nonisolated(nonsending) and @concurrent on @_inheritActorContext parameters"
This reverts commit e032f33cfb.
2025-07-10 11:15:00 -07:00
Michael Gottesman
648bb8fe30 [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
2025-07-07 17:21:41 -07:00
Pavel Yaskevich
e032f33cfb [Concurrency] Prevent use of nonisolated(nonsending) and @concurrent on @_inheritActorContext parameters
`@_inheritActorContext` is a form of isolation which precludes
direct use of inference of `nonisolated(nonsending)` and `@concurrent`
just like other isolation attributes/modifiers would i.e. `isolated`
or `@isolated(any)`.
2025-07-07 17:21:41 -07:00
Pavel Yaskevich
bb0cd6f0a6 [Concurrency] SE-0461: Extend nonisolated(nonsending) inference to function types
Currently only declarations would get `nonisolated(nonsending)`
inferred if the upcoming flag is enabled, this changes extend
this to apply to asynchronous nonisolated function types as well.

Resolves: rdar://154808850
2025-07-02 12:12:06 -07:00
Slava Pestov
9033198674 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-27 10:56:12 -04:00
Pavel Yaskevich
25585c07f3 Merge pull request #82386 from xedin/rdar-153922620
[Concurrency] References to `nonisolated(nonsending)` properties don't…
2025-06-23 13:38:09 -07:00
Pavel Yaskevich
35a41ab9cf [Concurrency] References to nonisolated(nonsending) properties don't leave caller's isolation
Make sure that referencing `nonisolated(nonsending)` properties,
especially through a witness is as not treated as leaving the
isolation domain of the caller.

Resolves: rdar://153922620
2025-06-20 15:26:42 -07:00
Pavel Yaskevich
a964282275 [Concurrency] Don't infer nonisolated(nonsending) on synchronous witnesses
If the requirement is `nonisolated(nonsending)` but witness is
synchronous, prevent actor isolation inference from requirements
because this isolation only applies to asynchronous declarations
at the moment.

Resolves: rdar://153680826
2025-06-20 10:14:05 -07:00
Pavel Yaskevich
1457aecc87 [Tests/NFC] NonisolatedNonsendingByDefault: Rename adoption_mode.swift test into migration_mode.swift 2025-06-11 00:11:00 -07:00
Pavel Yaskevich
bcd6caaea4 [Concurrency] NonisolatedNonsendingByDefault: Migration applies only to the current module declarations
Prevent migration from handling declarations that come from a
module different from the current one, this is primarily a
problem for swiftinterfaces that can get rebuilt when the module
is imported by a model that has migration mode enabled.

Resolves: rdar://152687353
2025-06-11 00:06:38 -07:00
Pavel Yaskevich
55b29fea4b Merge pull request #81690 from xedin/rdar-151797372
[CSApply] Don't inject global actor into closure type if it's marked …
2025-05-22 09:33:36 -07:00
Pavel Yaskevich
efc6efc4ed [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
2025-05-21 15:22:03 -07:00
Anthony Latsis
eedc774fca InFlightDiagnostic: Minor improvement to fixItAddAttribute
Do not follow `in` keyword with a space unless the first token inside
the body begins with the next char after `{`.
2025-05-21 12:11:19 +01:00
Anthony Latsis
2d7e040d4d Sema: Fix an issue with NonisolatedNonsendingByDefault migration for closures
See the inline comments for more details. Depending on the closure's
type signature, sometimes adding the attribute will break code. Fix this
by also adding inferred effects to the signature in these cases.
2025-05-20 08:18:33 +01:00
Michael Gottesman
abcc134621 Merge pull request #81542 from gottesmm/rdar150209093_rdar151394209
[concurrency] Fix a few issues around not emitted correct protocol witness and vtable thunks for nonisolated(nonsending)
2025-05-19 10:43:18 -07:00
Anthony Latsis
f4e49d5a0a Sema: Fix UB in NonisolatedNonsendingByDefault migration diagnosis
The diagnostic can outlive the locally constructed attribute, which was
passed by pointer, if there is an active `DiagnosticTransaction`.
2025-05-16 21:13:08 +01:00
Anthony Latsis
4313f8f262 Merge pull request #81538 from AnthonyLatsis/pinus-sibirica
AST, Sema: Fix 2 `NonisolatedNonsendingByDefault` bugs
2025-05-16 09:42:52 +01:00
Michael Gottesman
ef23f97071 [silgen] Teach SILGen how to handle nonisolated(nonsending) thunking for vtables
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
2025-05-15 14:11:55 -07:00
Michael Gottesman
39a013f807 [silgen] Place the correct isolation on protocol witness thunks.
We were using the isolation from the witness not from the requirement which we
are supposed to do. The witness thunk thunks the isolation from the requirement
to the witness so from an ABI perspective it should have the interface implied
by the requirement's isolation since that is what callers of the witness method
will expect.

rdar://151394209
2025-05-15 14:11:55 -07:00
Anthony Latsis
bee2b6778e TypeCheckType: Do not emit migration mode diags if nonisolated(nonsending) is explicit
This broke when we split `@execution(...)` into `@concurrent` and
`nonisolated(nonsending)` because the latter became its own `TypeRepr`,
whereas the condition for whether to attempt migration diagnostics
inside `resolveASTFunctionType` is still based on the function type's
attributes alone.
2025-05-15 20:18:28 +01:00
Anthony Latsis
d90c7cb57a DiagnosticEngine: Fix attribute insertion location for closures with capture lists 2025-05-15 20:17:42 +01:00
Pavel Yaskevich
a8c538937a Merge pull request #81418 from xedin/rdar-130168104
[Concurrency] Diagnose loss of global actor isolation in async functi…
2025-05-15 01:00:43 -07:00
Pavel Yaskevich
37e2f374aa [CSApply] Don't attempt to mark autoclosures as non-implicit
While building an initializer call the declaration reference
should have the same implicitness as the call when it doesn't
require thunking, otherwise don't attempt to mark autoclosures
as non-implicit because it could break assumptions elsewhere.
2025-05-09 14:43:48 -07:00
Pavel Yaskevich
a058ffc998 [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
2025-05-09 13:05:57 -07:00
Pavel Yaskevich
ef65f26457 [Concurrency] Account for explicit @concurrent on closures
If closure is stated as `@concurrent` is has to be treated as
nonisolated.

Resolves: rdar://150397825
2025-04-30 20:25:32 -07:00