Having tried to imagine how my feature request could be implemented, I think I understand now. A strict sub-typing relation is required when the compiler nicely considers a "sendable variant" of the explicit type during the assignment:
// â
Compiler knows that `any Sendable`
// is a subtype of `Any`, so this can fly:
static let x: Any = 1
// â
Compiler knows that `[any P & Sendable]`
// is a subtype of `[any P]`, so this can fly:
static let x: [any P] = [1]
// â Compiler does not consider `MyContainer<any P & Sendable>`
// as a subtype of `MyContainer<any P>`, so a warning is required:
static let x: MyContainer<any P> = MyContainer(value: 1)
If I'm correct, I'd understand the hesitation of the Swift team to hard-code more special cases for arrays, dictionaries, optionals, etc.
How I was imagining the implementation
Considering a general assignment as below:
static let x: [type] = [expression]
The compiler could run the following algorithm when determining if there is a Sendable violation or not. Of course I'm not familiar with the compiler internals, and I'm probably violating many compiler layers - please bear with me: I just want to outline the principles of a possible solution.
For all conditional conformances of [type] to Sendable:
Derive a [sendable subtype] from [type] and the conditional conformance.
Can [expression] be assigned to a value of type [sendable subtype], without changing the type of literals?
Yes -> return "no warning"
No -> continue
Return "warn about Sendable violation"
Let's consider a first positive example:
static let x: [Any] = [1]
From conditional conformance of Array
to Sendable
when Element
conforms to Sendable
, consider the subtype [any Sendable]
.
Lock 1
to Int
because Int
fits Any
.
static let x: [any Sendable] = [1 as Int]
is valid -> no warning.
And now consider a negative example:
protocol P { }
protocol Q: P { }
struct MyContainer<T> {
init(value: T) { ... }
}
extension MyContainer: Sendable where T == any Q { }
extension Int: P { }
extension Int64: P, Q { }
static let x: MyContainer<any P> = MyContainer(value: 1)
From conditional conformance of MyContainer
to Sendable
when T
is any Q
, consider the subtype MyContainer<any Q>
(
TODO: prove the subtype relation).
Lock 1
to Int
because Int
fits any P
.
static let x: MyContainer<any Q> = MyContainer(value: 1 as Int)
is not a valid assignment -> Sendable violation warning.