@@ -814,16 +814,40 @@ Objective-C header for a function to be imported as an `@concurrent` function.
814
814
815
815
## Source compatibility
816
816
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) ` .
818
842
819
843
## ABI compatibility
820
844
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 .
827
851
828
852
For example, if a nonisolated async function is ABI-public and is available
829
853
earlier than a version of the Swift runtime that includes this change, the
@@ -845,7 +869,7 @@ internal func abi_myAsyncFunc() async {
845
869
}
846
870
```
847
871
848
- However, this transformation only works if the original function implementation
872
+ This transformation only works if the original function implementation
849
873
can be made inlinable.
850
874
851
875
## Implications on adoption
0 commit comments