Generic function with protocol restriction

Hello,
i have the following code:

protocol A { }
@objc protocol B { }

func testA<T: A>(_ value: T) { }
func testB<T: B>(_ value: T) { }
func testC<T>(_ value: T) { }

func tryAll(a: A, b: B) {

    testA(a) //Does not compile
    testB(b) //compile
    testC(a) // compile
}

can anyone tell me why i get the following error when writting testA(a)?
error: cannot invoke ‘testA’ with an argument list of type '(A)'
note: expected an argument list of type ‘(T)’

In Swift, protocols don’t conform to themselves. Let me see if I can dig up some links on the rationale behind this.

Thanks @saagarjha but if this is true can you tell me why the following code compile juste fine:

func testAP(_ value: A) {}
testAP(a) 

To me is was two ways to same the same thing but somehow there is a difference that i just can’t figure out.

func testA<T: A>(_ value: T) { }
func testAP(_ value: A) {}

There’s a great explanation of the reasons at Stack Overflow:

In short, letting protocols conform to themselves leads to corner cases with static members.

1 Like

The first function (testA) is generic, which means it works with different types. The requirement is that all those types should conform to protocol A. The second function (testAP) is not generic. Its argument has a single fixed type. This single type is a special type that is called an existential type.

An existential type is effectively a container that hides the true type of a value and only exposes its conformance to a protocol (or aggregate of protocols). For the moment, existential types only work with concrete (none-generic) protocols. Protocols that have Self or associatedtype requirements are not concrete, since they don't fully specify fixed argument types for their requirements.

I think the Swift book needs to expand and improve the coverage of existential types. I see many people struggle with existential types and how they differ from generics and protocol constraints.

4 Likes

Thanks everyone !! This is cristal clear for me now 👍🏽

IIRC though there was some thought behind making this work when the compiler could ensure that there were no such issues in the protocol, as it’s mostly unexpected behaviour (even though justified) in practice.

I believe it’s the subject of SR-55.

1 Like