Goodsquirrel Goodsquirrel - 2 months ago 29
Swift Question

Swift 3.0: compiler error when calling global func min<T>(T,T) in Array or Dictionary extension

After converting from Swift 2.2 to 3.0 my

Array
extension does not compile anymore, because it contains a call to global standard library function
min<T>(T,T)
and shows compiler error
extra argument in call
.

Here's a simple 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 an extension of
Dictionary
, while the exact same code compiles just fine in an extension of other types (e.g.
String
or
AudioBuffer
):

compiler errors in Array and Dictionary extensions

Looking at the documentation of
Array
and
Dictionary
, I find that there are instance methods on
Sequence
named
public func min() -> Element?
and
public func min(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> Element?
. While both
String
and
AudioBuffer
do not have any kind of
min(...)
function.

Is it possible that this is the reason why I can't call the global function? The compiler can't distinguish between global
func min<T>(T,T)
and
self.min(...)
although they have completely different signatures?

Is this a bug or a feature? What am I doing wrong? How can I call
min(T,T)
correctly inside an
Array
extension?

Answer

I see no reason why the compiler shouldn't be able to resolve this function call, therefore I would consider it a bug (it has already been filed – see SR-2450).

It seems to occur whenever attempting to call a global function with the same name, but unambiguously different signature to a method that's accessible from the same scope in a given type (instance or static).

An even simpler example would be:

func foo(_ a: Int) {}

struct Foo {

    func foo() {}

    func bar() {
        foo(2) // error: argument passed to call that takes no arguments
    }
}

Until fixed, a simple solution would be to use the module name in order to disambiguate that you're referring to the global function, rather than the instance one:

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