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

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 top-level function with the same name, but unambiguously different signature to a method or property 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() {} // or static func foo() {}, var foo = 0, static var foo = 0

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

Until fixed, a simple solution would be to prefix the call with the name of the module in which it resides in order to disambiguate that you’re referring to the top-level function, rather than the instance one. For the standard library, that’s Swift:

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

In Swift 4, the compiler has a better diagnostic for this error (though the fact that it’s still an error is a bug 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)
    }
}

Although what’s interesting is that the compiler will now also warn on attempting to call a standard library method with the same name as a stdlib top-level function:

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 the warning says, you can silence it by using an explicit self.:

extension Array where Element : Comparable {

    func smallest() -> Element? {
        return self.min()
    }
}

Although what’s really curious about this warning is it doesn’t appear to extend to non-stdlib defined functions:

func foo(_ a: Int) {}

struct Foo {

    func foo() {}

    func bar() {
        foo() // no warning...
    }
}

Leave a Comment