I think your example is a good motivation example for Existential subtyping as generic constraint.
For the sake of this discussion, I'm gonna use syntax any P
vs P
to disambiguate between protocol-as-existential vs protocol-as-contraint, but exact syntax is irrelevant.
Image that there is no self-conformance (any Error): Error
. But in the generic signature of the Result
we still want to be able to use any Error
. Signature of enum Result<Success, Failure> where Failure : Error
would not work here. But we can fix this if we introduce another kind of constraint - existential subtyping. I was suggesting syntax where Failure : any Error
. This constraint means that Failure
can be type that conforms to Error
, but also any Error
itself, and other existentials like any LocalizedError
.
Such constraint would allow Failure
to be any type which can be implicitly converted to any Error
.
let concrete: Failure = ....
// If this compiles
let existential: any Error = concrete
// then this will compile as well.
let result: Result<Never, Failure> = .failure(concrete)
Would such language mechanism cover your needs?