After the pushback we’re seeing in this thread from @Douglas_Gregor and @ktoso, I’m trying to switch my point of view, to evaluate — and see if I can embrace — their apparently exclusively global-actor-based conceptualization of serial-execution contexts.
In that regard, I’m confused on a couple of points, where I can’t find adequate clarification in the proposals. It may be there, but I can’t find it.
Consider an actor:
actor MyActor {
func dataFromNetwork() async -> Data { … }
func doStuff() async {
let data = await dataFromNetwork()
…
}
}
I can’t find anything in the Actors proposal that’s very explicit about this, but I assume that dataFromNetwork — apart from its asynchronous portions, such as making a network request, that might run on an execution context outside the actor — will execute its synchronous portions and returns its result in MyActor’s execution context. Is that correct?
Now let’s change doStuff like this:
func doStuff() async {
async let data = await dataFromNetwork()
…
}
According to my reading of the Async Let proposal, this would produce a compilation error, because it would be attempt to invoke an isolated function (dataFromNetwork) from a non-isolated closure. The proposal says:
The initializer of the async let can be thought of as a closure that runs the code contained within it in a separate task [… and …] the closure is @Sendable and nonisolated.Is that the intended behavior inside an actor? Or does `dataFromNetwork` actually begin and end running in the MyActor execution context in this scenario?
If the answer to that question is “yes”, I think I can embrace this approach, even though I’m not thrilled with the idea that actors are the only way to manage Swift concurrency in serial-execution contexts.
(In contrast, the basic structured concurrency proposals have a rich-enough set of concepts and APIs to manage Swift concurrency in concurrent-execution contexts, aside from any considerations of actors.)