We need to include them because we'd like to provide diagnostics and suggest to add a prefix i.e. Swift.
or other module/declaration name to make it work if nothing from the inner scope matched for example.
It is not clear to me why āThe set of candidates for use at the call siteā and āThe set of candidates for use in diagnosticsā should need to be identical.
Or even that they need to be constructed at the same time. One could imagine the latter set being lazy, so it is only created if a diagnostic is actually needed.
It is not clear to me why āThe set of candidates for use at the call siteā and āThe set of candidates for use in diagnosticsā should need to be identical.
I didn't say the should be, currently solver has no control over that set, it's formed during pre-checking and passed down, outer scope candidates either lazily looked up or added and disabled in normal mode and only attempted in diagnostic mode, it would just be an implementation detail at that point.
Okay, but you talked about āchanging the shadowing behaviorā. That sounds to me quite different from āchanging the diagnostics behaviorā.
Just a terminology issue, it's not going to be changing the diagnostic behavior it's going to be changing how the constraint solver handles name lookup internally.
Ah, so for the two code examples I listed in this post, are you saying they would continue to behave as they do today after the changes youāre thinking of?
Yes, the surface language behavior doesn't have to change with this rework of the implementation although it would make it much easier to change if we wanted to.
Does it mean that in this example:
func foo() {}
func foo(x1: Int) {}
func foo(x2: Int) {}
func foo(x3: Int) {}
// ...
func foo(x999: Int) {}
when the compiler sees the line:
foo()
it would first construct a set of 1000 candidates, to potentially use it for diagnostic purposes, but then (because there is no diagnostic to show, as would be in the vast majority of cases) that set of candidates would be simply thrown away?
And when the diagnostics is being shown, compiler will use the first element of the candidate set, throwing everything else away?
š Missing argument for parameter 'x1' in call
Insert 'x1: <#Int#>'
Looks quite inefficient. OTOH, this is a synthetic example, and in real life such instances would be extremely rare.
Yes, this is what happens today too, the type-checker has to evaluate each candidate before throwing it away and by evaluate I mean first check the labels, default arguments and other things if that matches, check types.
@jrose , @xwu, @xedin: If we were to tell the compiler to take the one in the global scope by prefixing the function-call expression with something, say ::
struct Demo {
func foo (bar: Int) -> Int {
::foo(notBar: bar, baz: true)
}
}
func foo (notBar: Int, baz: Bool) -> Int {
baz ? notBar : -notBar
}
Would this also constitute a scary change?
If it's the module/type scope we already have a way to spell that, the only problem is implementation. There is also a pitch from @beccadax a while back about this kind of issues with name lookup - Pitch: Fully qualified name syntax