+1. Currently non-Sendable types are effectively generic over isolation, and it makes sense that async methods inside non-Sendable types would be generic over isolation. And not only methods, but pretty much any async functions accepting or returning non-Sendable types.
+1 for preserving attribute in the type system.
However, if the conversion happens on the actor, and the new function type is not
@Sendable, then the function must only be called from the actor. In this case, the function conversion is allowed, and the resulting function value is merged into the actor's region
That's an interesting point. This aligns well with [Pre-pitch] Isolated conformances. +1.
For most calls, the switch upon entering the function will have no effect, because it's already running on the executor of the actor parameter
Are there any cases where switching upon entering will have the effect? If no, should switching upon entering be removed as an optimization?
Note that this introduces a semantic difference compared to synchronous nonisolated functions, where there is no implicit isolated parameter and
#isolationalways expands tonil.
This could solved if runtime would store reference-counted actor references, which was discussed before and rejected. So, I guess, we will have to accept this discrepancy.
If the attribute were spelled
@isolated(caller)and@isolated(concurrent), presumably that attribute would not work together withnonisolated; it would instead be an alternative kind of actor isolation.
Sounds good to me. The fact that @execution(caller)/@isolated(concurrent) are mutually exclusive with isolation attributes, and that there is always one or another present (possibly implicitly), leads me to the conclusion that @execution(caller)/@isolated(concurrent) are indeed isolation attributes.
From the other hand, name @execution() sounds as if it has something to do with the task executors, which it is not.
To avoid having two syntaxes, we could deprecate nonisolated altogether, and use @isolated(caller) on sync functions.
Another plus is that it makes it easier to understand if feature is adopted or not from reading the code.
This increases code churn, but it should be solvable with tooling. I'm not concerned about it.
Also would be nice if tooling could automatically recognise isolation: isolated (any Actor)? = #isolation pattern and replace it with @isolated(caller).
I'm a bit concerned that replacing nonisolated with @isolated(caller) would increase syntax length from 11 characters to 17, but this is well compensated by replacement of isolation: isolated (any Actor)? = #isolation as well (45 characters).