Swift 3.0: compiler error when calling global func min <T> (T, T) in an array or dictionary extension
After converting from Swift 2.2 to 3.0, my Array extension is no longer compiled since it contains a function call to the global standard library min<T>(T,T) and shows extra argument in call compiling extra argument in call .
Here is an easy way to reproduce the error:
extension Array { func smallestInt(first: Int, second: Int) -> Int { return min(first, second) // compiler error: "Extra argument in call" } } I get the same error when adding the same function to the Dictionary extension, while the same code compiles just in the extension of other types (for example, String or AudioBuffer ):
Looking at the Array and Dictionary documentation, I found that there are instance methods in Sequence named public func min() β Element? and public func min(by areInIncreasingOrder: (Element, Element) throws β Bool) rethrows β Element? Although both String and AudioBuffer do not have any min(...) function.
Is it possible that it is for this reason that I cannot name a global function? The compiler cannot distinguish between global func min<T>(T,T) and self.min(...) although they have completely different signatures?
Is this a bug or a function? What am I doing wrong? How can I properly call min(T,T) inside an Array extension?
I see no reason why the compiler will not be able to resolve this function call, so I would consider it an error (it has already been registered - see SR-2450 ).
It seems that this happens when trying to call a top-level function with the same name, but with a distinctly different signature for the method or property accessible from the same area in the specified type (instance or static).
An even simpler example:
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 } } Before a fixed, a simple solution would be to prefix the call with the name of the module in which it is located, to eliminate that you are referring to a top-level function, not an instance. For the standard library, this is Swift :
extension Array { func smallestInt(first: Int, second: Int) -> Int { return Swift.min(first, second) } } In Swift 4, the compiler has better diagnostics for this error (although the fact that it is still an error is an IMO error):
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) } } Although it is interesting that the compiler now also warns of trying to call the standard library method with the same name as the top-level function 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() } } In this case, as warns, you can disable it using explicit self. :
extension Array where Element : Comparable { func smallest() -> Element? { return self.min() } } Although what is really interesting about this warning does not seem to apply to non-stdlib specific functions:
func foo(_ a: Int) {} struct Foo { func foo() {} func bar() { foo() // no warning... } } 