Skip to content

Commit fc5af18

Browse files
committed
Auto merge of #144272 - petrochenkov:disambunder2, r=oli-obk
resolve: Make disambiguators for underscore bindings module-local (take 2) The difference with #144013 can be seen in the second commit. Now we just keep a separate disambiguator counter in every `Module`, instead of a global counter in `Resolver`. This will be ok for parallel import resolution because we'll need to lock the module anyway when updating `resolutions` and other fields in it. And for external modules the disabmiguator could be just passed as an argument to `define_extern`, without using any cells or locks, once #143884 lands. Unblocks #143884.
2 parents 3c30dbb + 4b55791 commit fc5af18

File tree

4 files changed

+62
-45
lines changed

4 files changed

+62
-45
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
5353
ns: Namespace,
5454
binding: NameBinding<'ra>,
5555
) {
56-
let key = self.new_disambiguated_key(ident, ns);
57-
if let Err(old_binding) = self.try_define(parent, key, binding, false) {
56+
if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) {
5857
self.report_conflict(parent, ident, ns, old_binding, binding);
5958
}
6059
}
@@ -446,16 +445,18 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
446445

447446
self.r.indeterminate_imports.push(import);
448447
match import.kind {
449-
// Don't add unresolved underscore imports to modules
450-
ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
451448
ImportKind::Single { target, type_ns_only, .. } => {
452-
self.r.per_ns(|this, ns| {
453-
if !type_ns_only || ns == TypeNS {
454-
let key = BindingKey::new(target, ns);
455-
let mut resolution = this.resolution(current_module, key).borrow_mut();
456-
resolution.single_imports.insert(import);
457-
}
458-
});
449+
// Don't add underscore imports to `single_imports`
450+
// because they cannot define any usable names.
451+
if target.name != kw::Underscore {
452+
self.r.per_ns(|this, ns| {
453+
if !type_ns_only || ns == TypeNS {
454+
let key = BindingKey::new(target, ns);
455+
let mut resolution = this.resolution(current_module, key).borrow_mut();
456+
resolution.single_imports.insert(import);
457+
}
458+
});
459+
}
459460
}
460461
// We don't add prelude imports to the globs since they only affect lexical scopes,
461462
// which are not relevant to import resolution.
@@ -1401,9 +1402,12 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
14011402
let parent = self.parent_scope.module;
14021403
let expansion = self.parent_scope.expansion;
14031404
self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
1404-
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
1405+
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob)
1406+
&& ident.name != kw::Underscore
1407+
{
1408+
// Don't add underscore names, they cannot be looked up anyway.
14051409
let impl_def_id = self.r.tcx.local_parent(local_def_id);
1406-
let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
1410+
let key = BindingKey::new(ident, ns);
14071411
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
14081412
}
14091413

compiler/rustc_resolve/src/imports.rs

Lines changed: 26 additions & 13 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,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
338338
pub(crate) fn try_define(
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.underscore_disambiguator.update(|d| d + 1);
354+
module.underscore_disambiguator.get()
355+
});
348356
self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
349357
if let Some(old_binding) = resolution.best_binding() {
350358
if res == Res::Err && old_binding.res() != Res::Err {
@@ -383,7 +391,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
383391
(old_glob @ true, false) | (old_glob @ false, true) => {
384392
let (glob_binding, non_glob_binding) =
385393
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
386-
if key.ns == MacroNS
394+
if ns == MacroNS
387395
&& non_glob_binding.expansion != LocalExpnId::ROOT
388396
&& glob_binding.res() != non_glob_binding.res()
389397
{
@@ -489,10 +497,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
489497
};
490498
if self.is_accessible_from(binding.vis, scope) {
491499
let imported_binding = self.import(binding, *import);
492-
let key = BindingKey { ident, ..key };
493500
let _ = self.try_define(
494501
import.parent_scope.module,
495-
key,
502+
ident,
503+
key.ns,
496504
imported_binding,
497505
warn_ambiguity,
498506
);
@@ -514,11 +522,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
514522
let dummy_binding = self.dummy_binding;
515523
let dummy_binding = self.import(dummy_binding, import);
516524
self.per_ns(|this, ns| {
517-
let key = BindingKey::new(target, ns);
518-
let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
519-
this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
520-
resolution.single_imports.swap_remove(&import);
521-
})
525+
let module = import.parent_scope.module;
526+
let _ = this.try_define(module, target, ns, dummy_binding, false);
527+
// Don't remove underscores from `single_imports`, they were never added.
528+
if target.name != kw::Underscore {
529+
let key = BindingKey::new(target, ns);
530+
this.update_resolution(module, key, false, |_, resolution| {
531+
resolution.single_imports.swap_remove(&import);
532+
})
533+
}
522534
});
523535
self.record_use(target, dummy_binding, Used::Other);
524536
} else if import.imported_module.get().is_none() {
@@ -895,7 +907,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
895907
PendingBinding::Ready(Some(imported_binding))
896908
}
897909
Err(Determinacy::Determined) => {
898-
// Don't update the resolution for underscores, because it was never added.
910+
// Don't remove underscores from `single_imports`, they were never added.
899911
if target.name != kw::Underscore {
900912
let key = BindingKey::new(target, ns);
901913
this.update_resolution(parent, key, false, |_, resolution| {
@@ -1510,7 +1522,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15101522
.is_some_and(|binding| binding.warn_ambiguity_recursive());
15111523
let _ = self.try_define(
15121524
import.parent_scope.module,
1513-
key,
1525+
key.ident,
1526+
key.ns,
15141527
imported_binding,
15151528
warn_ambiguity,
15161529
);

compiler/rustc_resolve/src/lib.rs

Lines changed: 18 additions & 18 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

@@ -568,6 +579,8 @@ struct ModuleData<'ra> {
568579
lazy_resolutions: Resolutions<'ra>,
569580
/// True if this is a module from other crate that needs to be populated on access.
570581
populate_on_access: Cell<bool>,
582+
/// Used to disambiguate underscore items (`const _: T = ...`) in the module.
583+
underscore_disambiguator: Cell<u32>,
571584

572585
/// Macro invocations that can expand into items in this module.
573586
unexpanded_invocations: RefCell<FxHashSet<LocalExpnId>>,
@@ -628,6 +641,7 @@ impl<'ra> ModuleData<'ra> {
628641
kind,
629642
lazy_resolutions: Default::default(),
630643
populate_on_access: Cell::new(is_foreign),
644+
underscore_disambiguator: Cell::new(0),
631645
unexpanded_invocations: Default::default(),
632646
no_implicit_prelude,
633647
glob_importers: RefCell::new(Vec::new()),
@@ -1087,8 +1101,6 @@ pub struct Resolver<'ra, 'tcx> {
10871101
extern_module_map: RefCell<FxIndexMap<DefId, Module<'ra>>>,
10881102
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
10891103

1090-
underscore_disambiguator: u32,
1091-
10921104
/// Maps glob imports to the names of items actually imported.
10931105
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
10941106
glob_error: Option<ErrorGuaranteed>,
@@ -1500,7 +1512,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15001512
extern_crate_map: Default::default(),
15011513
module_children: Default::default(),
15021514
trait_map: NodeMap::default(),
1503-
underscore_disambiguator: 0,
15041515
empty_module,
15051516
local_module_map,
15061517
extern_module_map: Default::default(),
@@ -1881,17 +1892,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
18811892
import_ids
18821893
}
18831894

1884-
fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
1885-
let ident = ident.normalize_to_macros_2_0();
1886-
let disambiguator = if ident.name == kw::Underscore {
1887-
self.underscore_disambiguator += 1;
1888-
self.underscore_disambiguator
1889-
} else {
1890-
0
1891-
};
1892-
BindingKey { ident, ns, disambiguator }
1893-
}
1894-
18951895
fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
18961896
if module.populate_on_access.get() {
18971897
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
@@ -535,7 +535,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
535535
target_trait.for_each_child(self, |this, ident, ns, _binding| {
536536
// FIXME: Adjust hygiene for idents from globs, like for glob imports.
537537
if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
538-
&& overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns))
538+
&& overriding_keys.contains(&BindingKey::new(ident, ns))
539539
{
540540
// The name is overridden, do not produce it from the glob delegation.
541541
} else {

0 commit comments

Comments
 (0)