A common point of confusion that I see is people not understanding why protocols with a global actor attribute don't implicitly refine Sendable. The reason why protocols with global actor attributes don't automatically refine Sendable is because the global actor isolation is not a requirement of the conforming type. The global actor attribute on a protocol has two effects:
- It applies isolation to all protocol requirements unless otherwise annotated
- It's a default inference source for conforming types, but conforming types can opt out of this isolation, and the isolation inference does not apply if the conformance is written in an extension (possibly outside the module)
There's no requirement that the conforming type actually be global actor isolated, so it's not the case that all conforming types are Sendable by definition. A protocol requiring Sendable should be done carefully -- only if the generic code that uses the protocol as a conformance constraint actually needs it -- because a Sendable requirement forces conformances to implement a thread-safe type, which might be difficult if the type is not global actor isolated.
Similar reasoning applies to SendableMetatype, which is restrictive because it prevents things like isolated conformances, and should be required only when the generic code needs to use the metatype concurrently. It is possible to have an isolated conformance to a protocol that has a global actor attribute if one of the protocol requirements is marked nonisolated:
@MainActor protocol MyProtocol {
func a()
nonisolated func b()
}
You could have a concrete type that conforms to MyProtocol where the implementation of b is main actor isolated. MyProtocol implicitly refining SendableMetatype would prevent this. Obviously this is super contrived, but I've seen use cases where a protocol wants conformances to be able to be main actor isolated by default, but also wants to support concurrently invoking protocol requirements only if the conforming type opted into it by implementing the requirements as nonisolated methods.
Does this explanation make sense?