resolve: Make disambiguators for underscore bindings module-local
This commit is contained in:
@@ -49,8 +49,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
binding: NameBinding<'ra>,
|
binding: NameBinding<'ra>,
|
||||||
) {
|
) {
|
||||||
let key = self.new_disambiguated_key(ident, ns);
|
if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) {
|
||||||
if let Err(old_binding) = self.try_define(parent, key, binding, false) {
|
|
||||||
self.report_conflict(parent, ident, ns, old_binding, binding);
|
self.report_conflict(parent, ident, ns, old_binding, binding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,9 +441,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
|
|
||||||
self.r.indeterminate_imports.push(import);
|
self.r.indeterminate_imports.push(import);
|
||||||
match import.kind {
|
match import.kind {
|
||||||
// Don't add unresolved underscore imports to modules
|
|
||||||
ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
|
|
||||||
ImportKind::Single { target, type_ns_only, .. } => {
|
ImportKind::Single { target, type_ns_only, .. } => {
|
||||||
|
// Don't add underscore imports to `single_imports`
|
||||||
|
// because they cannot define any usable names.
|
||||||
|
if target.name != kw::Underscore {
|
||||||
self.r.per_ns(|this, ns| {
|
self.r.per_ns(|this, ns| {
|
||||||
if !type_ns_only || ns == TypeNS {
|
if !type_ns_only || ns == TypeNS {
|
||||||
let key = BindingKey::new(target, ns);
|
let key = BindingKey::new(target, ns);
|
||||||
@@ -453,6 +453,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// We don't add prelude imports to the globs since they only affect lexical scopes,
|
// We don't add prelude imports to the globs since they only affect lexical scopes,
|
||||||
// which are not relevant to import resolution.
|
// which are not relevant to import resolution.
|
||||||
ImportKind::Glob { is_prelude: true, .. } => {}
|
ImportKind::Glob { is_prelude: true, .. } => {}
|
||||||
@@ -1408,9 +1409,12 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
let parent = self.parent_scope.module;
|
let parent = self.parent_scope.module;
|
||||||
let expansion = self.parent_scope.expansion;
|
let expansion = self.parent_scope.expansion;
|
||||||
self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
|
self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
|
||||||
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
|
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob)
|
||||||
|
&& ident.name != kw::Underscore
|
||||||
|
{
|
||||||
|
// Don't add underscore names, they cannot be looked up anyway.
|
||||||
let impl_def_id = self.r.tcx.local_parent(local_def_id);
|
let impl_def_id = self.r.tcx.local_parent(local_def_id);
|
||||||
let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
|
let key = BindingKey::new(ident, ns);
|
||||||
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
|
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use rustc_span::{Ident, Span, Symbol, kw, sym};
|
|||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::Namespace::*;
|
use crate::Namespace::{self, *};
|
||||||
use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
|
use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
|
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
|
||||||
@@ -338,13 +338,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
pub(crate) fn try_define(
|
pub(crate) fn try_define(
|
||||||
&mut self,
|
&mut self,
|
||||||
module: Module<'ra>,
|
module: Module<'ra>,
|
||||||
key: BindingKey,
|
ident: Ident,
|
||||||
|
ns: Namespace,
|
||||||
binding: NameBinding<'ra>,
|
binding: NameBinding<'ra>,
|
||||||
warn_ambiguity: bool,
|
warn_ambiguity: bool,
|
||||||
) -> Result<(), NameBinding<'ra>> {
|
) -> Result<(), NameBinding<'ra>> {
|
||||||
let res = binding.res();
|
let res = binding.res();
|
||||||
self.check_reserved_macro_name(key.ident, res);
|
self.check_reserved_macro_name(ident, res);
|
||||||
self.set_binding_parent_module(binding, module);
|
self.set_binding_parent_module(binding, module);
|
||||||
|
// Even if underscore names cannot be looked up, we still need to add them to modules,
|
||||||
|
// because they can be fetched by glob imports from those modules, and bring traits
|
||||||
|
// into scope both directly and through glob imports.
|
||||||
|
let key = BindingKey::new_disambiguated(ident, ns, || {
|
||||||
|
(module.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap()
|
||||||
|
});
|
||||||
self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
|
self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
|
||||||
if let Some(old_binding) = resolution.best_binding() {
|
if let Some(old_binding) = resolution.best_binding() {
|
||||||
if res == Res::Err && old_binding.res() != Res::Err {
|
if res == Res::Err && old_binding.res() != Res::Err {
|
||||||
@@ -383,7 +390,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
(old_glob @ true, false) | (old_glob @ false, true) => {
|
(old_glob @ true, false) | (old_glob @ false, true) => {
|
||||||
let (glob_binding, non_glob_binding) =
|
let (glob_binding, non_glob_binding) =
|
||||||
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
||||||
if key.ns == MacroNS
|
if ns == MacroNS
|
||||||
&& non_glob_binding.expansion != LocalExpnId::ROOT
|
&& non_glob_binding.expansion != LocalExpnId::ROOT
|
||||||
&& glob_binding.res() != non_glob_binding.res()
|
&& glob_binding.res() != non_glob_binding.res()
|
||||||
{
|
{
|
||||||
@@ -489,10 +496,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
};
|
};
|
||||||
if self.is_accessible_from(binding.vis, scope) {
|
if self.is_accessible_from(binding.vis, scope) {
|
||||||
let imported_binding = self.import(binding, *import);
|
let imported_binding = self.import(binding, *import);
|
||||||
let key = BindingKey { ident, ..key };
|
|
||||||
let _ = self.try_define(
|
let _ = self.try_define(
|
||||||
import.parent_scope.module,
|
import.parent_scope.module,
|
||||||
key,
|
ident,
|
||||||
|
key.ns,
|
||||||
imported_binding,
|
imported_binding,
|
||||||
warn_ambiguity,
|
warn_ambiguity,
|
||||||
);
|
);
|
||||||
@@ -514,11 +521,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
let dummy_binding = self.dummy_binding;
|
let dummy_binding = self.dummy_binding;
|
||||||
let dummy_binding = self.import(dummy_binding, import);
|
let dummy_binding = self.import(dummy_binding, import);
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
|
let module = import.parent_scope.module;
|
||||||
|
let _ = this.try_define(module, target, ns, dummy_binding, false);
|
||||||
|
// Don't remove underscores from `single_imports`, they were never added.
|
||||||
|
if target.name != kw::Underscore {
|
||||||
let key = BindingKey::new(target, ns);
|
let key = BindingKey::new(target, ns);
|
||||||
let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
|
this.update_resolution(module, key, false, |_, resolution| {
|
||||||
this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
|
|
||||||
resolution.single_imports.swap_remove(&import);
|
resolution.single_imports.swap_remove(&import);
|
||||||
})
|
})
|
||||||
|
}
|
||||||
});
|
});
|
||||||
self.record_use(target, dummy_binding, Used::Other);
|
self.record_use(target, dummy_binding, Used::Other);
|
||||||
} else if import.imported_module.get().is_none() {
|
} else if import.imported_module.get().is_none() {
|
||||||
@@ -895,7 +906,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
PendingBinding::Ready(Some(imported_binding))
|
PendingBinding::Ready(Some(imported_binding))
|
||||||
}
|
}
|
||||||
Err(Determinacy::Determined) => {
|
Err(Determinacy::Determined) => {
|
||||||
// Don't update the resolution for underscores, because it was never added.
|
// Don't remove underscores from `single_imports`, they were never added.
|
||||||
if target.name != kw::Underscore {
|
if target.name != kw::Underscore {
|
||||||
let key = BindingKey::new(target, ns);
|
let key = BindingKey::new(target, ns);
|
||||||
this.update_resolution(parent, key, false, |_, resolution| {
|
this.update_resolution(parent, key, false, |_, resolution| {
|
||||||
@@ -1510,7 +1521,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
.is_some_and(|binding| binding.warn_ambiguity_recursive());
|
.is_some_and(|binding| binding.warn_ambiguity_recursive());
|
||||||
let _ = self.try_define(
|
let _ = self.try_define(
|
||||||
import.parent_scope.module,
|
import.parent_scope.module,
|
||||||
key,
|
key.ident,
|
||||||
|
key.ns,
|
||||||
imported_binding,
|
imported_binding,
|
||||||
warn_ambiguity,
|
warn_ambiguity,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -532,15 +532,26 @@ struct BindingKey {
|
|||||||
/// identifier.
|
/// identifier.
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
/// 0 if ident is not `_`, otherwise a value that's unique to the specific
|
/// When we add an underscore binding (with ident `_`) to some module, this field has
|
||||||
/// `_` in the expanded AST that introduced this binding.
|
/// a non-zero value that uniquely identifies this binding in that module.
|
||||||
|
/// For non-underscore bindings this field is zero.
|
||||||
|
/// When a key is constructed for name lookup (as opposed to name definition), this field is
|
||||||
|
/// also zero, even for underscore names, so for underscores the lookup will never succeed.
|
||||||
disambiguator: u32,
|
disambiguator: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BindingKey {
|
impl BindingKey {
|
||||||
fn new(ident: Ident, ns: Namespace) -> Self {
|
fn new(ident: Ident, ns: Namespace) -> Self {
|
||||||
let ident = ident.normalize_to_macros_2_0();
|
BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator: 0 }
|
||||||
BindingKey { ident, ns, disambiguator: 0 }
|
}
|
||||||
|
|
||||||
|
fn new_disambiguated(
|
||||||
|
ident: Ident,
|
||||||
|
ns: Namespace,
|
||||||
|
disambiguator: impl FnOnce() -> u32,
|
||||||
|
) -> BindingKey {
|
||||||
|
let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 };
|
||||||
|
BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,8 +1098,6 @@ pub struct Resolver<'ra, 'tcx> {
|
|||||||
extern_module_map: RefCell<FxIndexMap<DefId, Module<'ra>>>,
|
extern_module_map: RefCell<FxIndexMap<DefId, Module<'ra>>>,
|
||||||
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
|
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
|
||||||
|
|
||||||
underscore_disambiguator: u32,
|
|
||||||
|
|
||||||
/// Maps glob imports to the names of items actually imported.
|
/// Maps glob imports to the names of items actually imported.
|
||||||
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
|
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
|
||||||
glob_error: Option<ErrorGuaranteed>,
|
glob_error: Option<ErrorGuaranteed>,
|
||||||
@@ -1500,7 +1509,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
extern_crate_map: Default::default(),
|
extern_crate_map: Default::default(),
|
||||||
module_children: Default::default(),
|
module_children: Default::default(),
|
||||||
trait_map: NodeMap::default(),
|
trait_map: NodeMap::default(),
|
||||||
underscore_disambiguator: 0,
|
|
||||||
empty_module,
|
empty_module,
|
||||||
local_module_map,
|
local_module_map,
|
||||||
extern_module_map: Default::default(),
|
extern_module_map: Default::default(),
|
||||||
@@ -1881,17 +1889,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
import_ids
|
import_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
|
|
||||||
let ident = ident.normalize_to_macros_2_0();
|
|
||||||
let disambiguator = if ident.name == kw::Underscore {
|
|
||||||
self.underscore_disambiguator += 1;
|
|
||||||
self.underscore_disambiguator
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
BindingKey { ident, ns, disambiguator }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
|
fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
|
||||||
if module.populate_on_access.get() {
|
if module.populate_on_access.get() {
|
||||||
module.populate_on_access.set(false);
|
module.populate_on_access.set(false);
|
||||||
|
|||||||
@@ -530,7 +530,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||||||
target_trait.for_each_child(self, |this, ident, ns, _binding| {
|
target_trait.for_each_child(self, |this, ident, ns, _binding| {
|
||||||
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
|
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
|
||||||
if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
|
if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
|
||||||
&& overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns))
|
&& overriding_keys.contains(&BindingKey::new(ident, ns))
|
||||||
{
|
{
|
||||||
// The name is overridden, do not produce it from the glob delegation.
|
// The name is overridden, do not produce it from the glob delegation.
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user