迁移到swift 4后对泛型方法的"模糊使用"

tal*_*952 10 generics swift swift4 xcode9

我试图将我的代码从xcode 8.2 swift 3.0.2迁移到xcode 9 swift 4,我有这个代码的问题:

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)
Run Code Online (Sandbox Code Playgroud)

xcode 8.0.2,swift 3.0.2结果:

foo2
Int
Int
Run Code Online (Sandbox Code Playgroud)

xcode 9,swift 4结果:

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 {
^
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?swift 4中是否有任何新功能导致此错误?


更新

我按照评论中的建议在bugs.swift.org上提交了一个错误.
https://bugs.swift.org/browse/SR-6108

jle*_*lew 2

我遇到了同样的问题,并偶然发现了一种解决方法(就我的目的而言),它比通过命名消除歧义更好。也许这甚至不是一个解决方法,事情就必须如此。这也有可能是 Swift 4.1 中新出现的(不确定,因为我直接从 Swift 3 迁移到 4.1)

改变这个:

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

……对此……

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

(注意回调参数周围额外的一对括号T0,这显式地使其成为一个 tuple-of-1)

进行此更改后,test(fn2) 编译并调用test<T0,T1,TRet>重载。编译器似乎能够将具有 N 个参数的函数视为具有一个 N 路元组参数的函数。因此,(T0) -> TRet(T0,T1) -> TRet重载都是 fn2 的候选者,并且调用是不明确的。添加第二对括号((T0)) -> TRet限制对具有单个参数或单向元组的参数的重载。