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

这是重现该错误的简单方法:

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


将相同的函数添加到Dictionary的扩展名时遇到相同的错误,而完全相同的代码在其他类型的扩展名(例如StringAudioBuffer)中的编译也很好:

arrays - Swift 3.0:在数组或字典扩展中调用全局函数min &lt;T&gt;(T,T)时出现编译器错误-LMLPHP

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

这可能是我无法调用全局函数的原因吗?编译器无法区分全局func min<T>(T,T)self.min(...),尽管它们具有完全不同的签名?

这是错误还是功能?我究竟做错了什么?如何在min(T,T)扩展名内正确调用Array

最佳答案

我看不出编译器为何无法解决此函数调用的原因,因此我认为它是一个错误(已归档-请参见SR-2450)。

每当尝试调用具有相同名称但对从给定类型(实例或静态)的同一作用域可访问的方法或属性明确不同的签名时,似乎都会发生这种情况。

一个更简单的示例是:

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
    }
}


在修复之前,一种简单的解决方案是在调用之前添加调用所在模块的名称,以消除您在引用顶级功能而不是实例功能的歧义。对于标准库,为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)
    }
}


尽管有趣的是,编译器现在还将警告尝试调用与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.将其静音:

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...
    }
}

关于arrays - Swift 3.0:在数组或字典扩展中调用全局函数min <T>(T,T)时出现编译器错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42110700/

10-11 22:15
查看更多