Swift 3.0:调用Array或Dictionary扩展中的全局func min <T>(T,T)时发生编译器错误

从Swift 2.2转换到3.0之后,我的Array扩展名不再编译,因为它包含对全局标准库函数min<T>(T,T) extra argument in call min<T>(T,T)extra argument in call显示编译器错误的extra argument in call

这里有一个简单的方法来重现错误:

 extension Array { func smallestInt(first: Int, second: Int) -> Int { return min(first, second) // compiler error: "Extra argument in call" } } 

当将相同的函数添加到Dictionary的扩展中时,我得到相同的错误,而完全相同的代码在其他types的扩展中编译得很好(例如StringAudioBuffer ):

数组和字典扩展中的编译器错误

看看ArrayDictionary的文档,我发现Sequence中有实例方法public func min() -> Element?public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element? 。 虽然StringAudioBuffer都没有任何种类的min(...)函数。

这有可能是我不能称为全球function的原因吗? 编译器不能区分全局func min<T>(T,T)self.min(...)尽pipe它们具有完全不同的签名。

这是一个错误还是一个function? 我究竟做错了什么? 如何在Array扩展中正确调用min(T,T)

我没有理由为什么编译器不应该能够解决这个函数调用,所以我会认为它是一个错误(它已经被提交 – 见SR-2450 )。

每当试图调用具有相同名称的顶级函数时,似乎都会发生这种情况,但对于可以从给定types(实例或静态)中的相同作用域访问的方法或属性,其签名明确不同。

一个更简单的例子是:

 func foo(_ a: Int) {} struct Foo { func foo() {} // or static func foo() {}, var foo = 0, static var foo = 0 func bar() { foo(2) // error: argument passed to call that takes no arguments } } 

在修正之前,一个简单的解决scheme就是在调用前加上它所在模块的名称,以便消除你指的是顶级函数,而不是实例一。 对于标准库,那就是Swift

 extension Array { func smallestInt(first: Int, second: Int) -> Int { return Swift.min(first, second) } } 

在Swift 4中,编译器对这个错误有一个更好的诊断(虽然它仍然是一个错误是一个错误IMO):

 extension Array { func smallestInt(first: Int, second: Int) -> Int { // Use of 'min' refers to instance method 'min(by:)' // rather than global function 'min' in module 'Swift' // - Use 'Swift.' to reference the global function in module 'Swift' return min(first, second) } } 

尽pipe有趣的是,编译器现在还会试图调用一个标准库方法,它与stdlib顶级函数具有相同的名称:

 extension Array where Element : Comparable { func smallest() -> Element? { // Use of 'min' treated as a reference to instance method in protocol 'Sequence' // - Use 'self.' to silence this warning // - Use 'Swift.' to reference the global function return min() } } 

在这种情况下,正如警告所说,你可以通过使用明确的self.使其沉默self.

 extension Array where Element : Comparable { func smallest() -> Element? { return self.min() } } 

虽然这个警告真的好奇,但它似乎并没有扩展到非stdlib定义的函数:

 func foo(_ a: Int) {} struct Foo { func foo() {} func bar() { foo() // no warning... } }