I'm personally quite torn, because a function inheriting the actor feels more intuitive, and I agree with all of the usability concerns in the Motivation section. At the same time, I think that purely techincally having more functions that default to the global executor is the more correct default for most programs, as actor-isolated functions should be few and far between in the first place. As also evident in the examples, the functions that'd really benefit from sticking to the actor are the "generic data structure-y" ones, which are more common in libraries, but less so in application code.
I vaguely remember reading somewhere in the earliest proposals/threads on Concurrency that "a function always chooses its own isolation". The SE-0338 behaviour represents this to me: being non-isolated (even if not explicitly spelled out through nonisolated
) in this case is a specific choice rather than the lack of one.
If "a function always chooses its own isolation" is a good paradigm, I think the problem is not which of the two modes is the better default (so far in my experience, I'd required both of them with pretty much equal frequency), but the fact that there should be three modes that we talk about:
- isolated
- non-isolated (aka "always runs on global executor)
- "do not care"/"happy to inherit"
I think that the lack of an option to explicitly express the latter distinction is the crux of the problem; moreso to do it uniformly (as proposed, we'll end up with a mix of both a parameter keyword and an attribute).
Not blocking an actor is a very legitimate reason for a function to strongly insist on running on the global executor; but so is the intent to not hop off an actor, and I think they should have ideally received the same treatment and syntax.
Perhaps there is still an opportunity to explore this direction?
Edit: as a bikesheddable proposition, I'd consider spellings like nonisolated(strict)
/nonisolated(always)
on the one hand and nonisolated(inherit)
on the other — or something similar. Whichever becomes the default, it'd at most be a redundant annotation (like the internal
visibility qualifier), but still leaves the option to be explicit about the choice regardless.
The nonisolated
proper could become deprecated, and the compiler could provide a fixit to annotate all current functions that behave in accordance to SE-0338 with nonisolated(always)
.