Thanks for bringing this up. A couple of thoughts, as always...
First of all, I'm not sure if you realized this in writing our document, but two of the three parts of our "Proposed Solution" are already a part of the actors pitch:
- Your proposed "global actor variables" are already part of global actors already. The bit about accessing global state asynchronously would follow from the change to allow non-
async
actor declarations to be accessed asynchronously, a suggestion that will come in a revised version of the asynchronous functions pitches. - Your proposed "process global variables" are already part of the actors pitch, spelled
@actorIndependent(unsafe)
.
So the fundamental contribution of this proposal is to have global variables that aren't marked with one of the above implicitly become lazily-initialized actor instance members. While I agree that this is a source-compatible change in the sense that all code is non-actor code today and won't change behavior, I have major concerns with this proposal.
I think the end result of this proposal isn't where we want Swift to be. If we wanted to add a feature where one could add lazily-initialized instance data to an actor (or to any class, a la associated objects), I cannot imagine us doing so by declaring the variable at module scope. As Kavon noted, this is a confusion of global vs. local. If we were to add this feature, it would allow stored properties to be declared with initializers in an extension
extension SomeReferenceType {
var myCounter: Int = 0
}
A much better end state would be to have every global variable marked as either being part of a global actor or being marked as @actorIndependent(unsafe)
. I think we can get there in two phases: require one of these annotations for all global variables that are referenced from asynchronous code (therefore, only new code is affected, and source compatibility is maintained) in "phase 1", and have "phase 2" require such annotations for all global variables.
Doug