Skip to content

Commit 4cbb121

Browse files
committed
Fill out the source compatibility section.
1 parent 5c48918 commit 4cbb121

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

proposals/NNNN-async-function-isolation.md

+32-8
Original file line numberDiff line numberDiff line change
@@ -814,16 +814,40 @@ Objective-C header for a function to be imported as an `@concurrent` function.
814814

815815
## Source compatibility
816816

817-
TBD
817+
This proposal changes the semantics of existing nonisolated async functions.
818+
Adopting the semantics to run on the caller's actor for an existing nonisolated
819+
async function also has minor source compatibility impact if the implementation
820+
calls an `@concurrent` function and passes non-Sendable state in the actor's
821+
region.
822+
823+
To avoid breaking source compatibility or silently changing behavior of
824+
existing code, this change will be gated behind an upcoming feature flag.
825+
However, unlike most other changes gated behind upcoming feature flags, this
826+
change allows writing code that is valid with and without the upcoming feature
827+
flag, but means something different. Many programmers have internalized the
828+
SE-0338 semantics, and making this change several years after SE-0338 was
829+
accepted creates an unforuntate intermediate state where it's difficult to
830+
understand the semantics of a nonisolated async function without understanding
831+
the build settings of the module you're writing code in. To mitigate these
832+
consequences, we can introduce an explicit attribute for running an async
833+
function on the caller's actor, and start emitting warnings in all language
834+
modes that do not enable this upcoming feature to explicitly specify the
835+
execution semantics of a nonisolated or unspecified async function.
836+
837+
For example, the attribute could be spelled `@execution(concurrent)` or
838+
`@execution(caller)`. Without the upcoming feature enabled, the compiler
839+
will warn if neither attribute is specified on a nonisolated or unspecified
840+
async function. With the upcoming feature enabled, the default for a
841+
nonisolated or unspecified async function is `@execution(caller)`.
818842

819843
## ABI compatibility
820844

821-
**Open question.** I'm still figuring out whether this change can be staged in
822-
while preserving ABI for existing nonisolated async functions while also
823-
preserving source compatibility. A number of APIs in the concurrency library
824-
have transitioned to inheriting the isolation of the caller using isolated
825-
parameters and `#isolation`, and it may be possible to do this transformation
826-
automatically for resilient libraries.
845+
Adopting the semantics to run on the caller's actor for an existing nonisolated
846+
async function is an ABI change, because the caller's actor must be passed as
847+
a parameter. However, a number of APIs in the concurrency library have staged
848+
in similar changes using isolated parameters and `#isolation`, and it may be
849+
possible to offer tools to do this transformation automatically for resilient
850+
libraries that want to adopt this behavior.
827851

828852
For example, if a nonisolated async function is ABI-public and is available
829853
earlier than a version of the Swift runtime that includes this change, the
@@ -845,7 +869,7 @@ internal func abi_myAsyncFunc() async {
845869
}
846870
```
847871

848-
However, this transformation only works if the original function implementation
872+
This transformation only works if the original function implementation
849873
can be made inlinable.
850874

851875
## Implications on adoption

0 commit comments

Comments
 (0)