Suppose I have this simple generic protocol
protocol FooProtocol {
associatedtype Element: CustomStringConvertible
func echo(element: Element) -> Element
}
And this simple generic struct that implements it
struct FooStruct<Element: CustomStringConvertible>: FooProtocol {
func echo(element: Element) -> Element {
return element
}
}
Lastly, I have the following function:
func callEcho<T: FooProtocol>(container: T) {
container.echo(element: "some string")
}
This results in error: cannot invoke 'echo' with an argument list of type '(element: String)'
The solution is to change the function to
func callEcho<T: FooProtocol>(container: T) where T.Element == String {
container.echo(element: "some string")
}
My question is: why is the where T.Element == String
constraint necessary? The compiler knows that T
is some entity that implements FooProtocol
, and the protocol only demands that Element
implements CustomStringConvertible
, which my string literal does. So why does it not work without the constraint?
Thanks!
I'm not sure why you say "the protocol only demands that Element implements CustomStringConvertible." The protocol demands that echo
accept and return its Element, which may or may not be String. For example, I can implement this conforming type:
struct AnotherFoo: FooProtocol {
func echo(element: Int) -> Int { fatalError() }
}
So what should happen if I then call:
callEcho(container: AnotherFoo())
This would try to pass a string literal to a function that requires an Int.