From 71177d1b669c32bcf668c81f4840b543f5352435 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 May 2026 10:30:16 +0200 Subject: [PATCH 1/2] Add NodeId to ModuleKind --- .../rustc_resolve/src/build_reduced_graph.rs | 18 ++++++---- compiler/rustc_resolve/src/diagnostics.rs | 28 ++++++++-------- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/late.rs | 3 +- compiler/rustc_resolve/src/lib.rs | 33 ++++++++++++------- compiler/rustc_resolve/src/macros.rs | 2 +- 6 files changed, 51 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4c307e8a6a3d7..524c9ce8ad5d7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,8 +9,9 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem, - ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, DUMMY_NODE_ID, Delegation, Fn, + ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, + TyAlias, }; use rustc_attr_parsing::AttributeParser; use rustc_expand::base::ResolverExpand; @@ -168,7 +169,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let expn_id = self.cstore().expn_that_defined_untracked(self.tcx, def_id); let module = self.new_extern_module( parent, - ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))), + ModuleKind::Def( + def_kind, + def_id, + DUMMY_NODE_ID, + Some(self.tcx.item_name(def_id)), + ), expn_id, self.def_span(def_id), // FIXME: Account for `#[no_implicit_prelude]` attributes. @@ -251,7 +257,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Any inherited visibility resolved directly inside an enum or trait // (i.e. variants, fields, and trait items) inherits from the visibility // of the enum or trait. - ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _) => { + ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _, _) => { self.tcx.visibility(def_id).expect_local() } // Otherwise, the visibility is restricted to the nearest parent `mod` item. @@ -848,7 +854,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } let module = self.r.new_local_module( Some(parent), - ModuleKind::Def(def_kind, def_id, Some(ident.name)), + ModuleKind::Def(def_kind, def_id, item.id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude @@ -882,7 +888,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { let module = self.r.new_local_module( Some(parent), - ModuleKind::Def(def_kind, def_id, Some(ident.name)), + ModuleKind::Def(def_kind, def_id, item.id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7e1dd19167899..f891622d0baea 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -242,7 +242,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let container = match old_binding.parent_module.unwrap().kind { // Avoid using TyCtxt::def_kind_descr in the resolver, because it // indirectly *calls* the resolver, and would cause a query cycle. - ModuleKind::Def(kind, def_id, _) => kind.descr(def_id), + ModuleKind::Def(kind, def_id, _, _) => kind.descr(def_id), ModuleKind::Block => "block", }; @@ -1764,7 +1764,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if ident.name == kw::Default - && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind + && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind { let span = self.def_span(def_id); let source_map = self.tcx.sess.source_map(); @@ -1892,19 +1892,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { missing a `derive` attribute", ident.name, ); - let sugg_span = if let ModuleKind::Def(DefKind::Enum, id, _) = parent_scope.module.kind - { - let span = self.def_span(id); - if span.from_expansion() { - None + let sugg_span = + if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind { + let span = self.def_span(id); + if span.from_expansion() { + None + } else { + // For enum variants sugg_span is empty but we can get the enum's Span. + Some(span.shrink_to_lo()) + } } else { - // For enum variants sugg_span is empty but we can get the enum's Span. - Some(span.shrink_to_lo()) - } - } else { - // For items this `Span` will be populated, everything else it'll be None. - sugg_span - }; + // For items this `Span` will be populated, everything else it'll be None. + sugg_span + }; match sugg_span { Some(span) => { err.span_suggestion_verbose( diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 658e36083b0ad..1c43ca431d8bf 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -644,7 +644,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } Scope::ModuleGlobs(module, _) - if let ModuleKind::Def(_, def_id, _) = module.kind + if let ModuleKind::Def(_, def_id, _, _) = module.kind && !def_id.is_local() => { // Fast path: external module decoding only creates non-glob declarations. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 014a472c2c1bb..29a151b277d55 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1941,7 +1941,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { && let Some((module, _)) = &self.current_trait_ref && let Some(ty) = &self.diag_metadata.current_self_type && Some(true) == self.diag_metadata.in_non_gat_assoc_type - && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind + && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _, _) = + module.kind { if def_id_matches_path( self.r.tcx, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b15e4b1b72774..af9a72b13c1d1 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -543,7 +543,7 @@ enum ModuleKind { /// The crate root will have `None` for the symbol. /// * A trait or an enum (it implicitly contains associated types, methods and variant /// constructors). - Def(DefKind, DefId, Option), + Def(DefKind, DefId, NodeId, Option), } impl ModuleKind { @@ -557,7 +557,7 @@ impl ModuleKind { fn opt_def_id(&self) -> Option { match self { - ModuleKind::Def(_, def_id, _) => Some(*def_id), + ModuleKind::Def(_, def_id, _, _) => Some(*def_id), _ => None, } } @@ -726,7 +726,7 @@ impl<'ra> ModuleData<'ra> { self_decl: Option>, ) -> Self { let is_foreign = match kind { - ModuleKind::Def(_, def_id, _) => !def_id.is_local(), + ModuleKind::Def(_, def_id, _, _) => !def_id.is_local(), ModuleKind::Block => false, }; ModuleData { @@ -756,7 +756,7 @@ impl<'ra> ModuleData<'ra> { fn res(&self) -> Option { match self.kind { - ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), + ModuleKind::Def(kind, def_id, _, _) => Some(Res::Def(kind, def_id)), _ => None, } } @@ -813,11 +813,11 @@ impl<'ra> Module<'ra> { // `self` resolves to the first module ancestor that `is_normal`. fn is_normal(self) -> bool { - matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _)) + matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _, _)) } fn is_trait(self) -> bool { - matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _)) + matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _, _)) } fn nearest_item_scope(self) -> Module<'ra> { @@ -833,11 +833,20 @@ impl<'ra> Module<'ra> { /// This may be the crate root. fn nearest_parent_mod(self) -> DefId { match self.kind { - ModuleKind::Def(DefKind::Mod, def_id, _) => def_id, + ModuleKind::Def(DefKind::Mod, def_id, _, _) => def_id, _ => self.parent.expect("non-root module without parent").nearest_parent_mod(), } } + /// The [`NodeId`] of the nearest `mod` item ancestor (which may be this module). + /// This may be the crate root. + fn nearest_parent_mod_node_id(self) -> NodeId { + match self.kind { + ModuleKind::Def(DefKind::Mod, _, node_id, _) => node_id, + _ => self.parent.expect("non-root module without parent").nearest_parent_mod_node_id(), + } + } + fn is_ancestor_of(self, mut other: Self) -> bool { while self != other { if let Some(parent) = other.parent { @@ -852,7 +861,7 @@ impl<'ra> Module<'ra> { #[track_caller] fn expect_local(self) -> LocalModule<'ra> { match self.kind { - ModuleKind::Def(_, def_id, _) if !def_id.is_local() => { + ModuleKind::Def(_, def_id, _, _) if !def_id.is_local() => { panic!("`Module::expect_local` is called on a non-local module: {self:?}") } ModuleKind::Def(..) | ModuleKind::Block => LocalModule(self.0), @@ -862,7 +871,7 @@ impl<'ra> Module<'ra> { #[track_caller] fn expect_extern(self) -> ExternModule<'ra> { match self.kind { - ModuleKind::Def(_, def_id, _) if !def_id.is_local() => ExternModule(self.0), + ModuleKind::Def(_, def_id, _, _) if !def_id.is_local() => ExternModule(self.0), ModuleKind::Def(..) | ModuleKind::Block => { panic!("`Module::expect_extern` is called on a local module: {self:?}") } @@ -1551,7 +1560,7 @@ impl<'ra> ResolverArenas<'ra> { no_implicit_prelude: bool, ) -> Module<'ra> { let self_decl = match kind { - ModuleKind::Def(def_kind, def_id, _) => Some(self.new_def_decl( + ModuleKind::Def(def_kind, def_id, _, _) => Some(self.new_def_decl( Res::Def(def_kind, def_id), vis, span, @@ -1732,7 +1741,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); let graph_root = arenas.new_module( None, - ModuleKind::Def(DefKind::Mod, root_def_id, None), + ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None), Visibility::Public, ExpnId::root(), crate_span, @@ -1743,7 +1752,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let local_module_map = FxIndexMap::from_iter([(CRATE_DEF_ID, graph_root)]); let empty_module = arenas.new_module( None, - ModuleKind::Def(DefKind::Mod, root_def_id, None), + ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None), Visibility::Public, ExpnId::root(), DUMMY_SP, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index dd9f500ff88d0..d4349b9d73a77 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1185,7 +1185,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.get_mut().record_use(ident, fallback_binding, Used::Other); } else { let location = match parent_scope.module.kind { - ModuleKind::Def(kind, def_id, name) => { + ModuleKind::Def(kind, def_id, _, name) => { if let Some(name) = name { format!("{} `{name}`", kind.descr(def_id)) } else { From fd701b79a71a93a4df5f60262e249e23aa1648cb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 May 2026 10:37:46 +0200 Subject: [PATCH 2/2] Remove most uses of `def_id_to_node_id` Especially those happening during normal resolving, where we are actually looking at current parent scopes --- compiler/rustc_resolve/src/diagnostics.rs | 15 ++++++++------- compiler/rustc_resolve/src/late.rs | 8 ++++---- compiler/rustc_resolve/src/lib.rs | 4 ++-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f891622d0baea..c082455380ce7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -5,7 +5,8 @@ use std::ops::ControlFlow; use itertools::Itertools as _; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path, join_path_idents, + self as ast, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, ItemKind, ModKind, NodeId, Path, + join_path_idents, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -192,11 +193,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn report_with_use_injections(&mut self, krate: &Crate) { - for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in + for UseError { mut err, candidates, node_id, instead, suggestion, path, is_call } in mem::take(&mut self.use_injections) { - let (span, found_use) = if let Some(def_id) = def_id.as_local() { - UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)) + let (span, found_use) = if node_id != DUMMY_NODE_ID { + UsePlacementFinder::check(krate, node_id) } else { (None, FoundUse::No) }; @@ -1705,9 +1706,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let import_suggestions = self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected); - let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() { - Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)), - None => (None, FoundUse::No), + let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() { + DUMMY_NODE_ID => (None, FoundUse::No), + node_id => UsePlacementFinder::check(krate, node_id), }; show_candidates( self.tcx, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 29a151b277d55..3337a4626b040 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4515,7 +4515,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { parent_qself, ); - let def_id = this.parent_scope.module.nearest_parent_mod(); + let node_id = this.parent_scope.module.nearest_parent_mod_node_id(); let instead = res.is_some(); let (suggestion, const_err) = if let Some((start, end)) = this.diag_metadata.in_range @@ -4557,7 +4557,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let ue = UseError { err, candidates, - def_id, + node_id, instead, suggestion, path: path.into(), @@ -4646,7 +4646,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { parent_err.cancel(); - let def_id = this.parent_scope.module.nearest_parent_mod(); + let node_id = this.parent_scope.module.nearest_parent_mod_node_id(); if this.should_report_errs() { if candidates.is_empty() { @@ -4671,7 +4671,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.r.use_injections.push(UseError { err, candidates, - def_id, + node_id, instead: false, suggestion: None, path: prefix_path.into(), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af9a72b13c1d1..f5f063ecaf458 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1001,8 +1001,8 @@ struct UseError<'a> { err: Diag<'a>, /// Candidates which user could `use` to access the missing type. candidates: Vec, - /// The `DefId` of the module to place the use-statements in. - def_id: DefId, + /// The `NodeId` of the module to place the use-statements in. + node_id: NodeId, /// Whether the diagnostic should say "instead" (as in `consider importing ... instead`). instead: bool, /// Extra free-form suggestion.