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的扩展中编译得很好(例如String
或AudioBuffer
):
看看Array
和Dictionary
的文档,我发现Sequence
中有实例方法public func min() -> Element?
和public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
。 虽然String
和AudioBuffer
都没有任何种类的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... } }