Just to add my reaction as a humble user. For this particular example, my mental model of Swift's generics (which took a while to develop) allows me to not get surprised or confused. This example is in my opinion not showcasing any of the really-hard-to-understand parts. I include the example here again for completeness:
protocol P {
func whatAmI()
}
extension P { func whatAmI() { print("P") } }
extension Array: P { func whatAmI() { print("Array") } }
extension Array where Element: P { func whatAmI() { print("Array<P>") } }
extension Int: P { func whatAmI() { print("Int") } }
func whatIsIt<C: P>(_ value: C) {
value.whatAmI()
}
func test() {
let x = [1, 2, 3]
x.whatAmI() // Array<P>
whatIsIt(x) // Array
}
test()
By looking at this program I can predict (and not get surprised) by the output. The generic function whatIsIt
has a typeparameter C
which is constrained only by C: P
which means that the compiler knows nothing about C
except what it knows about P
. That is, it knows about P
's requirement whatAmI()
and can call that required method (as implemented by various particular C
s), but it does so without knowing anything about eg Element
or Array
, it cannot get any information from any if its call sites, it's just its signature that matters.
The only way to make whatIsIt
print "Array<P>"
too (which I guess might be what some would expect?) would be to rewrite the example in a way that lets the compiler know more/enough about C
. As the example is currently written, it is clear that within the body of whatIsIt
, the compiler has no idea about Element: P
or that C can sometimes be an Array
. It only knows that some C
conforms to P
and if that C
happens to implement P
's requirement rather than use a default implementation, it will call C
's implementation.
That said, there are many other things I get confused by in Swift's generics, like this example which @dabrahams linked to in the OP. (Note that I do not have a clear expectation about what the intended/best/fixed behavior should be in that example, especially so when taking @Nevin's "fun fact" into account.)
But perhaps my confusion there is just caused by the same rules I claim to understand here, I haven't thought about it enough to know if that might be the case.