From 61bc404458cfa41511580ba5b483024c33351bce Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 27 Mar 2026 16:35:35 +0300 Subject: [PATCH] resolve: Introduce `(Local,Extern)Module` newtypes for local and external modules respectively --- .../rustc_resolve/src/build_reduced_graph.rs | 79 +++++----- compiler/rustc_resolve/src/check_unused.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 10 +- compiler/rustc_resolve/src/ident.rs | 16 +- compiler/rustc_resolve/src/imports.rs | 21 ++- compiler/rustc_resolve/src/late.rs | 18 +-- .../rustc_resolve/src/late/diagnostics.rs | 14 +- compiler/rustc_resolve/src/lib.rs | 142 +++++++++++++----- compiler/rustc_resolve/src/macros.rs | 4 +- 9 files changed, 197 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 1c6889efe7501..9ec27fb175e27 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -37,9 +37,9 @@ use crate::imports::{ImportData, ImportKind, OnUnknownData}; use crate::macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; use crate::ref_mut::CmCell; use crate::{ - BindingKey, Decl, DeclData, DeclKind, ExternPreludeEntry, Finalize, IdentKey, MacroData, - Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, - Resolver, Segment, Used, VisResolutionError, errors, + BindingKey, Decl, DeclData, DeclKind, ExternModule, ExternPreludeEntry, Finalize, IdentKey, + LocalModule, MacroData, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, + ResolutionError, Resolver, Segment, Used, VisResolutionError, errors, }; impl<'ra, 'tcx> Resolver<'ra, 'tcx> { @@ -62,7 +62,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Create a name definition from the given components, and put it into the local module. fn define_local( &mut self, - parent: Module<'ra>, + parent: LocalModule<'ra>, orig_ident: Ident, ns: Namespace, res: Res, @@ -70,7 +70,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, expn_id: LocalExpnId, ) { - let decl = self.arenas.new_def_decl(res, vis.to_def_id(), span, expn_id, Some(parent)); + let decl = + self.arenas.new_def_decl(res, vis.to_def_id(), span, expn_id, Some(parent.to_module())); let ident = IdentKey::new(orig_ident); self.plant_decl_into_local_module(ident, orig_ident.span, ns, decl); } @@ -78,7 +79,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Create a name definition from the given components, and put it into the extern module. fn define_extern( &self, - parent: Module<'ra>, + parent: ExternModule<'ra>, ident: IdentKey, orig_ident_span: Span, ns: Namespace, @@ -97,7 +98,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { vis: CmCell::new(vis), span, expansion, - parent_module: Some(parent), + parent_module: Some(parent.to_module()), }); // Even if underscore names cannot be looked up, we still need to add them to modules, // because they can be fetched by glob imports from those modules, and bring traits @@ -105,7 +106,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let key = BindingKey::new_disambiguated(ident, ns, || (child_index + 1).try_into().unwrap()); // 0 indicates no underscore if self - .resolution_or_default(parent, key, orig_ident_span) + .resolution_or_default(parent.to_module(), key, orig_ident_span) .borrow_mut_unchecked() .non_glob_decl .replace(decl) @@ -149,30 +150,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// returns `None`. pub(crate) fn get_module(&self, def_id: DefId) -> Option> { match def_id.as_local() { - Some(local_def_id) => self.local_module_map.get(&local_def_id).copied(), + Some(local_def_id) => self.local_module_map.get(&local_def_id).map(|m| m.to_module()), None => { if let module @ Some(..) = self.extern_module_map.borrow().get(&def_id) { - return module.copied(); + return module.map(|m| m.to_module()); } // Query `def_kind` is not used because query system overhead is too expensive here. let def_kind = self.cstore().def_kind_untracked(self.tcx, def_id); if def_kind.is_module_like() { - let parent = self - .tcx - .opt_parent(def_id) - .map(|parent_id| self.get_nearest_non_block_module(parent_id)); + let parent = self.tcx.opt_parent(def_id).map(|parent_id| { + self.get_nearest_non_block_module(parent_id).expect_extern() + }); // Query `expn_that_defined` is not used because // hashing spans in its result is expensive. let expn_id = self.cstore().expn_that_defined_untracked(self.tcx, def_id); - return Some(self.new_extern_module( + let module = self.new_extern_module( parent, ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))), expn_id, self.def_span(def_id), // FIXME: Account for `#[no_implicit_prelude]` attributes. parent.is_some_and(|module| module.no_implicit_prelude), - )); + ); + return Some(module.to_module()); } None @@ -186,13 +187,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => expn_id .as_local() .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied()) - .unwrap_or(self.graph_root), + .unwrap_or(self.graph_root) + .to_module(), } } pub(crate) fn macro_def_scope(&self, def_id: DefId) -> Module<'ra> { if let Some(id) = def_id.as_local() { - self.local_macro_def_scopes[&id] + self.local_macro_def_scopes[&id].to_module() } else { self.get_nearest_non_block_module(def_id) } @@ -246,10 +248,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { visitor.parent_scope.macro_rules } - pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) { + pub(crate) fn build_reduced_graph_external(&self, module: ExternModule<'ra>) { let def_id = module.def_id(); let children = self.tcx.module_children(def_id); - let parent_scope = ParentScope::module(module, self.arenas); + let parent_scope = ParentScope::module(module.to_module(), self.arenas); for (i, child) in children.iter().enumerate() { self.build_reduced_graph_for_external_crate_res(child, parent_scope, i, None) } @@ -273,7 +275,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { child_index: usize, ambig_child: Option<&ModChild>, ) { - let parent = parent_scope.module; + let parent = parent_scope.module.expect_extern(); let child_span = |this: &Self, reexport_chain: &[Reexport], res: def::Res<_>| { this.def_span( reexport_chain @@ -291,7 +293,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child; let span = child_span(self, reexport_chain, res); let res = res.expect_non_local(); - self.arenas.new_def_decl(res, vis, span, expansion, Some(parent)) + self.arenas.new_def_decl(res, vis, span, expansion, Some(parent.to_module())) }); // Record primary definitions. @@ -801,7 +803,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { adt_span: Span, ) { let parent_scope = &self.parent_scope; - let parent = parent_scope.module; + let parent = parent_scope.module.expect_local(); let expansion = parent_scope.expansion; // Define a name in the type namespace if it is not anonymous. @@ -817,7 +819,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { /// Constructs the reduced graph for one item. fn build_reduced_graph_for_item(&mut self, item: &'a Item) { let parent_scope = &self.parent_scope; - let parent = parent_scope.module; + let parent = parent_scope.module.expect_local(); let expansion = parent_scope.expansion; let sp = item.span; let vis = self.resolve_visibility(&item.vis); @@ -862,7 +864,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { { self.r.mods_with_parse_errors.insert(def_id); } - self.parent_scope.module = self.r.new_local_module( + let module = self.r.new_local_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), @@ -870,6 +872,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { parent.no_implicit_prelude || ast::attr::contains_name(&item.attrs, sym::no_implicit_prelude), ); + self.parent_scope.module = module.to_module(); } // These items live in the value namespace. @@ -895,13 +898,14 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => { self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); - self.parent_scope.module = self.r.new_local_module( + let module = self.r.new_local_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude, ); + self.parent_scope.module = module.to_module(); } // These items live in both the type and value namespaces. @@ -997,7 +1001,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.dcx().emit_err(errors::ExternCrateSelfRequiresRenaming { span: sp }); return; } else if orig_name == Some(kw::SelfLower) { - Some(self.r.graph_root) + Some(self.r.graph_root.to_module()) } else { let tcx = self.r.tcx; let crate_id = self.r.cstore_mut().process_extern_crate( @@ -1038,7 +1042,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.potentially_unused_imports.push(import); let import_decl = self.r.new_import_decl(decl, import); let ident = IdentKey::new(orig_ident); - if ident.name != kw::Underscore && parent == self.r.graph_root { + if ident.name != kw::Underscore && parent == self.r.graph_root.to_module() { // FIXME: this error is technically unnecessary now when extern prelude is split into // two scopes, remove it with lang team approval. if let Some(entry) = self.r.extern_prelude.get(&ident) @@ -1083,7 +1087,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ForeignItemKind::TyAlias(..) => TypeNS, ForeignItemKind::MacCall(..) => unreachable!(), }; - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); @@ -1091,7 +1095,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } fn build_reduced_graph_for_block(&mut self, block: &Block) { - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; if self.block_needs_anonymous_module(block) { let module = self.r.new_local_module( @@ -1102,7 +1106,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { parent.no_implicit_prelude, ); self.r.block_map.insert(block.id, module); - self.parent_scope.module = module; // Descend into the block. + self.parent_scope.module = module.to_module(); // Descend into the block. } } @@ -1302,7 +1306,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { _ => unreachable!(), }; - self.r.local_macro_def_scopes.insert(def_id, parent_scope.module); + self.r.local_macro_def_scopes.insert(def_id, parent_scope.module.expect_local()); if macro_rules { let ident = IdentKey::new(orig_ident); @@ -1325,7 +1329,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroExport, root_id: item.id, - parent_scope: ParentScope { module: self.r.graph_root, ..parent_scope }, + parent_scope: ParentScope { + module: self.r.graph_root.to_module(), + ..parent_scope + }, imported_module: CmCell::new(None), has_attributes: false, use_span_with_attributes: span, @@ -1356,7 +1363,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.macro_rules_scopes.insert(def_id, scope); scope } else { - let module = parent_scope.module; + let module = parent_scope.module.expect_local(); let vis = match item.kind { // Visibilities must not be resolved non-speculatively twice // and we already resolved this one as a `fn` item visibility. @@ -1504,7 +1511,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } if ctxt == AssocCtxt::Trait { - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) @@ -1586,7 +1593,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { return; } - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expn_id = self.parent_scope.expansion; let ident = variant.ident; diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index b5246808cd5ad..7e1b1bce3ff74 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -545,7 +545,7 @@ impl Resolver<'_, '_> { let unused_imports = visitor.unused_imports; let mut check_redundant_imports = FxIndexSet::default(); for module in &self.local_modules { - for (_key, resolution) in self.resolutions(*module).borrow().iter() { + for (_key, resolution) in self.resolutions(module.to_module()).borrow().iter() { if let Some(decl) = resolution.borrow().best_decl() && let DeclKind::Import { import, .. } = decl.kind && let ImportKind::Single { id, .. } = import.kind diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 08ee2db1f5b17..bf260d823b765 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1585,7 +1585,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lookup_ident, namespace, parent_scope, - self.graph_root, + self.graph_root.to_module(), crate_path, &filter_fn, ); @@ -2074,7 +2074,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if kind != AmbiguityKind::GlobVsGlob { if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope { - if module == self.graph_root { + if module == self.graph_root.to_module() { help_msgs.push(format!( "use `crate::{ident}` to refer to this {thing} unambiguously" )); @@ -2452,7 +2452,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.local_module_map .iter() .filter(|(_, module)| { - current_module.is_ancestor_of(**module) && current_module != **module + let module = module.to_module(); + current_module.is_ancestor_of(module) && current_module != module }) .flat_map(|(_, module)| module.kind.name()), ) @@ -2461,7 +2462,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .borrow() .iter() .filter(|(_, module)| { - current_module.is_ancestor_of(**module) && current_module != **module + let module = module.to_module(); + current_module.is_ancestor_of(module) && current_module != module }) .flat_map(|(_, module)| module.kind.name()), ) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 7ff3f09668928..56a0ee2acc1a6 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -24,9 +24,9 @@ use crate::late::{ use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind, - Determinacy, Finalize, IdentKey, ImportKind, LateDecl, Module, ModuleKind, ModuleOrUniformRoot, - ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, - Segment, Stage, Symbol, Used, errors, + Determinacy, Finalize, IdentKey, ImportKind, LateDecl, LocalModule, Module, ModuleKind, + ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, + Scope, ScopeSet, Segment, Stage, Symbol, Used, errors, }; #[derive(Copy, Clone)] @@ -346,7 +346,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else if let RibKind::Block(Some(module)) = rib.kind && let Ok(binding) = self.cm().resolve_ident_in_scope_set( ident, - ScopeSet::Module(ns, module), + ScopeSet::Module(ns, module.to_module()), parent_scope, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), ignore_decl, @@ -357,7 +357,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return Some(LateDecl::Decl(binding)); } else if let RibKind::Module(module) = rib.kind { // Encountered a module item, abandon ribs and look into that module and preludes. - let parent_scope = &ParentScope { module, ..*parent_scope }; + let parent_scope = &ParentScope { module: module.to_module(), ..*parent_scope }; let finalize = finalize.map(|f| Finalize { stage: Stage::Late, ..f }); return self .cm() @@ -658,7 +658,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) }; let binding = self.reborrow().resolve_ident_in_module_globs_unadjusted( - module, + module.expect_local(), ident, orig_ident_span, ns, @@ -1122,7 +1122,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Attempts to resolve `ident` in namespace `ns` of glob bindings in `module`. fn resolve_ident_in_module_globs_unadjusted<'r>( mut self: CmResolver<'r, 'ra, 'tcx>, - module: Module<'ra>, + module: LocalModule<'ra>, ident: IdentKey, orig_ident_span: Span, ns: Namespace, @@ -1137,7 +1137,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // doesn't need to be mutable. It will fail when there is a cycle of imports, and without // the exclusive access infinite recursion will crash the compiler with stack overflow. let resolution = &*self - .resolution_or_default(module, key, orig_ident_span) + .resolution_or_default(module.to_module(), key, orig_ident_span) .try_borrow_mut_unchecked() .map_err(|_| ControlFlow::Continue(Determined))?; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index d1a3960afd039..b4f03db96e6ea 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -37,8 +37,8 @@ use crate::errors::{ use crate::ref_mut::CmCell; use crate::{ AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize, - IdentKey, ImportSuggestion, Module, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, Res, - ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string, + IdentKey, ImportSuggestion, LocalModule, 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. @@ -471,7 +471,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl: Decl<'ra>, warn_ambiguity: bool, ) -> Result<(), Decl<'ra>> { - let module = decl.parent_module.unwrap(); + let module = decl.parent_module.unwrap().expect_local(); let res = decl.res(); self.check_reserved_macro_name(ident.name, orig_ident_span, res); // Even if underscore names cannot be looked up, we still need to add them to modules, @@ -513,7 +513,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // If the resolution becomes a success, define it in the module's glob importers. fn update_local_resolution( &mut self, - module: Module<'ra>, + module: LocalModule<'ra>, key: BindingKey, orig_ident_span: Span, warn_ambiguity: bool, @@ -526,7 +526,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // during which the resolution might end up getting re-defined via a glob cycle. let (binding, t, warn_ambiguity) = { let resolution = &mut *self - .resolution_or_default(module, key, orig_ident_span) + .resolution_or_default(module.to_module(), key, orig_ident_span) .borrow_mut_unchecked(); let old_decl = resolution.determined_decl(); @@ -582,7 +582,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let dummy_decl = self.dummy_decl; let dummy_decl = self.new_import_decl(dummy_decl, import); self.per_ns(|this, ns| { - let module = import.parent_scope.module; let ident = IdentKey::new(target); // This can fail, dummies are inserted only in non-occupied slots. let _ = this.try_plant_decl_into_local_module( @@ -596,7 +595,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if target.name != kw::Underscore { let key = BindingKey::new(ident, ns); this.update_local_resolution( - module, + import.parent_scope.module.expect_local(), key, target.span, false, @@ -734,7 +733,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet>) { for module in &self.local_modules { - for (key, resolution) in self.resolutions(*module).borrow().iter() { + for (key, resolution) in self.resolutions(module.to_module()).borrow().iter() { let resolution = resolution.borrow(); let Some(binding) = resolution.best_decl() else { continue }; @@ -1027,7 +1026,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if target.name != kw::Underscore { let key = BindingKey::new(IdentKey::new(target), ns); this.get_mut_unchecked().update_local_resolution( - parent, + parent.expect_local(), key, target.span, false, @@ -1700,7 +1699,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // reporting conflicts, and reporting unresolved imports. fn finalize_resolutions_in( &self, - module: Module<'ra>, + module: LocalModule<'ra>, module_children: &mut LocalDefIdMap>, ambig_module_children: &mut LocalDefIdMap>, ) { @@ -1712,7 +1711,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut children = Vec::new(); let mut ambig_children = Vec::new(); - module.for_each_child(self, |this, ident, orig_ident_span, _, binding| { + module.to_module().for_each_child(self, |this, ident, orig_ident_span, _, binding| { let res = binding.res().expect_non_local(); if res != def::Res::Err { let ident = ident.orig(orig_ident_span); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a88f06f931389..db71f7ed79d8b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -40,9 +40,9 @@ use thin_vec::ThinVec; use tracing::{debug, instrument, trace}; use crate::{ - BindingError, BindingKey, Decl, DelegationFnSig, Finalize, IdentKey, LateDecl, Module, - ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, Resolver, Segment, Stage, - TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc, + BindingError, BindingKey, Decl, DelegationFnSig, Finalize, IdentKey, LateDecl, LocalModule, + Module, ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, Resolver, Segment, + Stage, TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc, }; mod diagnostics; @@ -196,7 +196,7 @@ pub(crate) enum RibKind<'ra> { /// `Block(None)` must be always processed in the same way as `Block(Some(module))` /// with empty `module`. The module can be `None` only because creation of some definitely /// empty modules is skipped as an optimization. - Block(Option>), + Block(Option>), /// We passed through an impl or trait and are now in one of its /// methods or associated types. Allow references to ty params that impl or trait @@ -217,7 +217,7 @@ pub(crate) enum RibKind<'ra> { ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), /// We passed through a module item. - Module(Module<'ra>), + Module(LocalModule<'ra>), /// We passed through a `macro_rules!` statement MacroDefinition(DefId), @@ -1473,7 +1473,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, resolver.arenas); + let parent_scope = ParentScope::module(graph_root.to_module(), resolver.arenas); let start_rib_kind = RibKind::Module(graph_root); LateResolutionVisitor { r: resolver, @@ -2875,8 +2875,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ItemKind::Mod(..) => { let module = self.r.expect_module(self.r.local_def_id(item.id).to_def_id()); let orig_module = replace(&mut self.parent_scope.module, module); - self.with_rib(ValueNS, RibKind::Module(module), |this| { - this.with_rib(TypeNS, RibKind::Module(module), |this| { + self.with_rib(ValueNS, RibKind::Module(module.expect_local()), |this| { + this.with_rib(TypeNS, RibKind::Module(module.expect_local()), |this| { if mod_inner_docs { this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); } @@ -5015,7 +5015,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { debug!("(resolving block) found anonymous module, moving down"); self.ribs[ValueNS].push(Rib::new(RibKind::Block(Some(anonymous_module)))); self.ribs[TypeNS].push(Rib::new(RibKind::Block(Some(anonymous_module)))); - self.parent_scope.module = anonymous_module; + self.parent_scope.module = anonymous_module.to_module(); } else { self.ribs[ValueNS].push(Rib::new(RibKind::Block(None))); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cbcf1a182c7e1..2990ad8af58d1 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1130,7 +1130,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { for rib in self.ribs[ns].iter().rev() { let item = path[0].ident; if let RibKind::Module(module) | RibKind::Block(Some(module)) = rib.kind - && let Some(did) = find_doc_alias_name(self.r, module, item.name) + && let Some(did) = find_doc_alias_name(self.r, module.to_module(), item.name) { return Some((did, item)); } @@ -2861,10 +2861,16 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } if let RibKind::Block(Some(module)) = rib.kind { - self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt)); + self.r.add_module_candidates( + module.to_module(), + &mut names, + &filter_fn, + Some(ctxt), + ); } else if let RibKind::Module(module) = rib.kind { // Encountered a module item, abandon ribs and look into that module and preludes. - let parent_scope = &ParentScope { module, ..self.parent_scope }; + let parent_scope = + &ParentScope { module: module.to_module(), ..self.parent_scope }; self.r.add_scope_set_candidates( &mut names, ScopeSet::All(ns), @@ -3007,7 +3013,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut seen_modules = FxHashSet::default(); let root_did = self.r.graph_root.def_id(); let mut worklist = vec![( - self.r.graph_root, + self.r.graph_root.to_module(), ThinVec::new(), root_did.is_local() || !self.r.tcx.is_doc_hidden(root_did), )]; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 35ef00f945035..444fcb0fe6685 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -686,6 +686,16 @@ struct ModuleData<'ra> { #[rustc_pass_by_value] struct Module<'ra>(Interned<'ra, ModuleData<'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>>); + +/// 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>>); + // 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 @@ -728,6 +738,21 @@ impl<'ra> ModuleData<'ra> { self_decl, } } + + fn opt_def_id(&self) -> Option { + self.kind.opt_def_id() + } + + fn def_id(&self) -> DefId { + self.opt_def_id().expect("`ModuleData::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> { @@ -779,21 +804,6 @@ impl<'ra> Module<'ra> { } } - fn res(self) -> Option { - match self.kind { - ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), - _ => None, - } - } - - fn def_id(self) -> DefId { - self.opt_def_id().expect("`ModuleData::def_id` is called on a block module") - } - - fn opt_def_id(self) -> Option { - self.kind.opt_def_id() - } - // `self` resolves to the first module ancestor that `is_normal`. fn is_normal(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _)) @@ -831,6 +841,38 @@ impl<'ra> Module<'ra> { } true } + + #[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), + } + } + + #[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:?}") + } + } + } +} + +impl<'ra> LocalModule<'ra> { + fn to_module(self) -> Module<'ra> { + Module(self.0) + } +} + +impl<'ra> ExternModule<'ra> { + fn to_module(self) -> Module<'ra> { + Module(self.0) + } } impl<'ra> std::ops::Deref for Module<'ra> { @@ -841,6 +883,22 @@ impl<'ra> std::ops::Deref for Module<'ra> { } } +impl<'ra> std::ops::Deref for LocalModule<'ra> { + type Target = ModuleData<'ra>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'ra> std::ops::Deref for ExternModule<'ra> { + type Target = ModuleData<'ra>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl<'ra> fmt::Debug for Module<'ra> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { @@ -850,6 +908,12 @@ impl<'ra> fmt::Debug for Module<'ra> { } } +impl<'ra> fmt::Debug for LocalModule<'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> { @@ -1197,7 +1261,7 @@ pub struct Resolver<'ra, 'tcx> { /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expn_that_defined: UnordMap = Default::default(), - graph_root: Module<'ra>, + graph_root: LocalModule<'ra>, /// Assert that we are in speculative resolution mode. assert_speculative: bool, @@ -1256,17 +1320,17 @@ pub struct Resolver<'ra, 'tcx> { /// /// There will be an anonymous module created around `g` with the ID of the /// entry block for `f`. - block_map: NodeMap> = Default::default(), + block_map: NodeMap> = Default::default(), /// A fake module that contains no definition and no prelude. Used so that /// some AST passes can generate identifiers that only resolve to local or /// lang items. - empty_module: Module<'ra>, + empty_module: LocalModule<'ra>, /// All local modules, including blocks. - local_modules: Vec>, + local_modules: Vec>, /// Eagerly populated map of all local non-block modules. - local_module_map: FxIndexMap>, + local_module_map: FxIndexMap>, /// Lazily populated cache of modules loaded from external crates. - extern_module_map: CacheRefCell>>, + extern_module_map: CacheRefCell>>, /// Maps glob imports to the names of items actually imported. glob_map: FxIndexMap>, @@ -1301,8 +1365,8 @@ pub struct Resolver<'ra, 'tcx> { dummy_ext_bang: Arc, dummy_ext_derive: Arc, non_macro_attr: &'ra MacroData, - local_macro_def_scopes: FxHashMap> = default::fx_hash_map(), - ast_transform_scopes: FxHashMap> = default::fx_hash_map(), + local_macro_def_scopes: FxHashMap> = default::fx_hash_map(), + ast_transform_scopes: FxHashMap> = default::fx_hash_map(), unused_macros: FxIndexMap, /// A map from the macro to all its potentially unused arms. unused_macro_rules: FxIndexMap>, @@ -1650,6 +1714,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), ); + 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( @@ -1660,6 +1725,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { DUMMY_SP, true, ); + 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); @@ -1742,7 +1808,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .. }; - let root_parent_scope = ParentScope::module(graph_root, resolver.arenas); + let root_parent_scope = ParentScope::module(graph_root.to_module(), resolver.arenas); resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); resolver.feed_visibility(crate_feed, Visibility::Public); @@ -1751,15 +1817,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn new_local_module( &mut self, - parent: Option>, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - ) -> Module<'ra> { + ) -> 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 = self.arenas.new_module(parent, kind, vis, expn_id, span, no_implicit_prelude); + let module = self + .arenas + .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude) + .expect_local(); self.local_modules.push(module); if let Some(def_id) = module.opt_def_id() { self.local_module_map.insert(def_id.expect_local(), module); @@ -1769,15 +1839,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn new_extern_module( &self, - parent: Option>, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - ) -> Module<'ra> { + ) -> 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 = self.arenas.new_module(parent, kind, vis, expn_id, span, no_implicit_prelude); + let module = self + .arenas + .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude) + .expect_extern(); self.extern_module_map.borrow_mut().insert(module.def_id(), module); module } @@ -2063,7 +2137,7 @@ 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); + self.build_reduced_graph_external(module.expect_extern()); } &module.0.0.lazy_resolutions } @@ -2136,7 +2210,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; + let empty_module = self.empty_module.to_module(); let arenas = self.arenas; self.cm() .maybe_resolve_ident_in_module( @@ -2248,7 +2322,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { "resolve_crate_root({:?}): found no mark (ident.span = {:?})", ident, ident.span ); - return self.graph_root; + return self.graph_root.to_module(); } }; let module = self.expect_module( @@ -2503,7 +2577,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } - let module = self.graph_root; + let module = self.graph_root.to_module(); let ident = Ident::with_dummy_span(sym::main); let parent_scope = &ParentScope::module(module, self.arenas); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 68242fba473d6..2de4e21b1e96a 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -240,8 +240,8 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ) }); - let parent_scope = - parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id)); + let parent_scope = parent_module + .map_or(self.empty_module, |def_id| self.expect_module(def_id).expect_local()); self.ast_transform_scopes.insert(expn_id, parent_scope); expn_id