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

This commit is contained in:
Vadim Petrochenkov
2026-03-27 16:35:35 +03:00
parent 1b8f2e46e1
commit 61bc404458
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
@@ -1130,7 +1130,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));
}
@@ -2861,10 +2861,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),
@@ -3007,7 +3013,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