Yeah, this is an unfortunate wart. Right now unqualified lookup starts at the 
innermost scope and stops when it finds a candidate which matches the name 
being looked up. Overload sets are only formed if there are multiple candidates 
inside the same scope, not in different scopes.

It would be nice to fix this but note that it might have a compile-time 
performance impact, because now we will be looking up names in more scopes. In 
particular, this means almost every name lookup will have to look at all 
imported modules.

If this can be implemented in a clever way without impacting compile time, I’ll 
be all for this change.

However, note that the most common way in which people hit this is with 
type(of:) vs a local name named type — I think this can be solved without 
fundamentally changing unqualified lookup, by having unqualified lookup look at 
the DeclName rather than an Identifier. So if you have

var type = …

type(of: foo)

We would not consider the ‘var type’ at all, since it doesn’t match the 
DeclName type(of:). This might also address min vs Collection.min if we 
consider the number of arguments when performing the lookup too.

Either way I think an evolution proposal is a good idea, this has source 
compatibility impact since it can introduce ambiguity at call sites that were 
formerly unambiguous. But we should be careful not to impact compile time.

Slava

> On Nov 12, 2017, at 5:12 PM, Nevin Brackett-Rozinsky via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> I brought this up on Swift Dev and was told to check on Swift Evolution to 
> see if a proposal is needed.
> 
> Currently, the following code produces a compiler error:
> 
> func foo(_ x: Int, _ y: Int) -> Int {
>   return x + y
> }
> 
> extension Int {
>   func foo() -> Int {
>     return foo(self, self)    // Error here
>   }
> }
> 
> Notice that the two functions named “foo” have entirely different signatures. 
> The global function takes 2 arguments, while the member function takes 0 (or 
> 1, if referenced as “Int.foo”).
> 
> There is exactly one function “foo” which takes 2 arguments, so a call to 
> “foo” with 2 arguments, like the one shown, should be unambiguous. However, 
> instead of calling the function with matching signature, there is instead a 
> compiler error.
> 
> This is already documented as SR–2450 
> <https://bugs.swift.org/browse/SR-2450>, with an example from the standard 
> library (global 2-argument “min” vs. 0-argument “Collection.min”).
> 
> It appears that in any situation where a global function and a member 
> function share the same base name, but only the global function’s signature 
> matches the call site, the result is a compiler error.
> 
> I suggest that, when there is exactly one function available with the proper 
> name and signature, instead of a compiler error the matching function should 
> be called.
> 
> Do we need a Swift Evolution proposal for this change?
> 
> Nevin
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to