Reputation: 3802
Here's my sample code:
protocol P {
}
protocol B {
associatedtype ID: P
}
class MyClass: B {
enum ID: P {
case one
case two
}
}
func process<T: B>(_ value: T.ID) {
// do something
}
process(MyClass.ID.one) // Compile Error: cannot convert value of type 'MyClass.ID' to expected argument type '_.ID'
As you can see, I define a generic function with a parameter whose type is an associated type of the generic type T. How can I call this function? I want to use MyClass.ID.one as the argument, but the compiler gives the following warning:
cannot convert value of type 'MyClass.ID' to expected argument type '_.ID'
Upvotes: 3
Views: 3385
Reputation: 726987
It appears that Swift has a problem inferring T
from the invocation by starting from MyClass.ID
being T.ID
and backing into MyClass
being T
.
If you change your function to take an additional parameter of type T
, the code compiles and runs fine:
func process<T: B>(_ value: T.ID, _ workaround : T) {
// do something
}
let workaround = MyClass()
process(MyClass.ID.one, workaround)
Swift designers could approach this inference problem in two ways:
T
by enforcing stricter rules on function signatures.It appears that they decided on the second approach with Swift 4, because the original function fails to compile, issuing the following error:
generic parameter
'T'
is not used in function signature
A better work-around is to pass the type instead of an instance, using Java-style approach:
func process<T: B>(_ value: T.ID, _ workaround: T.Type) {
// do something
}
...
process(MyClass.ID.one, MyClass.self)
Note: The edit is based on very insightful comments by tesch
Upvotes: 7
Reputation: 3015
dasblinkenlight provides a good answer to why your current implementation doesn't work. If the decided resolution is to simply find another way to implement this function, then I would opt for a less hacky solution:
extension B {
static func process(_ value: Self.ID) {
//do stuff
}
}
MyClass.process(.one)
This takes advantage of the more flexible type inference achievable via protocol extension Self
.
Upvotes: 0