[swift-evolution] When exactly 1 function matches a call site, should it be called or cause a compiler error?
Slava Pestov
spestov at apple.com
Sun Nov 12 19:44:30 CST 2017
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 at 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171112/060298b1/attachment.html>
More information about the swift-evolution
mailing list