tera
1
Is there a difference between B & C below or are they equivalent?
protocol A {}
protocol B where Self : A {}
protocol C: A {}
2 Likes
Intuitively, I would say they are not the same:
C inherits A (protocol inheritance)
B does not inherit A, but puts a constraint on which types can adopt it.
ibex10
3
B does seem to inherit A, as the following code demonstrates.
protocol A {}
protocol B where Self : A {}
protocol C: A {}
struct Foo: B {
}
func fubar (_ p: A) {
print (type (of: p))
}
let u = Foo ()
let p: A = u
fubar (u) // prints Foo
fubar (p) // prints Foo
It appears that protocol conformance only requires a protocol's requirements to be satisfied, not that a type explicitly adopts it (by placing the protocol’s name after the type’s name).
Actually, the docs say so: " Any type that satisfies the requirements of a protocol is said to conform to that protocol." So conforming to a protocol and adopting a protocol are not the same.
protocol A {
func a()
}
protocol B where Self : A {
func b()
}
struct Foo: B { // gives: Type 'Foo' does not conform to protocol 'A' if func a() is not present
func b() { }
func a() { }
}
Adding a bit to my first answer: I think as types B and C are not the same, a C is-an A, wheres a B is-not-an A, that would be my thinking here.
1 Like
ibex10
5
Thank you for clarifying the subtlety.
tera
6
How exactly could you check this? C is A is a compilation error 
1 Like
They are equivalent. Each of the following pairs are equivalent:
protocol P: Q {}
protocol P where Self: Q {}
func f<T: P>(_: T) {}
func f<T>(_: T) where T: P {}
associatedtype A: P
associatedtype A where Self.A: P
The desugaring is documented in Chapter 4 of swift/docs/Generics at main · swiftlang/swift · GitHub. To build it, install MacTeX and run make in docs/Generics.
5 Likes
You can check that a type parameter constrained to C satisfies a conformance requirement to A or whatever:
func f<T: C>(_ t: T) { g(t) }
func g<T: A>(_: T) {}