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)’
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.
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.