B
describes a type that conforms to some set of rules. It is not itself a type that conforms to those rules. B
does not conform to B
, let alone anything it requires additional conformance to. protocol B:A
says "anything that conforms to B
also must conform to A
." However, B
does not conform to B
, and so does not conform to A
.
This has been answered many times on SO, but to repeat the "why," it comes down most simply to this example:
protocol A {
init()
}
func f(type: A.Type) {
let a = type.init()
}
f(type: A.self)
If A
itself conforms to A
, then this should be legal. But what init
should f
call? In the presence of init
and static
requirements, it's not possible for protocols to conform to themselves.
While the specific covariance you want in this case is possible in principle, Swift doesn't have the ability to distinguish between legal and illegal covariance, and disallows all of it. For example, consider the small variation from immutable to mutable:
protocol C {
var property: A { get set }
}
In this case, it is definitely impossible for Bar
to conform (it would have to provide a setter for property
that accepted any A
, even though the getter would return a subtype of A
). Swift is not able to distinguish all the cases where it is possible (generally when everything is immutable and there are no init
or static
requirements) from the cases where it isn't. There's been some discussion of allowing these kinds of cases where it's technically possible, but the concern is that very small changes to the protocol could then break your entire type structure, sometimes for non-obvious reasons. Instead, at least for now, type requirements are generally invariant.
A typical way to address this overall issue is to just provide accessors for the types you want. For example:
protocol A { }
protocol B: A { }
protocol C {
var aProperty: A { get }
}
struct Foo: C {
let aProperty: A
}
struct Bar: C {
var aProperty: A { return bProperty }
let bProperty: B
}
This provides greater flexibility (you can make bProperty
a var
if you like), and makes your code more explicit.