From a437c0089093155bdf7569244561575b70ac3916 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 14:41:27 +0300 Subject: [PATCH 01/11] resolve: Introduce separate `(Local,Extern)ModuleData` structures for local and external modules respectively --- compiler/rustc_resolve/src/ident.rs | 5 +- compiler/rustc_resolve/src/lib.rs | 125 +++++++++++++++++++--------- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index b33b77d43999d..049df2950a8ca 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -643,10 +643,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Err(ControlFlow::Break(..)) => return decl, } } - Scope::ModuleGlobs(module, _) - if let ModuleKind::Def(_, def_id, _, _) = module.kind - && !def_id.is_local() => - { + Scope::ModuleGlobs(module, _) if !module.kind.is_local() => { // Fast path: external module decoding only creates non-glob declarations. Err(Determined) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 879a4dd3983a6..fea8764e6a4ab 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -61,7 +61,6 @@ use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguator use rustc_hir::{PrimTy, TraitCandidate, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::CStore; -use rustc_middle::bug; use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; @@ -69,6 +68,7 @@ use rustc_middle::ty::{ self, DelegationInfo, MainDefinition, RegisteredTools, ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, }; +use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -561,6 +561,13 @@ impl ModuleKind { _ => None, } } + + fn is_local(&self) -> bool { + match self { + ModuleKind::Def(_, def_id, ..) => def_id.is_local(), + _ => true, + } + } } /// Combination of a symbol and its macros 2.0 normalized hygiene context. @@ -648,8 +655,8 @@ type Resolutions<'ra> = CmRefCell { +/// You can use [`CommonModuleData::kind`] to determine the kind of module this is. +struct CommonModuleData<'ra> { /// The direct parent module (it may not be a `mod`, however). parent: Option>, /// What kind of module this is, because this may not be a `mod`. @@ -687,27 +694,40 @@ struct ModuleData<'ra> { self_decl: Option>, } +#[derive(Hash)] +struct LocalModuleData<'ra> { + common: CommonModuleData<'ra>, +} + +#[derive(Hash)] +struct ExternModuleData<'ra> { + common: CommonModuleData<'ra>, +} + /// All modules are unique and allocated on a same arena, /// so we can use referential equality to compare them. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] -struct Module<'ra>(Interned<'ra, ModuleData<'ra>>); +enum Module<'ra> { + Local(LocalModule<'ra>), + Extern(ExternModule<'ra>), +} /// Same as `Module`, but is guaranteed to be from the current crate. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] -struct LocalModule<'ra>(Interned<'ra, ModuleData<'ra>>); +struct LocalModule<'ra>(Interned<'ra, LocalModuleData<'ra>>); /// Same as `Module`, but is guaranteed to be from an external crate. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] -struct ExternModule<'ra>(Interned<'ra, ModuleData<'ra>>); +struct ExternModule<'ra>(Interned<'ra, ExternModuleData<'ra>>); // Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the // contained data. // FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees // are upheld. -impl std::hash::Hash for ModuleData<'_> { +impl std::hash::Hash for CommonModuleData<'_> { fn hash(&self, _: &mut H) where H: std::hash::Hasher, @@ -716,7 +736,7 @@ impl std::hash::Hash for ModuleData<'_> { } } -impl<'ra> ModuleData<'ra> { +impl<'ra> CommonModuleData<'ra> { fn new( parent: Option>, kind: ModuleKind, @@ -725,11 +745,8 @@ impl<'ra> ModuleData<'ra> { no_implicit_prelude: bool, self_decl: Option>, ) -> Self { - let is_foreign = match kind { - ModuleKind::Def(_, def_id, _, _) => !def_id.is_local(), - ModuleKind::Block => false, - }; - ModuleData { + let is_foreign = !kind.is_local(); + CommonModuleData { parent, kind, lazy_resolutions: Default::default(), @@ -751,7 +768,7 @@ impl<'ra> ModuleData<'ra> { } fn def_id(&self) -> DefId { - self.opt_def_id().expect("`ModuleData::def_id` is called on a block module") + self.opt_def_id().expect("`CommonModuleData::def_id` is called on a block module") } fn res(&self) -> Option { @@ -860,61 +877,76 @@ impl<'ra> Module<'ra> { #[track_caller] fn expect_local(self) -> LocalModule<'ra> { - match self.kind { - 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), + match self { + Module::Local(m) => m, + Module::Extern(m) => span_bug!(m.span, "unexpected extern module: {m:?}"), } } #[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(..) | ModuleKind::Block => { - panic!("`Module::expect_extern` is called on a local module: {self:?}") - } + match self { + Module::Extern(m) => m, + Module::Local(m) => span_bug!(m.span, "unexpected local module: {m:?}"), } } } impl<'ra> LocalModule<'ra> { fn to_module(self) -> Module<'ra> { - Module(self.0) + Module::Local(self) } } impl<'ra> ExternModule<'ra> { fn to_module(self) -> Module<'ra> { - Module(self.0) + Module::Extern(self) } } impl<'ra> std::ops::Deref for Module<'ra> { - type Target = ModuleData<'ra>; + type Target = CommonModuleData<'ra>; fn deref(&self) -> &Self::Target { - &self.0 + match self { + Module::Local(m) => &m.common, + Module::Extern(m) => &m.common, + } } } impl<'ra> std::ops::Deref for LocalModule<'ra> { - type Target = ModuleData<'ra>; + type Target = LocalModuleData<'ra>; fn deref(&self) -> &Self::Target { &self.0 } } +impl<'ra> std::ops::Deref for LocalModuleData<'ra> { + type Target = CommonModuleData<'ra>; + + fn deref(&self) -> &Self::Target { + &self.common + } +} + impl<'ra> std::ops::Deref for ExternModule<'ra> { - type Target = ModuleData<'ra>; + type Target = ExternModuleData<'ra>; fn deref(&self) -> &Self::Target { &self.0 } } +impl<'ra> std::ops::Deref for ExternModuleData<'ra> { + type Target = CommonModuleData<'ra>; + + fn deref(&self) -> &Self::Target { + &self.common + } +} + impl<'ra> fmt::Debug for Module<'ra> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { @@ -930,6 +962,12 @@ impl<'ra> fmt::Debug for LocalModule<'ra> { } } +impl<'ra> fmt::Debug for ExternModule<'ra> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.to_module().fmt(f) + } +} + /// Data associated with any name declaration. #[derive(Clone, Debug)] struct DeclData<'ra> { @@ -1504,7 +1542,8 @@ pub struct Resolver<'ra, 'tcx> { /// used by many types in this crate is an abbreviation of `ResolverArenas`. #[derive(Default)] pub struct ResolverArenas<'ra> { - modules: TypedArena>, + local_modules: TypedArena>, + extern_modules: TypedArena>, imports: TypedArena>, name_resolutions: TypedArena>>, ast_paths: TypedArena, @@ -1554,14 +1593,17 @@ impl<'ra> ResolverArenas<'ra> { } ModuleKind::Block => None, }; - Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( - parent, - kind, - expn_id, - span, - no_implicit_prelude, - self_decl, - )))) + let common = + CommonModuleData::new(parent, kind, expn_id, span, no_implicit_prelude, self_decl); + if common.kind.is_local() { + Module::Local(LocalModule(Interned::new_unchecked( + self.local_modules.alloc(LocalModuleData { common }), + ))) + } else { + Module::Extern(ExternModule(Interned::new_unchecked( + self.extern_modules.alloc(ExternModuleData { common }), + ))) + } } fn alloc_decl(&'ra self, data: DeclData<'ra>) -> Decl<'ra> { Interned::new_unchecked(self.dropless.alloc(data)) @@ -2149,7 +2191,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module.populate_on_access.set(false); self.build_reduced_graph_external(module.expect_extern()); } - &module.0.0.lazy_resolutions + match module { + Module::Local(m) => &m.0.0.lazy_resolutions, + Module::Extern(m) => &m.0.0.lazy_resolutions, + } } fn resolution( From 4bdcc7ae47eda027b84f3cadfe4de7d17476739c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 15:30:26 +0300 Subject: [PATCH 02/11] resolve: Cleanup module construction --- compiler/rustc_resolve/src/lib.rs | 90 +++++++++++++++++-------------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index fea8764e6a4ab..c8b96df3e056c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -740,12 +740,20 @@ impl<'ra> CommonModuleData<'ra> { fn new( parent: Option>, kind: ModuleKind, + vis: Visibility, expansion: ExpnId, span: Span, no_implicit_prelude: bool, - self_decl: Option>, + arenas: &'ra ResolverArenas<'ra>, ) -> Self { let is_foreign = !kind.is_local(); + let self_decl = match kind { + ModuleKind::Def(def_kind, def_id, _, _) => { + let expn_id = expansion.as_local().unwrap_or(LocalExpnId::ROOT); + Some(arenas.new_def_decl(Res::Def(def_kind, def_id), vis, span, expn_id, parent)) + } + ModuleKind::Block => None, + }; CommonModuleData { parent, kind, @@ -893,12 +901,44 @@ impl<'ra> Module<'ra> { } impl<'ra> LocalModule<'ra> { + fn new( + parent: Option>, + kind: ModuleKind, + vis: Visibility, + expn_id: ExpnId, + span: Span, + no_implicit_prelude: bool, + arenas: &'ra ResolverArenas<'ra>, + ) -> LocalModule<'ra> { + assert!(kind.is_local()); + let common = + CommonModuleData::new(parent, kind, vis, expn_id, span, no_implicit_prelude, arenas); + LocalModule(Interned::new_unchecked(arenas.local_modules.alloc(LocalModuleData { common }))) + } + fn to_module(self) -> Module<'ra> { Module::Local(self) } } impl<'ra> ExternModule<'ra> { + fn new( + parent: Option>, + kind: ModuleKind, + vis: Visibility, + expn_id: ExpnId, + span: Span, + no_implicit_prelude: bool, + arenas: &'ra ResolverArenas<'ra>, + ) -> ExternModule<'ra> { + assert!(!kind.is_local()); + let common = + CommonModuleData::new(parent, kind, vis, expn_id, span, no_implicit_prelude, arenas); + ExternModule(Interned::new_unchecked( + arenas.extern_modules.alloc(ExternModuleData { common }), + )) + } + fn to_module(self) -> Module<'ra> { Module::Extern(self) } @@ -1577,34 +1617,6 @@ impl<'ra> ResolverArenas<'ra> { self.new_def_decl(res, Visibility::Public, span, expn_id, None) } - fn new_module( - &'ra self, - parent: Option>, - kind: ModuleKind, - vis: Visibility, - expn_id: ExpnId, - span: Span, - no_implicit_prelude: bool, - ) -> Module<'ra> { - let self_decl = match kind { - ModuleKind::Def(def_kind, def_id, _, _) => { - let expn_id = expn_id.as_local().unwrap_or(LocalExpnId::ROOT); - Some(self.new_def_decl(Res::Def(def_kind, def_id), vis, span, expn_id, parent)) - } - ModuleKind::Block => None, - }; - let common = - CommonModuleData::new(parent, kind, expn_id, span, no_implicit_prelude, self_decl); - if common.kind.is_local() { - Module::Local(LocalModule(Interned::new_unchecked( - self.local_modules.alloc(LocalModuleData { common }), - ))) - } else { - Module::Extern(ExternModule(Interned::new_unchecked( - self.extern_modules.alloc(ExternModuleData { common }), - ))) - } - } fn alloc_decl(&'ra self, data: DeclData<'ra>) -> Decl<'ra> { Interned::new_unchecked(self.dropless.alloc(data)) } @@ -1766,26 +1778,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { arenas: &'ra ResolverArenas<'ra>, ) -> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); - let graph_root = arenas.new_module( + let graph_root = LocalModule::new( None, ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None), Visibility::Public, ExpnId::root(), crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), + arenas, ); - let graph_root = graph_root.expect_local(); let local_modules = vec![graph_root]; let local_module_map = FxIndexMap::from_iter([(CRATE_DEF_ID, graph_root)]); - let empty_module = arenas.new_module( + let empty_module = LocalModule::new( None, ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None), Visibility::Public, ExpnId::root(), DUMMY_SP, true, + arenas, ); - let empty_module = empty_module.expect_local(); let mut node_id_to_def_id = NodeMap::default(); let crate_feed = tcx.create_local_crate_def_id(crate_span); @@ -1885,10 +1897,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let parent = parent.map(|m| m.to_module()); let vis = kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id)); - let module = self - .arenas - .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude) - .expect_local(); + let module = + LocalModule::new(parent, kind, vis, expn_id, span, no_implicit_prelude, self.arenas); self.local_modules.push(module); if let Some(def_id) = module.opt_def_id() { self.local_module_map.insert(def_id.expect_local(), module); @@ -1907,10 +1917,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let parent = parent.map(|m| m.to_module()); let vis = kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id)); - let module = self - .arenas - .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude) - .expect_extern(); + let module = + ExternModule::new(parent, kind, vis, expn_id, span, no_implicit_prelude, self.arenas); self.extern_module_map.borrow_mut().insert(module.def_id(), module); module } From 2e1309f3770a0e1ed0b4041ceabb04c9fc2dd425 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 15:58:23 +0300 Subject: [PATCH 03/11] resolve: Move `underscore_disambiguator` to `LocalModuleData` --- compiler/rustc_resolve/src/lib.rs | 39 ++++++++++++++++--------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c8b96df3e056c..9a87d4b752aea 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -667,8 +667,6 @@ struct CommonModuleData<'ra> { lazy_resolutions: Resolutions<'ra>, /// True if this is a module from other crate that needs to be populated on access. populate_on_access: CacheCell, - /// Used to disambiguate underscore items (`const _: T = ...`) in the module. - underscore_disambiguator: CmCell, /// Macro invocations that can expand into items in this module. unexpanded_invocations: CmRefCell>, @@ -694,12 +692,12 @@ struct CommonModuleData<'ra> { self_decl: Option>, } -#[derive(Hash)] struct LocalModuleData<'ra> { common: CommonModuleData<'ra>, + /// Used to disambiguate underscore items (`const _: T = ...`) in the module. + underscore_disambiguator: CmCell, } -#[derive(Hash)] struct ExternModuleData<'ra> { common: CommonModuleData<'ra>, } @@ -723,19 +721,6 @@ struct LocalModule<'ra>(Interned<'ra, LocalModuleData<'ra>>); #[rustc_pass_by_value] struct ExternModule<'ra>(Interned<'ra, ExternModuleData<'ra>>); -// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the -// contained data. -// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees -// are upheld. -impl std::hash::Hash for CommonModuleData<'_> { - fn hash(&self, _: &mut H) - where - H: std::hash::Hasher, - { - unreachable!() - } -} - impl<'ra> CommonModuleData<'ra> { fn new( parent: Option>, @@ -759,7 +744,6 @@ impl<'ra> CommonModuleData<'ra> { kind, lazy_resolutions: Default::default(), populate_on_access: CacheCell::new(is_foreign), - underscore_disambiguator: CmCell::new(0), unexpanded_invocations: Default::default(), no_implicit_prelude, glob_importers: CmRefCell::new(Vec::new()), @@ -913,7 +897,8 @@ impl<'ra> LocalModule<'ra> { assert!(kind.is_local()); let common = CommonModuleData::new(parent, kind, vis, expn_id, span, no_implicit_prelude, arenas); - LocalModule(Interned::new_unchecked(arenas.local_modules.alloc(LocalModuleData { common }))) + let data = LocalModuleData { common, underscore_disambiguator: CmCell::new(0) }; + LocalModule(Interned::new_unchecked(arenas.local_modules.alloc(data))) } fn to_module(self) -> Module<'ra> { @@ -1008,6 +993,22 @@ impl<'ra> fmt::Debug for ExternModule<'ra> { } } +// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the +// contained data. +// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees +// are upheld. +impl std::hash::Hash for LocalModuleData<'_> { + fn hash(&self, _: &mut H) { + unreachable!() + } +} + +impl std::hash::Hash for ExternModuleData<'_> { + fn hash(&self, _: &mut H) { + unreachable!() + } +} + /// Data associated with any name declaration. #[derive(Clone, Debug)] struct DeclData<'ra> { From fbccce531ece73981ef3f6c240293464b66f4065 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 16:26:20 +0300 Subject: [PATCH 04/11] resolve: Move `unexpanded_invocations` to `LocalModuleData` --- .../rustc_resolve/src/build_reduced_graph.rs | 3 +- compiler/rustc_resolve/src/ident.rs | 19 +++++---- compiler/rustc_resolve/src/lib.rs | 40 ++++++++++++------- compiler/rustc_resolve/src/macros.rs | 5 ++- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 61da931df4d5d..8419fc7257bf2 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1247,7 +1247,8 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { /// directly into its parent scope's module. pub(crate) fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'ra> { let invoc_id = self.visit_invoc(id); - self.parent_scope.module.unexpanded_invocations.borrow_mut(self.r).insert(invoc_id); + let module = self.parent_scope.module.expect_local(); + module.unexpanded_invocations.borrow_mut(self.r).insert(invoc_id); self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id)) } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 049df2950a8ca..41a41e32f9297 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -696,9 +696,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() { Some(decl) => Ok(decl), - None => Err(Determinacy::determined( - self.graph_root.unexpanded_invocations.borrow().is_empty(), - )), + None => Err(Determinacy::determined(!self.graph_root.has_unexpanded_invocations())), }, Scope::BuiltinAttrs => match self.builtin_attr_decls.get(&ident.name) { Some(decl) => Ok(*decl), @@ -711,9 +709,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.is_some(), ) { Some(decl) => Ok(decl), - None => Err(Determinacy::determined( - self.graph_root.unexpanded_invocations.borrow().is_empty(), - )), + None => { + Err(Determinacy::determined(!self.graph_root.has_unexpanded_invocations())) + } } } Scope::ExternPreludeFlags => { @@ -1123,6 +1121,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) }; } + // In extern modules everything is determined from the start. + let Some(module) = module.as_local() else { + return Err(ControlFlow::Continue(Determined)); + }; + // Check if one of single imports can still define the name, block if it can. if self.reborrow().single_import_can_define_name( &resolution, @@ -1136,7 +1139,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Check if one of unexpanded macros can still define the name. - if !module.unexpanded_invocations.borrow().is_empty() { + if module.has_unexpanded_invocations() { return Err(ControlFlow::Continue(Undetermined)); } @@ -1220,7 +1223,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // scopes we return `Undetermined` with `ControlFlow::Continue`. // Check if one of unexpanded macros can still define the name, // if it can then our "no resolution" result is not determined and can be invalidated. - if !module.unexpanded_invocations.borrow().is_empty() { + if module.has_unexpanded_invocations() { return Err(ControlFlow::Continue(Undetermined)); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9a87d4b752aea..55f2aee72ed25 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -661,32 +661,22 @@ struct CommonModuleData<'ra> { parent: Option>, /// What kind of module this is, because this may not be a `mod`. kind: ModuleKind, - /// Mapping between names and their (possibly in-progress) resolutions in this module. /// Resolutions in modules from other crates are not populated until accessed. lazy_resolutions: Resolutions<'ra>, /// True if this is a module from other crate that needs to be populated on access. populate_on_access: CacheCell, - - /// Macro invocations that can expand into items in this module. - unexpanded_invocations: CmRefCell>, - /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - glob_importers: CmRefCell>>, globs: CmRefCell>>, - /// Used to memoize the traits in this module for faster searches through all traits in scope. traits: CmRefCell< Option, Option>, bool /* lint ambiguous */)]>>, >, - /// Span of the module itself. Used for error reporting. span: Span, - expansion: ExpnId, - /// Declaration for implicitly declared names that come with a module, /// like `self` (not yet used), or `crate`/`$crate` (for root modules). self_decl: Option>, @@ -696,6 +686,8 @@ struct LocalModuleData<'ra> { common: CommonModuleData<'ra>, /// Used to disambiguate underscore items (`const _: T = ...`) in the module. underscore_disambiguator: CmCell, + /// Macro invocations that can expand into items in this module. + unexpanded_invocations: CmRefCell>, } struct ExternModuleData<'ra> { @@ -744,7 +736,6 @@ impl<'ra> CommonModuleData<'ra> { kind, lazy_resolutions: Default::default(), populate_on_access: CacheCell::new(is_foreign), - unexpanded_invocations: Default::default(), no_implicit_prelude, glob_importers: CmRefCell::new(Vec::new()), globs: CmRefCell::new(Vec::new()), @@ -867,6 +858,13 @@ impl<'ra> Module<'ra> { true } + fn as_local(self) -> Option> { + match self { + Module::Local(m) => Some(m), + Module::Extern(_) => None, + } + } + #[track_caller] fn expect_local(self) -> LocalModule<'ra> { match self { @@ -882,6 +880,13 @@ impl<'ra> Module<'ra> { Module::Local(m) => span_bug!(m.span, "unexpected local module: {m:?}"), } } + + fn has_unexpanded_invocations(self) -> bool { + match self { + Module::Local(m) => m.has_unexpanded_invocations(), + Module::Extern(_) => false, + } + } } impl<'ra> LocalModule<'ra> { @@ -897,13 +902,21 @@ impl<'ra> LocalModule<'ra> { assert!(kind.is_local()); let common = CommonModuleData::new(parent, kind, vis, expn_id, span, no_implicit_prelude, arenas); - let data = LocalModuleData { common, underscore_disambiguator: CmCell::new(0) }; + let data = LocalModuleData { + common, + underscore_disambiguator: CmCell::new(0), + unexpanded_invocations: Default::default(), + }; LocalModule(Interned::new_unchecked(arenas.local_modules.alloc(data))) } fn to_module(self) -> Module<'ra> { Module::Local(self) } + + fn has_unexpanded_invocations(self) -> bool { + !self.unexpanded_invocations.borrow().is_empty() + } } impl<'ra> ExternModule<'ra> { @@ -1287,8 +1300,7 @@ impl<'ra> DeclData<'ra> { fn determined(&self) -> bool { match &self.kind { DeclKind::Import { source_decl, import, .. } if import.is_glob() => { - import.parent_scope.module.unexpanded_invocations.borrow().is_empty() - && source_decl.determined() + !import.parent_scope.module.has_unexpanded_invocations() && source_decl.determined() } _ => true, } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index f4464138ef1fc..163ddcc0329c0 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -193,7 +193,8 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { let output_macro_rules_scope = collect_definitions(self, fragment, parent_scope); self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope); - parent_scope.module.unexpanded_invocations.borrow_mut(self).remove(&expansion); + let module = parent_scope.module.expect_local(); + module.unexpanded_invocations.borrow_mut(self).remove(&expansion); if let Some(unexpanded_invocations) = self.impl_unexpanded_invocations.get_mut(&self.invocation_parent(expansion)) { @@ -523,7 +524,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { star_span: Span, ) -> Result)>, Indeterminate> { let target_trait = self.expect_module(trait_def_id); - if !target_trait.unexpanded_invocations.borrow().is_empty() { + if target_trait.has_unexpanded_invocations() { return Err(Indeterminate); } // FIXME: Instead of waiting try generating all trait methods, and pruning From 8604b087386c615913c49e5b7bd39ff01ac57086 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 16:50:49 +0300 Subject: [PATCH 05/11] resolve: Move `glob_importers` to `LocalModuleData` --- compiler/rustc_resolve/src/diagnostics.rs | 26 ++++++++++++----------- compiler/rustc_resolve/src/imports.rs | 4 +++- compiler/rustc_resolve/src/lib.rs | 4 ++-- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5e52ebcc3f194..b871515ad565c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3290,20 +3290,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return cached; } visited.insert(parent_module, false); - let m = r.expect_module(parent_module); let mut res = false; - for importer in m.glob_importers.borrow().iter() { - if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() { - if next_parent_module == module - || comes_from_same_module_for_glob( - r, - next_parent_module, - module, - visited, - ) + if let Some(m) = r.expect_module(parent_module).as_local() { + for importer in m.glob_importers.borrow().iter() { + if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() { - res = true; - break; + if next_parent_module == module + || comes_from_same_module_for_glob( + r, + next_parent_module, + module, + visited, + ) + { + res = true; + break; + } } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b16347af7ba0c..747b0b8020e65 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1790,7 +1790,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Add to module's glob_importers - module.glob_importers.borrow_mut_unchecked().push(import); + if let Some(module) = module.as_local() { + module.glob_importers.borrow_mut_unchecked().push(import); + } // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 55f2aee72ed25..a4231565d423c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -668,7 +668,6 @@ struct CommonModuleData<'ra> { populate_on_access: CacheCell, /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - glob_importers: CmRefCell>>, globs: CmRefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. traits: CmRefCell< @@ -688,6 +687,7 @@ struct LocalModuleData<'ra> { underscore_disambiguator: CmCell, /// Macro invocations that can expand into items in this module. unexpanded_invocations: CmRefCell>, + glob_importers: CmRefCell>>, } struct ExternModuleData<'ra> { @@ -737,7 +737,6 @@ impl<'ra> CommonModuleData<'ra> { lazy_resolutions: Default::default(), populate_on_access: CacheCell::new(is_foreign), no_implicit_prelude, - glob_importers: CmRefCell::new(Vec::new()), globs: CmRefCell::new(Vec::new()), traits: CmRefCell::new(None), span, @@ -906,6 +905,7 @@ impl<'ra> LocalModule<'ra> { common, underscore_disambiguator: CmCell::new(0), unexpanded_invocations: Default::default(), + glob_importers: Default::default(), }; LocalModule(Interned::new_unchecked(arenas.local_modules.alloc(data))) } From de550df1667067d211942103883b94b34a9b1745 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 17:32:43 +0300 Subject: [PATCH 06/11] resolve: Move `globs` to `LocalModuleData` --- compiler/rustc_resolve/src/build_reduced_graph.rs | 4 ++-- compiler/rustc_resolve/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 8419fc7257bf2..d65445f37546d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -535,7 +535,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { root_id: NodeId, vis: Visibility, ) { - let current_module = self.parent_scope.module; + let current_module = self.parent_scope.module.expect_local(); let import = self.r.arenas.alloc_import(ImportData { kind, parent_scope: self.parent_scope, @@ -560,7 +560,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { if target.name != kw::Underscore { self.r.per_ns(|this, ns| { let key = BindingKey::new(IdentKey::new(target), ns); - this.resolution_or_default(current_module, key, target.span) + this.resolution_or_default(current_module.to_module(), key, target.span) .borrow_mut(this) .single_imports .insert(import); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index a4231565d423c..17a1bb0ac0114 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -668,7 +668,6 @@ struct CommonModuleData<'ra> { populate_on_access: CacheCell, /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - globs: CmRefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. traits: CmRefCell< Option, Option>, bool /* lint ambiguous */)]>>, @@ -688,6 +687,7 @@ struct LocalModuleData<'ra> { /// Macro invocations that can expand into items in this module. unexpanded_invocations: CmRefCell>, glob_importers: CmRefCell>>, + globs: CmRefCell>>, } struct ExternModuleData<'ra> { @@ -737,7 +737,6 @@ impl<'ra> CommonModuleData<'ra> { lazy_resolutions: Default::default(), populate_on_access: CacheCell::new(is_foreign), no_implicit_prelude, - globs: CmRefCell::new(Vec::new()), traits: CmRefCell::new(None), span, expansion, @@ -906,6 +905,7 @@ impl<'ra> LocalModule<'ra> { underscore_disambiguator: CmCell::new(0), unexpanded_invocations: Default::default(), glob_importers: Default::default(), + globs: Default::default(), }; LocalModule(Interned::new_unchecked(arenas.local_modules.alloc(data))) } From 344faa7d1e461359074403f6fd945e8995c03b9a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 18:01:17 +0300 Subject: [PATCH 07/11] resolve: Move `populate_on_access` to `ExternModuleData` --- compiler/rustc_resolve/src/lib.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 17a1bb0ac0114..5c887fd01a33f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -664,8 +664,6 @@ struct CommonModuleData<'ra> { /// Mapping between names and their (possibly in-progress) resolutions in this module. /// Resolutions in modules from other crates are not populated until accessed. lazy_resolutions: Resolutions<'ra>, - /// True if this is a module from other crate that needs to be populated on access. - populate_on_access: CacheCell, /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, /// Used to memoize the traits in this module for faster searches through all traits in scope. @@ -692,6 +690,8 @@ struct LocalModuleData<'ra> { struct ExternModuleData<'ra> { common: CommonModuleData<'ra>, + /// True if this is a module from other crate that needs to be populated on access. + populate_on_access: CacheCell, } /// All modules are unique and allocated on a same arena, @@ -723,7 +723,6 @@ impl<'ra> CommonModuleData<'ra> { no_implicit_prelude: bool, arenas: &'ra ResolverArenas<'ra>, ) -> Self { - let is_foreign = !kind.is_local(); let self_decl = match kind { ModuleKind::Def(def_kind, def_id, _, _) => { let expn_id = expansion.as_local().unwrap_or(LocalExpnId::ROOT); @@ -735,7 +734,6 @@ impl<'ra> CommonModuleData<'ra> { parent, kind, lazy_resolutions: Default::default(), - populate_on_access: CacheCell::new(is_foreign), no_implicit_prelude, traits: CmRefCell::new(None), span, @@ -932,9 +930,8 @@ impl<'ra> ExternModule<'ra> { assert!(!kind.is_local()); let common = CommonModuleData::new(parent, kind, vis, expn_id, span, no_implicit_prelude, arenas); - ExternModule(Interned::new_unchecked( - arenas.extern_modules.alloc(ExternModuleData { common }), - )) + let data = ExternModuleData { common, populate_on_access: CacheCell::new(true) }; + ExternModule(Interned::new_unchecked(arenas.extern_modules.alloc(data))) } fn to_module(self) -> Module<'ra> { @@ -2208,13 +2205,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn resolutions(&self, module: Module<'ra>) -> &'ra Resolutions<'ra> { - if module.populate_on_access.get() { - module.populate_on_access.set(false); - self.build_reduced_graph_external(module.expect_extern()); - } match module { Module::Local(m) => &m.0.0.lazy_resolutions, - Module::Extern(m) => &m.0.0.lazy_resolutions, + Module::Extern(m) => { + if m.populate_on_access.get() { + m.populate_on_access.set(false); + self.build_reduced_graph_external(m); + } + &m.0.0.lazy_resolutions + } } } From ef2a51214df85acad842c6f731d0a40521ee2dbc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 18:35:37 +0300 Subject: [PATCH 08/11] resolve: Move `parent` to `(Local,Extern)ModuleData` --- .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 6 +-- compiler/rustc_resolve/src/lib.rs | 46 +++++++++++-------- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index d65445f37546d..fb4a2c940ad63 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1136,7 +1136,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { if let Some(Attribute::Parsed(AttributeKind::MacroUse { span, arguments })) = AttributeParser::parse_limited(self.r.tcx.sess, &item.attrs, &[sym::macro_use]) { - if self.parent_scope.module.parent.is_some() { + if self.parent_scope.module.expect_local().parent.is_some() { self.r .dcx() .emit_err(errors::ExternCrateLoadingMacroNotAtCrateRoot { span: item.span }); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index b871515ad565c..bf4fb15079a0b 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3128,7 +3128,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return None; }; - while let Some(parent) = crate_module.parent { + while let Some(parent) = crate_module.parent() { crate_module = parent; } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 41a41e32f9297..1b4403e9762f6 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -248,7 +248,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if let ModuleKind::Block = module.kind { - return Some((module.parent.unwrap().nearest_item_scope(), None)); + return Some((module.parent().unwrap().nearest_item_scope(), None)); } // We need to support the next case under a deprecation warning @@ -263,7 +263,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // ``` // So we have to fall back to the module's parent during lexical resolution in this case. if derive_fallback_lint_id.is_some() - && let Some(parent) = module.parent + && let Some(parent) = module.parent() // Inner module is inside the macro && module.expansion != parent.expansion // Parent module is outside of the macro @@ -961,7 +961,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); module .unwrap_or_else(|| self.resolve_self(&mut ctxt, parent_scope.module)) - .parent + .parent() .map(|parent| self.resolve_self(&mut ctxt, parent)) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 5c887fd01a33f..ce7c2cbe5e97e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -657,8 +657,6 @@ type Resolutions<'ra> = CmRefCell { - /// The direct parent module (it may not be a `mod`, however). - parent: Option>, /// What kind of module this is, because this may not be a `mod`. kind: ModuleKind, /// Mapping between names and their (possibly in-progress) resolutions in this module. @@ -680,6 +678,8 @@ struct CommonModuleData<'ra> { struct LocalModuleData<'ra> { common: CommonModuleData<'ra>, + /// The direct parent module (it may not be a `mod`, however). + parent: Option>, /// Used to disambiguate underscore items (`const _: T = ...`) in the module. underscore_disambiguator: CmCell, /// Macro invocations that can expand into items in this module. @@ -690,6 +690,8 @@ struct LocalModuleData<'ra> { struct ExternModuleData<'ra> { common: CommonModuleData<'ra>, + /// The direct parent module (it may not be a `mod`, however). + parent: Option>, /// True if this is a module from other crate that needs to be populated on access. populate_on_access: CacheCell, } @@ -715,7 +717,6 @@ struct ExternModule<'ra>(Interned<'ra, ExternModuleData<'ra>>); impl<'ra> CommonModuleData<'ra> { fn new( - parent: Option>, kind: ModuleKind, vis: Visibility, expansion: ExpnId, @@ -731,7 +732,6 @@ impl<'ra> CommonModuleData<'ra> { ModuleKind::Block => None, }; CommonModuleData { - parent, kind, lazy_resolutions: Default::default(), no_implicit_prelude, @@ -819,7 +819,7 @@ impl<'ra> Module<'ra> { fn nearest_item_scope(self) -> Module<'ra> { match self.kind { ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => { - self.parent.expect("enum or trait module without a parent") + self.parent().expect("enum or trait module without a parent") } _ => self, } @@ -830,7 +830,7 @@ impl<'ra> Module<'ra> { fn nearest_parent_mod(self) -> DefId { match self.kind { ModuleKind::Def(DefKind::Mod, def_id, _, _) => def_id, - _ => self.parent.expect("non-root module without parent").nearest_parent_mod(), + _ => self.parent().expect("non-root module without parent").nearest_parent_mod(), } } @@ -839,13 +839,15 @@ impl<'ra> Module<'ra> { 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(), + _ => { + 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 { + if let Some(parent) = other.parent() { other = parent; } else { return false; @@ -883,11 +885,18 @@ impl<'ra> Module<'ra> { Module::Extern(_) => false, } } + + fn parent(self) -> Option> { + match self { + Module::Local(m) => m.parent.map(Module::Local), + Module::Extern(m) => m.parent.map(Module::Extern), + } + } } impl<'ra> LocalModule<'ra> { fn new( - parent: Option>, + parent: Option>, kind: ModuleKind, vis: Visibility, expn_id: ExpnId, @@ -896,10 +905,10 @@ impl<'ra> LocalModule<'ra> { arenas: &'ra ResolverArenas<'ra>, ) -> LocalModule<'ra> { assert!(kind.is_local()); - let common = - CommonModuleData::new(parent, kind, vis, expn_id, span, no_implicit_prelude, arenas); + let common = CommonModuleData::new(kind, vis, expn_id, span, no_implicit_prelude, arenas); let data = LocalModuleData { common, + parent, underscore_disambiguator: CmCell::new(0), unexpanded_invocations: Default::default(), glob_importers: Default::default(), @@ -919,7 +928,7 @@ impl<'ra> LocalModule<'ra> { impl<'ra> ExternModule<'ra> { fn new( - parent: Option>, + parent: Option>, kind: ModuleKind, vis: Visibility, expn_id: ExpnId, @@ -928,9 +937,8 @@ impl<'ra> ExternModule<'ra> { arenas: &'ra ResolverArenas<'ra>, ) -> ExternModule<'ra> { assert!(!kind.is_local()); - let common = - CommonModuleData::new(parent, kind, vis, expn_id, span, no_implicit_prelude, arenas); - let data = ExternModuleData { common, populate_on_access: CacheCell::new(true) }; + let common = CommonModuleData::new(kind, vis, expn_id, span, no_implicit_prelude, arenas); + let data = ExternModuleData { common, parent, populate_on_access: CacheCell::new(true) }; ExternModule(Interned::new_unchecked(arenas.extern_modules.alloc(data))) } @@ -1904,7 +1912,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, no_implicit_prelude: bool, ) -> LocalModule<'ra> { - let parent = parent.map(|m| m.to_module()); let vis = kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id)); let module = @@ -1924,7 +1931,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, no_implicit_prelude: bool, ) -> ExternModule<'ra> { - let parent = parent.map(|m| m.to_module()); let vis = kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id)); let module = @@ -2415,7 +2421,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn resolve_self(&self, ctxt: &mut SyntaxContext, module: Module<'ra>) -> Module<'ra> { let mut module = self.expect_module(module.nearest_parent_mod()); while module.span.ctxt().normalize_to_macros_2_0() != *ctxt { - let parent = module.parent.unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark())); + let parent = module.parent().unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark())); module = self.expect_module(parent.nearest_parent_mod()); } module @@ -2752,7 +2758,7 @@ fn module_to_string(mut module: Module<'_>) -> Option { let mut names = Vec::new(); loop { if let ModuleKind::Def(.., name) = module.kind { - if let Some(parent) = module.parent { + if let Some(parent) = module.parent() { // `unwrap` is safe: the presence of a parent means it's not the crate root. names.push(name.unwrap()); module = parent @@ -2761,7 +2767,7 @@ fn module_to_string(mut module: Module<'_>) -> Option { } } else { names.push(sym::opaque_module_name_placeholder); - let Some(parent) = module.parent else { + let Some(parent) = module.parent() else { return None; }; module = parent; From 9c3c4b984312ecfa32a50dbfbabfbc59198aecec Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 9 May 2026 14:54:02 +0300 Subject: [PATCH 09/11] resolve: Move `kind` to `(Local,Extern)ModuleData` --- .../rustc_resolve/src/build_reduced_graph.rs | 18 +- compiler/rustc_resolve/src/diagnostics.rs | 18 +- compiler/rustc_resolve/src/ident.rs | 10 +- compiler/rustc_resolve/src/imports.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 13 +- compiler/rustc_resolve/src/lib.rs | 189 ++++++++++-------- compiler/rustc_resolve/src/macros.rs | 7 +- 8 files changed, 140 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index fb4a2c940ad63..184ec2b8d0336 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,9 +9,8 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ConstItem, DUMMY_NODE_ID, Delegation, Fn, - ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, - TyAlias, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem, + ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias, }; use rustc_attr_parsing::AttributeParser; use rustc_expand::base::{ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; @@ -168,12 +167,9 @@ 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, - DUMMY_NODE_ID, - Some(self.tcx.item_name(def_id)), - ), + def_kind, + def_id, + self.tcx.item_name(def_id), expn_id, self.def_span(def_id), // FIXME: Account for `#[no_implicit_prelude]` attributes. @@ -253,7 +249,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match vis.kind { ast::VisibilityKind::Public => Ok(Visibility::Public), ast::VisibilityKind::Inherited => { - Ok(match parent_scope.module.kind { + Ok(match parent_scope.module.expect_local().kind { // 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. @@ -350,7 +346,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub(crate) fn build_reduced_graph_external(&self, module: ExternModule<'ra>) { - let def_id = module.def_id(); + let def_id = module.def_id; let children = self.tcx.module_children(def_id); for (i, child) in children.iter().enumerate() { self.build_reduced_graph_for_external_crate_res(child, module, i, None) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bf4fb15079a0b..a63fca73a4cf1 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -240,7 +240,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return self.report_conflict(ident, ns, new_binding, old_binding); } - let container = match old_binding.parent_module.unwrap().kind { + let container = match old_binding.parent_module.unwrap().expect_local().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), @@ -1757,7 +1757,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } return; } - if Some(parent_nearest) == scope.opt_def_id() { + if Some(parent_nearest) == scope.kind.opt_def_id() { err.subdiagnostic(MacroDefinedLater { span: unused_ident.span }); err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident }); return; @@ -1765,7 +1765,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(); @@ -1894,7 +1894,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident.name, ); let sugg_span = - if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind { + if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind() { let span = self.def_span(id); if span.from_expansion() { None @@ -2607,7 +2607,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module = module.to_module(); current_module.is_ancestor_of(module) && current_module != module }) - .flat_map(|(_, module)| module.kind.name()), + .map(|(_, module)| module.name), ) .filter(|c| !c.to_string().is_empty()) .collect::>(); @@ -2631,8 +2631,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> (String, String, Option) { let is_last = failed_segment_idx == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; - let module_res = match module { - Some(ModuleOrUniformRoot::Module(module)) => module.res(), + let module_def_id = match module { + Some(ModuleOrUniformRoot::Module(module)) => module.opt_def_id(), _ => None, }; let scope = match &path[..failed_segment_idx] { @@ -2647,7 +2647,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let message = format!("cannot find `{ident}` in {scope}"); - if module_res == self.graph_root.res() { + if module_def_id == Some(CRATE_DEF_ID.to_def_id()) { let is_mod = |res| matches!(res, Res::Def(DefKind::Mod, _)); let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod); candidates @@ -3145,7 +3145,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if !kinds.contains(MacroKinds::BANG) { return None; } - let module_name = crate_module.kind.name().unwrap_or(kw::Crate); + let module_name = crate_module.name().unwrap_or(kw::Crate); let import_snippet = match import.kind { ImportKind::Single { source, target, .. } if source != target => { format!("{source} as {target}") diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 1b4403e9762f6..5fa2956a0a80d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -247,7 +247,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return Some((self.expn_def_scope(expn_id), None)); } - if let ModuleKind::Block = module.kind { + if let ModuleKind::Block = module.kind() { return Some((module.parent().unwrap().nearest_item_scope(), None)); } @@ -643,11 +643,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Err(ControlFlow::Break(..)) => return decl, } } - Scope::ModuleGlobs(module, _) if !module.kind.is_local() => { + Scope::ModuleGlobs(Module::Extern(_), _) => { // Fast path: external module decoding only creates non-glob declarations. Err(Determined) } - Scope::ModuleGlobs(module, derive_fallback_lint_id) => { + Scope::ModuleGlobs(Module::Local(module), derive_fallback_lint_id) => { let (adjusted_parent_scope, adjusted_finalize) = if matches!( scope_set, ScopeSet::Module(..) | ScopeSet::ModuleAndExternPrelude(..) @@ -655,12 +655,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (parent_scope, finalize) } else { ( - &ParentScope { module, ..*parent_scope }, + &ParentScope { module: module.to_module(), ..*parent_scope }, finalize.map(|f| Finalize { used: Used::Scope, ..f }), ) }; let binding = self.reborrow().resolve_ident_in_module_globs_unadjusted( - module.expect_local(), + module, ident, orig_ident_span, ns, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 747b0b8020e65..462516836e3ae 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1846,7 +1846,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Since import resolution is finished, globs will not define any more names. *module.globs.borrow_mut(self) = Vec::new(); - let Some(def_id) = module.opt_def_id() else { return }; + let Some(def_id) = module.kind.opt_def_id() else { return }; let mut children = Vec::new(); let mut ambig_children = Vec::new(); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 3337a4626b040..d2767c5e36545 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1942,7 +1942,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { && 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 + module.kind() { if def_id_matches_path( self.r.tcx, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 6f86759d46c5f..d7ce4f731e21b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -38,8 +38,8 @@ use crate::late::{ }; use crate::ty::fast_reject::SimplifiedType; use crate::{ - Finalize, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PathSource, Res, - Resolver, ScopeSet, Segment, errors, path_names_to_string, + Finalize, Module, ModuleOrUniformRoot, ParentScope, PathResult, PathSource, Res, Resolver, + ScopeSet, Segment, errors, path_names_to_string, }; /// A field or associated item from self type suggested in case of resolution failure. @@ -1698,7 +1698,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && let TyKind::Path(_, self_ty_path) = &self_ty.kind && let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(&Segment::from_path(self_ty_path), Some(TypeNS), None, source) - && let ModuleKind::Def(DefKind::Trait, ..) = module.kind + && module.def_kind() == Some(DefKind::Trait) && trait_ref.path.span == span && let PathSource::Trait(_) = source && let Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) = res @@ -3014,12 +3014,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn find_module(&self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> { let mut result = None; let mut seen_modules = FxHashSet::default(); - let root_did = self.r.graph_root.def_id(); - let mut worklist = vec![( - self.r.graph_root.to_module(), - ThinVec::new(), - root_did.is_local() || !self.r.tcx.is_doc_hidden(root_did), - )]; + let mut worklist = vec![(self.r.graph_root.to_module(), ThinVec::new(), true)]; while let Some((in_module, path_segments, doc_visible)) = worklist.pop() { // abort if the module is already found diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ce7c2cbe5e97e..9a9ad5f006900 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -39,8 +39,8 @@ use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::{ - self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, Expr, ExprKind, GenericArg, GenericArgs, - Generics, NodeId, Path, attr, + self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind, + GenericArg, GenericArgs, Generics, NodeId, Path, attr, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default}; use rustc_data_structures::intern::Interned; @@ -519,7 +519,7 @@ impl<'ra> PathResult<'ra> { } } -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] enum ModuleKind { /// An anonymous module; e.g., just a block. /// @@ -561,13 +561,6 @@ impl ModuleKind { _ => None, } } - - fn is_local(&self) -> bool { - match self { - ModuleKind::Def(_, def_id, ..) => def_id.is_local(), - _ => true, - } - } } /// Combination of a symbol and its macros 2.0 normalized hygiene context. @@ -655,10 +648,8 @@ type Resolutions<'ra> = CmRefCell { - /// What kind of module this is, because this may not be a `mod`. - kind: ModuleKind, /// Mapping between names and their (possibly in-progress) resolutions in this module. /// Resolutions in modules from other crates are not populated until accessed. lazy_resolutions: Resolutions<'ra>, @@ -678,6 +669,8 @@ struct CommonModuleData<'ra> { struct LocalModuleData<'ra> { common: CommonModuleData<'ra>, + /// What kind of module this is, because this may not be a `mod`. + kind: ModuleKind, /// The direct parent module (it may not be a `mod`, however). parent: Option>, /// Used to disambiguate underscore items (`const _: T = ...`) in the module. @@ -690,6 +683,9 @@ struct LocalModuleData<'ra> { struct ExternModuleData<'ra> { common: CommonModuleData<'ra>, + def_kind: DefKind, + def_id: DefId, + name: Symbol, /// The direct parent module (it may not be a `mod`, however). parent: Option>, /// True if this is a module from other crate that needs to be populated on access. @@ -717,22 +713,12 @@ struct ExternModule<'ra>(Interned<'ra, ExternModuleData<'ra>>); impl<'ra> CommonModuleData<'ra> { fn new( - kind: ModuleKind, - vis: Visibility, expansion: ExpnId, span: Span, no_implicit_prelude: bool, - arenas: &'ra ResolverArenas<'ra>, + self_decl: Option>, ) -> Self { - let self_decl = match kind { - ModuleKind::Def(def_kind, def_id, _, _) => { - let expn_id = expansion.as_local().unwrap_or(LocalExpnId::ROOT); - Some(arenas.new_def_decl(Res::Def(def_kind, def_id), vis, span, expn_id, parent)) - } - ModuleKind::Block => None, - }; CommonModuleData { - kind, lazy_resolutions: Default::default(), no_implicit_prelude, traits: CmRefCell::new(None), @@ -741,21 +727,6 @@ impl<'ra> CommonModuleData<'ra> { self_decl, } } - - fn opt_def_id(&self) -> Option { - self.kind.opt_def_id() - } - - fn def_id(&self) -> DefId { - self.opt_def_id().expect("`CommonModuleData::def_id` is called on a block module") - } - - fn res(&self) -> Option { - match self.kind { - ModuleKind::Def(kind, def_id, _, _) => Some(Res::Def(kind, def_id)), - _ => None, - } - } } impl<'ra> Module<'ra> { @@ -809,16 +780,16 @@ 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, _, _, _)) + self.def_kind() == Some(DefKind::Mod) } fn is_trait(self) -> bool { - matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _, _)) + matches!(self.def_kind(), Some(DefKind::Trait)) } fn nearest_item_scope(self) -> Module<'ra> { - match self.kind { - ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => { + match self.def_kind() { + Some(DefKind::Enum | DefKind::Trait) => { self.parent().expect("enum or trait module without a parent") } _ => self, @@ -828,7 +799,7 @@ impl<'ra> Module<'ra> { /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module). /// This may be the crate root. fn nearest_parent_mod(self) -> DefId { - match self.kind { + match self.kind() { ModuleKind::Def(DefKind::Mod, def_id, _, _) => def_id, _ => self.parent().expect("non-root module without parent").nearest_parent_mod(), } @@ -837,7 +808,7 @@ impl<'ra> Module<'ra> { /// 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 { + match self.kind() { ModuleKind::Def(DefKind::Mod, _, node_id, _) => node_id, _ => { self.parent().expect("non-root module without parent").nearest_parent_mod_node_id() @@ -892,6 +863,49 @@ impl<'ra> Module<'ra> { Module::Extern(m) => m.parent.map(Module::Extern), } } + + #[inline] + fn kind(self) -> ModuleKind { + match self { + Module::Local(m) => m.kind, + Module::Extern(m) => ModuleKind::Def(m.def_kind, m.def_id, DUMMY_NODE_ID, Some(m.name)), + } + } + + fn opt_def_id(self) -> Option { + match self { + Module::Local(m) => m.kind.opt_def_id(), + Module::Extern(m) => Some(m.def_id), + } + } + + fn def_id(self) -> DefId { + self.opt_def_id().expect("`Module::def_id` is called on a block module") + } + + fn res(self) -> Option { + match self.kind() { + ModuleKind::Def(kind, def_id, _, _) => Some(Res::Def(kind, def_id)), + _ => None, + } + } + + fn name(self) -> Option { + match self { + Module::Local(m) => m.kind.name(), + Module::Extern(m) => Some(m.name), + } + } + + fn def_kind(self) -> Option { + match self { + Module::Local(m) => match m.kind { + ModuleKind::Block => None, + ModuleKind::Def(def_kind, ..) => Some(def_kind), + }, + Module::Extern(m) => Some(m.def_kind), + } + } } impl<'ra> LocalModule<'ra> { @@ -904,10 +918,19 @@ impl<'ra> LocalModule<'ra> { no_implicit_prelude: bool, arenas: &'ra ResolverArenas<'ra>, ) -> LocalModule<'ra> { - assert!(kind.is_local()); - let common = CommonModuleData::new(kind, vis, expn_id, span, no_implicit_prelude, arenas); + let self_decl = match kind { + ModuleKind::Def(def_kind, def_id, ..) => { + assert!(def_id.is_local()); + let expn_id = expn_id.as_local().unwrap_or(LocalExpnId::ROOT); + let parent = parent.map(|m| m.to_module()); + Some(arenas.new_def_decl(Res::Def(def_kind, def_id), vis, span, expn_id, parent)) + } + ModuleKind::Block => None, + }; + let common = CommonModuleData::new(expn_id, span, no_implicit_prelude, self_decl); let data = LocalModuleData { common, + kind, parent, underscore_disambiguator: CmCell::new(0), unexpanded_invocations: Default::default(), @@ -929,16 +952,30 @@ impl<'ra> LocalModule<'ra> { impl<'ra> ExternModule<'ra> { fn new( parent: Option>, - kind: ModuleKind, + def_kind: DefKind, + def_id: DefId, + name: Symbol, vis: Visibility, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, arenas: &'ra ResolverArenas<'ra>, ) -> ExternModule<'ra> { - assert!(!kind.is_local()); - let common = CommonModuleData::new(kind, vis, expn_id, span, no_implicit_prelude, arenas); - let data = ExternModuleData { common, parent, populate_on_access: CacheCell::new(true) }; + assert!(!def_id.is_local()); + let self_decl = { + let expn_id = expn_id.as_local().unwrap_or(LocalExpnId::ROOT); + let parent = parent.map(|m| m.to_module()); + Some(arenas.new_def_decl(Res::Def(def_kind, def_id), vis, span, expn_id, parent)) + }; + let common = CommonModuleData::new(expn_id, span, no_implicit_prelude, self_decl); + let data = ExternModuleData { + common, + def_kind, + def_id, + name, + parent, + populate_on_access: CacheCell::new(true), + }; ExternModule(Interned::new_unchecked(arenas.extern_modules.alloc(data))) } @@ -992,9 +1029,9 @@ impl<'ra> std::ops::Deref for ExternModuleData<'ra> { impl<'ra> fmt::Debug for Module<'ra> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - ModuleKind::Block => write!(f, "block"), - ModuleKind::Def(..) => write!(f, "{:?}", self.res()), + match self.res() { + None => write!(f, "block"), + Some(res) => write!(f, "{:?}", res), } } } @@ -1917,7 +1954,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module = LocalModule::new(parent, kind, vis, expn_id, span, no_implicit_prelude, self.arenas); self.local_modules.push(module); - if let Some(def_id) = module.opt_def_id() { + if let Some(def_id) = module.kind.opt_def_id() { self.local_module_map.insert(def_id.expect_local(), module); } module @@ -1926,16 +1963,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn new_extern_module( &self, parent: Option>, - kind: ModuleKind, + def_kind: DefKind, + def_id: DefId, + name: Symbol, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, ) -> ExternModule<'ra> { - let vis = - kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id)); - let module = - ExternModule::new(parent, kind, vis, expn_id, span, no_implicit_prelude, self.arenas); - self.extern_module_map.borrow_mut().insert(module.def_id(), module); + let module = ExternModule::new( + parent, + def_kind, + def_id, + name, + self.tcx.visibility(def_id), + expn_id, + span, + no_implicit_prelude, + self.arenas, + ); + self.extern_module_map.borrow_mut().insert(module.def_id, module); module } @@ -2412,7 +2458,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { "resolve_crate_root({:?}): got module {:?} ({:?}) (ident.span = {:?})", ident, module, - module.kind.name(), + module.name(), ident.span ); module @@ -2756,22 +2802,9 @@ fn path_names_to_string(path: &Path) -> String { /// A somewhat inefficient routine to obtain the name of a module. fn module_to_string(mut module: Module<'_>) -> Option { let mut names = Vec::new(); - loop { - if let ModuleKind::Def(.., name) = module.kind { - if let Some(parent) = module.parent() { - // `unwrap` is safe: the presence of a parent means it's not the crate root. - names.push(name.unwrap()); - module = parent - } else { - break; - } - } else { - names.push(sym::opaque_module_name_placeholder); - let Some(parent) = module.parent() else { - return None; - }; - module = parent; - } + while let Some(parent) = module.parent() { + names.push(module.name().unwrap_or(sym::opaque_module_name_placeholder)); + module = parent; } if names.is_empty() { return None; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 163ddcc0329c0..2a7b6be458d01 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -175,10 +175,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { fn resolve_dollar_crates(&self) { hygiene::update_dollar_crate_names(|ctxt| { let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt)); - match self.resolve_crate_root(ident).kind { - ModuleKind::Def(.., name) if let Some(name) = name => name, - _ => kw::Crate, - } + self.resolve_crate_root(ident).name().unwrap_or(kw::Crate) }); } @@ -1184,7 +1181,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Silence `unused_imports` on the fallback import as well. self.get_mut().record_use(ident, fallback_binding, Used::Other); } else { - let location = match parent_scope.module.kind { + let location = match parent_scope.module.kind() { ModuleKind::Def(kind, def_id, _, name) => { if let Some(name) = name { format!("{} `{name}`", kind.descr(def_id)) From b03e05810a3dd7f093e42a2771a569d60f15f19b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 9 May 2026 16:35:43 +0300 Subject: [PATCH 10/11] resolve: Cleanup `ParentScope::module` --- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d2767c5e36545..a423f91fbe9cf 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1477,7 +1477,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; - let parent_scope = ParentScope::module(graph_root.to_module(), resolver.arenas); + let parent_scope = ParentScope::module(graph_root, resolver.arenas); let start_rib_kind = RibKind::Module(graph_root); LateResolutionVisitor { r: resolver, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9a9ad5f006900..c5d82be08028e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -172,9 +172,9 @@ struct ParentScope<'ra> { impl<'ra> ParentScope<'ra> { /// Creates a parent scope with the passed argument used as the module scope component, /// and other scope components set to default empty values. - fn module(module: Module<'ra>, arenas: &'ra ResolverArenas<'ra>) -> ParentScope<'ra> { + fn module(module: LocalModule<'ra>, arenas: &'ra ResolverArenas<'ra>) -> ParentScope<'ra> { ParentScope { - module, + module: module.to_module(), expansion: LocalExpnId::ROOT, macro_rules: arenas.alloc_macro_rules_scope(MacroRulesScope::Empty), derives: &[], @@ -1934,7 +1934,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .. }; - let root_parent_scope = ParentScope::module(graph_root.to_module(), resolver.arenas); + let root_parent_scope = ParentScope::module(graph_root, resolver.arenas); resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); resolver.feed_visibility(crate_feed, Visibility::Public); @@ -2337,7 +2337,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Do not report the lint if the macro name resolves in stdlib prelude // even without the problematic `macro_use` import. let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| { - let empty_module = self.empty_module.to_module(); + let empty_module = self.empty_module; let arenas = self.arenas; self.cm() .maybe_resolve_ident_in_module( @@ -2703,12 +2703,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } - let module = self.graph_root.to_module(); + let module = self.graph_root; let ident = Ident::with_dummy_span(sym::main); let parent_scope = &ParentScope::module(module, self.arenas); let Ok(name_binding) = self.cm().maybe_resolve_ident_in_module( - ModuleOrUniformRoot::Module(module), + ModuleOrUniformRoot::Module(module.to_module()), ident, ValueNS, parent_scope, From 0d013de52a3a9b7465c6fa32ccd8ae3f45c1b37a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 9 May 2026 16:58:21 +0300 Subject: [PATCH 11/11] resolve: Remove `Module::as_local` --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 8 ++++---- compiler/rustc_resolve/src/lib.rs | 7 ------- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index a63fca73a4cf1..5b38d820dde65 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3291,7 +3291,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } visited.insert(parent_module, false); let mut res = false; - if let Some(m) = r.expect_module(parent_module).as_local() { + if let Module::Local(m) = r.expect_module(parent_module) { for importer in m.glob_importers.borrow().iter() { if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5fa2956a0a80d..b855857a92ea5 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1122,7 +1122,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // In extern modules everything is determined from the start. - let Some(module) = module.as_local() else { + let Module::Local(module) = module else { return Err(ControlFlow::Continue(Determined)); }; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 462516836e3ae..76daf5fc2c033 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -43,9 +43,9 @@ use crate::errors::{ use crate::ref_mut::CmCell; use crate::{ AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize, - IdentKey, ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope, - PathResult, PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, - names_to_string, + IdentKey, ImportSuggestion, ImportSummary, LocalModule, Module, ModuleOrUniformRoot, + ParentScope, PathResult, PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, + module_to_string, names_to_string, }; /// A potential import declaration in the process of being planted into a module. @@ -1790,7 +1790,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Add to module's glob_importers - if let Some(module) = module.as_local() { + if let Module::Local(module) = module { module.glob_importers.borrow_mut_unchecked().push(import); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c5d82be08028e..3826fedddd2e2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -827,13 +827,6 @@ impl<'ra> Module<'ra> { true } - fn as_local(self) -> Option> { - match self { - Module::Local(m) => Some(m), - Module::Extern(_) => None, - } - } - #[track_caller] fn expect_local(self) -> LocalModule<'ra> { match self {