Skip to content

Commit 9ac9526

Browse files
petrochenkovLorrensP-2158466
authored andcommitted
resolve: Make disambiguators for underscore bindings module-local
1 parent 253410f commit 9ac9526

File tree

4 files changed

+81
-52
lines changed

4 files changed

+81
-52
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
4949
ns: Namespace,
5050
binding: NameBinding<'ra>,
5151
) {
52-
let key = self.new_disambiguated_key(ident, ns);
53-
if let Err(old_binding) = self.try_define_local(parent, key, binding, false) {
52+
if let Err(old_binding) = self.try_define_local(parent, ident, ns, binding, false) {
5453
self.report_conflict(parent, ident, ns, old_binding, binding);
5554
}
5655
}
@@ -89,12 +88,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
8988
def_id
9089
});
9190
let binding = self.arenas.new_res_binding(res, vis, span, expn_id);
92-
let key = self.new_disambiguated_key(ident, ns);
91+
// Even if underscore names cannot be looked up, we still need to add them to modules,
92+
// because they can be fetched by glob imports from those modules, and bring traits
93+
// into scope both directly and through glob imports.
94+
let key = BindingKey::new_disambiguated(ident, ns, || {
95+
(parent.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap()
96+
});
9397
let resolution = &mut *self.resolution(parent, key).borrow_mut();
94-
if resolution.binding.is_some() {
95-
panic!("An external binding was already defined");
98+
if binding.is_glob_import() {
99+
if resolution.glob_binding.is_some() {
100+
panic!("An external glob-binding was already defined");
101+
}
102+
resolution.glob_binding = Some(binding);
103+
} else {
104+
if resolution.non_glob_binding.is_some() {
105+
panic!("An external non-glob-binding was already defined");
106+
}
107+
resolution.non_glob_binding = Some(binding);
96108
}
97-
resolution.binding = Some(binding);
98109
}
99110

100111
/// Walks up the tree of definitions starting at `def_id`,
@@ -470,16 +481,18 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
470481

471482
self.r.indeterminate_imports.push(import);
472483
match import.kind {
473-
// Don't add unresolved underscore imports to modules
474-
ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
475484
ImportKind::Single { target, type_ns_only, .. } => {
476-
self.r.per_ns(|this, ns| {
477-
if !type_ns_only || ns == TypeNS {
478-
let key = BindingKey::new(target, ns);
479-
let mut resolution = this.resolution(current_module, key).borrow_mut();
480-
resolution.single_imports.insert(import);
481-
}
482-
});
485+
// Don't add underscore imports to `single_imports`
486+
// because they cannot define any usable names.
487+
if target.name != kw::Underscore {
488+
self.r.per_ns(|this, ns| {
489+
if !type_ns_only || ns == TypeNS {
490+
let key = BindingKey::new(target, ns);
491+
let mut resolution = this.resolution(current_module, key).borrow_mut();
492+
resolution.single_imports.insert(import);
493+
}
494+
});
495+
}
483496
}
484497
// We don't add prelude imports to the globs since they only affect lexical scopes,
485498
// which are not relevant to import resolution.
@@ -1433,9 +1446,12 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
14331446
let parent = self.parent_scope.module;
14341447
let expansion = self.parent_scope.expansion;
14351448
self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
1436-
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
1449+
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob)
1450+
&& ident.name != kw::Underscore
1451+
{
1452+
// Don't add underscore names, they cannot be looked up anyway.
14371453
let impl_def_id = self.r.tcx.local_parent(local_def_id);
1438-
let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
1454+
let key = BindingKey::new(ident, ns);
14391455
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
14401456
}
14411457

compiler/rustc_resolve/src/imports.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_span::{Ident, Span, Symbol, kw, sym};
2525
use smallvec::SmallVec;
2626
use tracing::debug;
2727

28-
use crate::Namespace::*;
28+
use crate::Namespace::{self, *};
2929
use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
3030
use crate::errors::{
3131
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
@@ -338,13 +338,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
338338
pub(crate) fn try_define_local(
339339
&mut self,
340340
module: Module<'ra>,
341-
key: BindingKey,
341+
ident: Ident,
342+
ns: Namespace,
342343
binding: NameBinding<'ra>,
343344
warn_ambiguity: bool,
344345
) -> Result<(), NameBinding<'ra>> {
345346
let res = binding.res();
346-
self.check_reserved_macro_name(key.ident, res);
347+
self.check_reserved_macro_name(ident, res);
347348
self.set_binding_parent_module(binding, module);
349+
// Even if underscore names cannot be looked up, we still need to add them to modules,
350+
// because they can be fetched by glob imports from those modules, and bring traits
351+
// into scope both directly and through glob imports.
352+
let key = BindingKey::new_disambiguated(ident, ns, || {
353+
(module.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap()
354+
});
348355
self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
349356
if let Some(old_binding) = resolution.best_binding() {
350357
if res == Res::Err && old_binding.res() != Res::Err {
@@ -383,7 +390,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
383390
(old_glob @ true, false) | (old_glob @ false, true) => {
384391
let (glob_binding, non_glob_binding) =
385392
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
386-
if key.ns == MacroNS
393+
if ns == MacroNS
387394
&& non_glob_binding.expansion != LocalExpnId::ROOT
388395
&& glob_binding.res() != non_glob_binding.res()
389396
{
@@ -489,11 +496,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
489496
};
490497
if self.is_accessible_from(binding.vis, scope) {
491498
let imported_binding = self.import(binding, *import);
492-
let key = BindingKey { ident, ..key };
493-
// FIXME: local or external?
494499
let _ = self.try_define_local(
495500
import.parent_scope.module,
496-
key,
501+
ident,
502+
key.ns,
497503
imported_binding,
498504
warn_ambiguity,
499505
);
@@ -515,12 +521,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
515521
let dummy_binding = self.dummy_binding;
516522
let dummy_binding = self.import(dummy_binding, import);
517523
self.per_ns(|this, ns| {
518-
let key = BindingKey::new(target, ns);
519-
let _ =
520-
this.try_define_local(import.parent_scope.module, key, dummy_binding, false);
521-
this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
522-
resolution.single_imports.swap_remove(&import);
523-
})
524+
let module = import.parent_scope.module;
525+
let _ = this.try_define_local(
526+
import.parent_scope.module,
527+
target,
528+
ns,
529+
dummy_binding,
530+
false,
531+
);
532+
// Don't remove underscores from `single_imports`, they were never added.
533+
if target.name != kw::Underscore {
534+
let key = BindingKey::new(target, ns);
535+
this.update_resolution(module, key, false, |_, resolution| {
536+
resolution.single_imports.swap_remove(&import);
537+
})
538+
}
524539
});
525540
self.record_use(target, dummy_binding, Used::Other);
526541
} else if import.imported_module.get().is_none() {
@@ -897,7 +912,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
897912
PendingBinding::Ready(Some(imported_binding))
898913
}
899914
Err(Determinacy::Determined) => {
900-
// Don't update the resolution for underscores, because it was never added.
915+
// Don't remove underscores from `single_imports`, they were never added.
901916
if target.name != kw::Underscore {
902917
let key = BindingKey::new(target, ns);
903918
this.update_resolution(parent, key, false, |_, resolution| {
@@ -1512,7 +1527,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15121527
.is_some_and(|binding| binding.warn_ambiguity_recursive());
15131528
let _ = self.try_define_local(
15141529
import.parent_scope.module,
1515-
key,
1530+
key.ident,
1531+
key.ns,
15161532
imported_binding,
15171533
warn_ambiguity,
15181534
);

compiler/rustc_resolve/src/lib.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -532,15 +532,26 @@ struct BindingKey {
532532
/// identifier.
533533
ident: Ident,
534534
ns: Namespace,
535-
/// 0 if ident is not `_`, otherwise a value that's unique to the specific
536-
/// `_` in the expanded AST that introduced this binding.
535+
/// When we add an underscore binding (with ident `_`) to some module, this field has
536+
/// a non-zero value that uniquely identifies this binding in that module.
537+
/// For non-underscore bindings this field is zero.
538+
/// When a key is constructed for name lookup (as opposed to name definition), this field is
539+
/// also zero, even for underscore names, so for underscores the lookup will never succeed.
537540
disambiguator: u32,
538541
}
539542

540543
impl BindingKey {
541544
fn new(ident: Ident, ns: Namespace) -> Self {
542-
let ident = ident.normalize_to_macros_2_0();
543-
BindingKey { ident, ns, disambiguator: 0 }
545+
BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator: 0 }
546+
}
547+
548+
fn new_disambiguated(
549+
ident: Ident,
550+
ns: Namespace,
551+
disambiguator: impl FnOnce() -> u32,
552+
) -> BindingKey {
553+
let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 };
554+
BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator }
544555
}
545556
}
546557

@@ -659,7 +670,7 @@ impl<'ra> Module<'ra> {
659670
F: FnMut(&R, Ident, Namespace, NameBinding<'ra>),
660671
{
661672
for (key, name_resolution) in resolver.as_ref().resolutions(self).borrow().iter() {
662-
if let Some(binding) = name_resolution.borrow().binding {
673+
if let Some(binding) = name_resolution.borrow().best_binding() {
663674
f(resolver, key.ident, key.ns, binding);
664675
}
665676
}
@@ -1103,8 +1114,6 @@ pub struct Resolver<'ra, 'tcx> {
11031114
extern_module_map: RefCell<FxIndexMap<DefId, Module<'ra>>>,
11041115
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
11051116

1106-
underscore_disambiguator: Cell<u32>,
1107-
11081117
/// Maps glob imports to the names of items actually imported.
11091118
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
11101119
glob_error: Option<ErrorGuaranteed>,
@@ -1523,7 +1532,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15231532
extern_crate_map: Default::default(),
15241533
module_children: Default::default(),
15251534
trait_map: NodeMap::default(),
1526-
underscore_disambiguator: Cell::new(0),
15271535
empty_module,
15281536
local_module_map,
15291537
extern_module_map: Default::default(),
@@ -1909,17 +1917,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19091917
import_ids
19101918
}
19111919

1912-
fn new_disambiguated_key(&self, ident: Ident, ns: Namespace) -> BindingKey {
1913-
let ident = ident.normalize_to_macros_2_0();
1914-
let disambiguator = if ident.name == kw::Underscore {
1915-
self.underscore_disambiguator.update(|x| x + 1);
1916-
self.underscore_disambiguator.get()
1917-
} else {
1918-
0
1919-
};
1920-
BindingKey { ident, ns, disambiguator }
1921-
}
1922-
19231920
fn resolutions(&self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
19241921
if module.populate_on_access.get() {
19251922
module.populate_on_access.set(false);

compiler/rustc_resolve/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
530530
target_trait.for_each_child(self, |this, ident, ns, _binding| {
531531
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
532532
if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
533-
&& overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns))
533+
&& overriding_keys.contains(&BindingKey::new(ident, ns))
534534
{
535535
// The name is overridden, do not produce it from the glob delegation.
536536
} else {

0 commit comments

Comments
 (0)