An ActorContext
is modeling what your pitch calls a "global actor" in the type system. My design would have UIActorContext
instead of @UIActor
. An "actor" would be a class instance that lives within the rules of the actor system. An "actor context" would be the serialization context in which actor instances can run.
This distinction is already latent in your design where actors that are annotated with @UIActor
live in a shared serialization context. I think it's useful to make it explicit.
I recall hearing of or reading about an actor system that had a similar notion. They called it a "vat" - a vat could have many actors in it and it provided a serialization context for all of those actors, allowing code to take advantage of the knowledge that this context is shared. I haven't been able to dig up any references on this, but have used the idea in my own code and found it very useful. This allows you to have some control over (and often reduce) the granularity of serialization boundaries.
The reason I introduced the actor context protocols is to allow Never
to be used as an ActorContext
that means “no shared context, each instance has its own queue”. If we didn’t need to do that (or if we had !=
constraints) we wouldn’t need the context protocols.
The programming model is not that different from yours in terms of conceptual or syntactic weight:
@globalActor
struct MyGlobalActor { }
@MyGlobalActor
actor class MyActor {}
vs
struct MyGlobalActorContext: GlobalActorContext { }
actor class MyActor: GlobalActor {
typealias ActorContext = MyGlobalActorContext
}
It’s slightly more verbose, but has all of the advantages that come with working within the existing language and type system. I think magic attributes make sense in some cases, but not when a protocol-based design is both possible and useful without imposing a meaningful burden on less experienced programmers (i.e. without violating the principle of progressive disclosure).