That’s a bad idea
There are only two ways to use an imported name: 1) name it, 2) that method resolution thing for traits.
(And 2 is not a use that should generate a conflict during resolution, type checker reports ambiguous methods regardless of names used to import traits).
Pretty basic assumption of the current resolution pass is that key (name, namespace) has a single resolution.
So every used path a::b::c can be either resolved unambiguously, or unresolved.
This preventive error reporting is the same general idea that Rust employs in other places (i.e. impl coherence, early checking of trait bounds).
Glob conflicts like
// OK, no error reported
use a::*; // imports type a::S
use b::*; // imports type b::S
are shoehorned into this single resolution system by creating special “ambiguity items”
// Previous snippet is desugared into something like
ambiguity_item S {
a::S,
b::S,
}
// key: `(S, type_ns)` => value: `ambiguity_item S`
these items behave like usual items, in particular, they can be reexported with pub.
I guess it’s possible to change the import resolution algorithm to permit arbitrary number of items with the same name in a namespace, i.e. key: (name, namespace) => value: Vec<resolution>.
In this case preventive error reporting will be done by a separate post-processing pass, which would report conflicts only when they are guaranteed to happen on use.
// Post-processing pass reports a preventive error, because there's no way name `S` can be unambiguously used
struct S {}
struct S {}
mod m {
pub struct S {}
pub fn S() {}
}
mod m {
pub use m::S;
pub fn S() {}
}
// Post-processing pass doesn't report a preventive error, because there IS a way name `S` can be unambiguously used - it can be used in context requiring type namespace.
// The error is reported only if `S` is used in value namespace (possibly in other crate!).
use m::S;
use n::S;
// Post-processing pass doesn't report a preventive error, because there IS a way `Tr` can be unambiguously used - it can be used for method resolution without using the name `Tr`.
trait Tr {}
trait Tr {}
This scheme would also require recording all sets of ambiguous names in crate metadata, that would help with resolving https://github.com/rust-lang/rust/issues/36837.
@jseyfried should probably know in more detail how good, bad or implementable this idea is.
Anyway, this needs an RFC and stabilizing RFC 1560 first.