somu
(somu)
1
Hi,
I have a doubt regarding Generics and Protocols.
Question:
- Why does
f2(p: f1()) compile ok but f3(p: f1()) throws an error ?
Code
protocol P {}
struct S1 : P {}
func f1() -> P {
return S1()
}
func f2(p: P) {}
f2(p: f1())
func f3<T>(p: T) where T : P {}
//Compilation Error: Protocol type 'P' cannot conform to 'P'
//because only concrete types can conform to protocols
//f3(p: f1())
Thanks.
There is a small difference between the two:
func f3<T>(p: T) where T : P {}
This one says "give me a concrete type T which conforms to P"
func f2(p: P) {}
This one says "give me the P existential"
Since protocols in Swift do not conform to themselves*, you cannot pass P to a function which takes T: P.
*except Error which is a special case.
1 Like
somu
(somu)
3
Thanks a lot @suyashsrijan,
Pardon my ignorance, I am a little confused about the following:
Questions:
- What does
existential mean ? Are you referring to P.Type.self ?
- Protocols in Swift do not conform to themselves, could you explain.
An existential is essentially a "box" that can hold a value of any concrete type conforming to a protocol P, or at least that's how I think of it at a high level. Here's a quote from Improving the UI of generics that offers a bit more information:
2 Likes
somu
(somu)
5
Thanks a ton @suyashsrijan, I understand better now.
It also explains why f3 can accept an Opaque type. which has type identity as it points to a specific type (underlying type is not visible to the caller yet specific)