Open inamiy opened 1 year ago
I'd ague this is correct; the Actor
protocol specifically is designed to NOT be implemented by anything else than implicitly by an actor
declaration. Allowing this would muddy the waters quite a bit and I don't think "just" allowing this would even be correct -- there is no synthesized unowned executor in such global actor conforming class type etc.
To share some more context, I wanted to abstract @MainActor class MyService
with protocol Service: Actor
so that caller can only reference any Service
without knowing its impl is running on MainActor or just a plain actor.
Of course this problem can be solved by having a different protocol without conforming to Actor
and instead let all methods turn into async
, but I personally find this a bit too abstract.
For example:
protocol Service: Actor {
var state: State { get }
func fetch() async // this async comes from network
}
will be turned into async
methods if not conforming to Actor
:
protocol Service {
var state: State { get async } // this async comes from actor
func fetch() async // this async comes from both network & actor
}
So, asynchrony from both network & (local) actor are merged as a single async
in the latter, which makes readability a bit obscure and too abstract (which can also be used for non-actors as well).
@ktoso
If I understand correctly, a class with @globalActor
can be considered as referencing globalActor's executor?
@MainActor class MyService { ... }
// We can assume this is synthesized
extension MyService: Actor {
nonisolated var unownedExecutor: UnownedSerialExecutor {
MainActor.shared.unownedExecutor
}
}
Description
or more shortly:
Expected behavior
@MainActor class
(or any global-actor-ed class) should be treated asActor
.Side note: Although we can use
async
-ed protocol version as below, we still want to allowprotocol P: Actor
style too.Environment
Additional context https://twitter.com/inamiy/status/1603652396294410240