Please consider the following code:
protocol P {}
class X {}
class Y: P {}
func foo<T>(_ closure: (T) -> Void) { print(type(of: closure)) }
func foo<T>(_ closure: (T) -> Void) where T: P { print(type(of: closure)) }
let xClosure: (X?) -> Void = { _ in }
foo(xClosure) // prints "(Optional<X>) -> ()"
let yClosure: (Y?) -> Void = { _ in }
foo(yClosure) // prints "(Y) -> ()"
Why does the foo(yClosure)
call resolve to the version of foo
constrained to T: P
?
I understand why that version prints what it prints,
what I don't see is why it gets called instead of the other one.
To me it seems that the non-P version would be a better match for T == (Y?) -> Void
.
Sure, the constrained version is more specific, but it requires conversion
(an implicit conversion from (Y?) -> Void
to (Y) -> Void
),
while the non-P version could be called with no conversion.
Is there a way to fix this code in a way such that the P-constrained version gets called only if the parameter type of the passed-in closure directly conforms to P, without any implicit conversions?