[Pitch] Global actors

Yes, it's another effect system. The good news is that we know how to integrate these; the bad news is that we've already added two of them as part of concurrency (async and @Sendable).


1 Like

Yes async adds a new effect for sure. Definitions may vary, but I don’t personally consider @Sendable to be an effect. Sendable checking is just type checking of values through protocol conformance checks, it doesn’t have the same nature and transitive infection properties as effect systems (which apply to function like decls, not to types). Similarly, “mutable” is not an effect, it is a type qualifier for self with special syntax because the self decl is implicit.

When comparing the proposed global actor effect system thing to the two existing effect systems (throws and async) in Swift, you can see that this would be a novel/different/unusual beast:

  • the existing effects all have marking (await/try) but this would not.

  • due to marking, the existing effects allow local reasoning about why they are required (and thus have a more predictable api evolution impact), whereas this one models a more nonlocal “calls something that touches a global actor global variable” property

  • the existing effects are sugar for (among other things) a type wrapper on the result of the function (implying a hidden Result or Future type) but this is not

  • the existing effects impact code generation, but this one does not

  • the existing effects were introduced when the corresponding language features were introduced, but this is trying to retroactively improve type checking for a design pattern that goes back to NeXT days. Impact: this will break tons of existing code, instead of allowing progressive adoption over time.

While I can see some attraction of building invasive type system support for modeling this sort of stuff, I don’t see how it is particularly related to the other parts of the swift concurrency model. I think huge progress would be made by making this sort of legacy code memory safe by /dynamically/ detecting that a tagged global is accessed from the wrong context/thread, and forgo static checking, type system extensions, and the massive api auditing, annotation, and api evolution problems that such things would bring with it.


1 Like

Perhaps a compiler flag allowing to opt out of global actors (or just MainActor) could be an option? I think most projects would really prefer doing the work to move to MainActor. It just seems to be such a huge improvement to me.

I'm currently trying to fix main thread access of some central properties in my project. Without the help of a static analysis tool it's an enormous task. I cannot just add asserts as I cannot be sure to actually exercise all code paths. I for one would really like compile-time checked MainActors :grinning_face_with_smiling_eyes:

I think this proposal looks good. There is on thing, I am wondering about:

For my iOS apps, I use the rule to always use the main thread unless there is a performance issue. In a world after global actors are implemented, this would probably mean tagging (almost) every type and global property with @MainActor. I can imagine that this could be tedious to write and that all these @MainActor could distract from the important bits of code.

Therefore, I have been wondering if it would be a good idea to be able to define a default global actor for a module. This would mean that the default global actor would apply to every global definition unless it is tagged with nonisolated or another global actor.


You mean most of your code isn’t in a view controller subclass?! :wink:

1 Like
Terms of Service

Privacy Policy

Cookie Policy