I think there's a bit of a disconnect here. MyClass
is Sendable
which can be observed by the fact that you're able to call doThing()
asynchronously:
func accessValue() async {
await value.doThing()
}
MyClass
achieves sendability by virtue of the fact that it is @MainActor
isolated. Being isolated to the main actor ensures that access to all mutable state is synchronized.
It seems like the misunderstanding here is an interpretation of Sendable
as meaning something like "free to be shared across isolation domains with no change in behavior" which is roughly what is achieved by, say, Int
, where you can copy it freely between isolation domains and everywhere it goes it's 'just' an Int
. But Sendable
is more broad than that. Sendable
also encompasses types which can be moved across isolation domains because they internally manage any access to their mutable state. This is why global-actor-isolated types (as well as actor
s) may be shared across isolation domains: the language enforces that any calls 'into' their members will actually hop into the corresponding isolation domain. I really recommend reading the full docs for the Sendable
protocol, they're pretty thorough.
Now, I think we could still potentially warn when a global-actor-isolated or actor
type notes a Sendable
conformance (since it's redundant), but I'm not totally sold. I think it would be reasonable for programmers to adopt a style where all conformances are noted explicitly, even if they'd otherwise be implicit (such as with Sendable
).
Nonetheless:
I do think this is good feedback about how we teach Sendable
, as well as a very good argument for adopting the proposal you've linked. You're right that not all Sendable
types are treated equally by the language. There is one such confusion about Sendable
's interaction with global actor isolation that went up just a few hours ago!