Rollup merge of #155242 - petrochenkov:modmodmod, r=mu001999

resolve: Introduce `(Local,Extern)Module` newtypes for local and external modules respectively

Right now both `LocalModule` and `ExternModule` refer to the same `ModuleData`, but the module data for local and extern modules can potentially be made quite different, and we can specialize name lookup for both cases as an optimization.

Declaration creation for local and external modules was already specialized as a part of the parallel import resolution work (see `define_local` and `define_extern`, rust-lang/rust#145108 and previous PRs), because they have different properties with regards to ownership and synchronization.
This commit is contained in:
Jonathan Brouwer
2026-04-17 13:28:56 +02:00
committed by GitHub
9 changed files with 197 additions and 109 deletions
@@ -37,9 +37,9 @@
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 @@ pub(crate) fn plant_decl_into_local_module(
/// 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 @@ fn define_local(
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 @@ fn define_local(
/// 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 @@ fn define_extern(
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 @@ fn define_extern(
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 @@ pub(crate) fn expect_module(&self, def_id: DefId) -> Module<'ra> {
/// returns `None`.
pub(crate) fn get_module(&self, def_id: DefId) -> Option<Module<'ra>> {
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 @@ pub(crate) fn expn_def_scope(&self, expn_id: ExpnId) -> Module<'ra> {
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 @@ pub(crate) fn build_reduced_graph(
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 @@ fn build_reduced_graph_for_external_crate_res(
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 @@ fn build_reduced_graph_for_external_crate_res(
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 @@ fn build_reduced_graph_for_struct_variant(
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 @@ fn build_reduced_graph_for_struct_variant(
/// 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 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
{
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 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
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 @@ fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
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 @@ fn build_reduced_graph_for_extern_crate(
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 @@ fn build_reduced_graph_for_extern_crate(
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 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Id
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 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Id
}
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 @@ fn build_reduced_graph_for_block(&mut self, block: &Block) {
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 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'ra> {
_ => 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 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'ra> {
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 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'ra> {
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 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
}
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 @@ fn visit_variant(&mut self, variant: &'a ast::Variant) {
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;
+1 -1
View File
@@ -545,7 +545,7 @@ pub(crate) fn check_unused(&mut self, krate: &ast::Crate) {
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
+6 -4
View File
@@ -1585,7 +1585,7 @@ pub(crate) fn lookup_import_candidates<FilterFn>(
lookup_ident,
namespace,
parent_scope,
self.graph_root,
self.graph_root.to_module(),
crate_path,
&filter_fn,
);
@@ -2074,7 +2074,7 @@ fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors:
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 @@ pub(crate) fn find_similarly_named_module_or_crate(
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 @@ pub(crate) fn find_similarly_named_module_or_crate(
.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()),
)
+8 -8
View File
@@ -24,9 +24,9 @@
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 @@ pub(crate) fn resolve_ident_in_lexical_scope(
} 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 @@ pub(crate) fn resolve_ident_in_lexical_scope(
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 @@ fn resolve_ident_in_scope<'r>(
)
};
let binding = self.reborrow().resolve_ident_in_module_globs_unadjusted(
module,
module.expect_local(),
ident,
orig_ident_span,
ns,
@@ -1122,7 +1122,7 @@ fn resolve_ident_in_module_non_globs_unadjusted<'r>(
/// 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 @@ fn resolve_ident_in_module_globs_unadjusted<'r>(
// 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))?;
+10 -11
View File
@@ -37,8 +37,8 @@
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 @@ pub(crate) fn try_plant_decl_into_local_module(
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 @@ pub(crate) fn try_plant_decl_into_local_module(
// If the resolution becomes a success, define it in the module's glob importers.
fn update_local_resolution<T, F>(
&mut self,
module: Module<'ra>,
module: LocalModule<'ra>,
key: BindingKey,
orig_ident_span: Span,
warn_ambiguity: bool,
@@ -526,7 +526,7 @@ fn update_local_resolution<T, F>(
// 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 @@ fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool)
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 @@ fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool)
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 @@ pub(crate) fn finalize_imports(&mut self) {
pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra>>) {
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 @@ fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>)
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 @@ fn resolve_glob_import(&mut self, import: Import<'ra>) {
// reporting conflicts, and reporting unresolved imports.
fn finalize_resolutions_in(
&self,
module: Module<'ra>,
module: LocalModule<'ra>,
module_children: &mut LocalDefIdMap<Vec<ModChild>>,
ambig_module_children: &mut LocalDefIdMap<Vec<AmbigModChild>>,
) {
@@ -1712,7 +1711,7 @@ fn finalize_resolutions_in(
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);
+9 -9
View File
@@ -40,9 +40,9 @@
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<Module<'ra>>),
Block(Option<LocalModule<'ra>>),
/// 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 @@ fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast,
// 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 @@ fn resolve_item(&mut self, item: &'ast Item) {
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 @@ fn resolve_block(&mut self, block: &'ast Block) {
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)));
}
+10 -4
View File
@@ -1133,7 +1133,7 @@ fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(
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));
}
@@ -2864,10 +2864,16 @@ fn lookup_typo_candidate(
}
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),
@@ -3010,7 +3016,7 @@ fn find_module(&self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)>
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),
)];
+108 -34
View File
@@ -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 @@ fn new(
self_decl,
}
}
fn opt_def_id(&self) -> Option<DefId> {
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<Res> {
match self.kind {
ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)),
_ => None,
}
}
}
impl<'ra> Module<'ra> {
@@ -779,21 +804,6 @@ fn ensure_traits<'tcx>(self, resolver: &impl AsRef<Resolver<'ra, 'tcx>>) {
}
}
fn res(self) -> Option<Res> {
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<DefId> {
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 @@ fn is_ancestor_of(self, mut other: Self) -> bool {
}
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 @@ fn deref(&self) -> &Self::Target {
}
}
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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
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<LocalDefId, ExpnId> = 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<Module<'ra>> = Default::default(),
block_map: NodeMap<LocalModule<'ra>> = 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<Module<'ra>>,
local_modules: Vec<LocalModule<'ra>>,
/// Eagerly populated map of all local non-block modules.
local_module_map: FxIndexMap<LocalDefId, Module<'ra>>,
local_module_map: FxIndexMap<LocalDefId, LocalModule<'ra>>,
/// Lazily populated cache of modules loaded from external crates.
extern_module_map: CacheRefCell<FxIndexMap<DefId, Module<'ra>>>,
extern_module_map: CacheRefCell<FxIndexMap<DefId, ExternModule<'ra>>>,
/// Maps glob imports to the names of items actually imported.
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
@@ -1301,8 +1365,8 @@ pub struct Resolver<'ra, 'tcx> {
dummy_ext_bang: Arc<SyntaxExtension>,
dummy_ext_derive: Arc<SyntaxExtension>,
non_macro_attr: &'ra MacroData,
local_macro_def_scopes: FxHashMap<LocalDefId, Module<'ra>> = default::fx_hash_map(),
ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>> = default::fx_hash_map(),
local_macro_def_scopes: FxHashMap<LocalDefId, LocalModule<'ra>> = default::fx_hash_map(),
ast_transform_scopes: FxHashMap<LocalExpnId, LocalModule<'ra>> = default::fx_hash_map(),
unused_macros: FxIndexMap<LocalDefId, (NodeId, Ident)>,
/// A map from the macro to all its potentially unused arms.
unused_macro_rules: FxIndexMap<NodeId, DenseBitSet<usize>>,
@@ -1650,6 +1714,7 @@ pub fn new(
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 @@ pub fn new(
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 @@ pub fn new(
..
};
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 @@ pub fn new(
fn new_local_module(
&mut self,
parent: Option<Module<'ra>>,
parent: Option<LocalModule<'ra>>,
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 @@ fn new_local_module(
fn new_extern_module(
&self,
parent: Option<Module<'ra>>,
parent: Option<ExternModule<'ra>>,
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 @@ fn find_transitive_imports(
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 @@ fn record_use_inner(
// 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 @@ fn resolve_crate_root(&self, ident: Ident) -> Module<'ra> {
"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 @@ fn resolve_main(&mut self) {
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);
+2 -2
View File
@@ -240,8 +240,8 @@ fn expansion_for_ast_pass(
)
});
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