# Protocol with a where clause vs protocol inheritance

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.

`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

Thank you for clarifying the subtlety.

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) {}
``````