Description
In the example below two glob imports bring two conflicting names V
into scope.
enum E1 { V }
use E1::*;
enum E2 { V }
use E2::*; // OK, no conflict with `use E1::*;`
fn main() {
let v = V; // ERROR `V` is ambiguous
match v {
V => {} // No error, `V` is a fresh binding
}
}
According to RFC 1560 an error is not immediately reported when two globs conflict, it is reported "on use" only if the ambiguous name is actually used.
Internally such an ambiguity creates an "erroneous item" (Def::Err
) with name V
used exclusively for reporting diagnostics. (However, see #36837, which is an issue closely related to this one.)
For other purposes the name V
doesn't exist in our module.
In the example above we can see that in let v = V;
V
is properly reported as ambiguous on use.
In match
however the meaning of V
is determined in two-step disambiguation process. First we search for an existing item named V
, then if no item named V
exists we create a new variable.
Diagnostics-only Def::Err
items do not exist from this disambiguation process' point of view, so the first step fails for V
and we interpret it as a new variable without any "ambiguous name" warning.
In many cases however, a warning about unused imports will be reported for use E1::*;
and use E2::*;
, but this happens only if the imports aren't actually used anywhere else and the warnings are not always noticed (see #46078).
Two possible solutions are:
- Issue some "did you mean the ambiguous import, not new variable?" warning for
V
inmatch
. - Make "import ambiguity items" actual items, affecting not only diagnostics, but name resolution behavior in general, including disambiguation for fresh bindings. This alternative may be better for resolving item_like_imports: Can "ambiguity error" items be reexported? #36837.