Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"ambiguous use" on generic method after migration to swift 4

I am trying to migrate my code from xcode 8.2 swift 3.0.2 to xcode 9 swift 4, and I have problem with this code:

func test<T0, TRet>(_ fn: (T0) -> TRet) -> Void {
    print("foo1")
    print(T0.self)
}

func test<T0, T1, TRet>(_ fn: (T0, T1) -> TRet) -> Void {
    print("foo2")
    print(T0.self)
    print(T1.self)
}

let fn2 : (Int, Int) -> Int = { (x:Int, y:Int)->Int in
    return x+y
}

test(fn2)

xcode 8.0.2, swift 3.0.2 results with:

foo2
Int
Int

xcode 9, swift 4 results with:

Playground execution failed:

error: MyPlayground.playground:12:1: error: ambiguous use of 'test'
test(fn2)
^

MyPlayground.playground:1:6: note: found this candidate
func test<T0, T1, TRet>(_ fn: (T0, T1) -> TRet) -> Void {
^

Am I missing something? Is there any new feature in swift 4 that causes this error?


Update

I filed a bug at bugs.swift.org as suggested in the comments.
https://bugs.swift.org/browse/SR-6108

like image 571
tal952 Avatar asked Oct 09 '17 14:10

tal952


1 Answers

I ran into the same problem, and stumbled across a workaround that is (for my purposes) nicer than disambiguating via naming. Perhaps it is not even a workaround, just the way things have to be. It's also possible that this is newly-possible in Swift 4.1 (not sure, since I migrated directly from Swift 3 to 4.1)

Change this:

func test<T0, TRet>( fn: (T0) -> TRet) -> Void

...to this...

func test<T0, TRet>( fn: ((T0)) -> TRet) -> Void

(note the extra pair of parens around the T0 callback parameter, which explicitly makes it into a tuple-of-1)

After this change, test(fn2) compiles and calls the test<T0,T1,TRet> overload. It seems that the compiler is able to treat a function with N arguments as a function with one N-way-tuple argument. Hence, both the (T0) -> TRet and (T0,T1) -> TRet overloads are candidates for fn2, and the call is ambiguous. Adding 2nd pair of parens ((T0)) -> TRet limits that overload to an argument with a single parameter or 1-way tuple.

like image 84
jlew Avatar answered Oct 13 '22 21:10

jlew