Skip to content

Commit ea81d8c

Browse files
committed
resolve: Populate external modules in more automatic and lazy way
The modules are now populated implicitly on the first access
1 parent 9dd5c19 commit ea81d8c

File tree

6 files changed

+73
-71
lines changed

6 files changed

+73
-71
lines changed

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -159,19 +159,6 @@ impl<'a> Resolver<'a> {
159159
Some(ext)
160160
}
161161

162-
/// Ensures that the reduced graph rooted at the given external module
163-
/// is built, building it if it is not.
164-
crate fn populate_module_if_necessary(&mut self, module: Module<'a>) {
165-
if module.populated.get() { return }
166-
let def_id = module.def_id().unwrap();
167-
for child in self.cstore.item_children_untracked(def_id, self.session) {
168-
let child = child.map_id(|_| panic!("unexpected id"));
169-
BuildReducedGraphVisitor { parent_scope: ParentScope::module(module), r: self }
170-
.build_reduced_graph_for_external_crate_res(child);
171-
}
172-
module.populated.set(true)
173-
}
174-
175162
crate fn build_reduced_graph(
176163
&mut self, fragment: &AstFragment, parent_scope: ParentScope<'a>
177164
) -> LegacyScope<'a> {
@@ -186,6 +173,10 @@ struct BuildReducedGraphVisitor<'a, 'b> {
186173
parent_scope: ParentScope<'a>,
187174
}
188175

176+
impl<'a> AsMut<Resolver<'a>> for BuildReducedGraphVisitor<'a, '_> {
177+
fn as_mut(&mut self) -> &mut Resolver<'a> { self.r }
178+
}
179+
189180
impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
190181
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
191182
let parent_scope = &self.parent_scope;
@@ -603,8 +594,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
603594
self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
604595
};
605596

606-
self.r.populate_module_if_necessary(module);
607-
608597
let used = self.process_legacy_macro_imports(item, module);
609598
let binding =
610599
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
@@ -922,6 +911,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
922911
span);
923912
self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
924913

914+
module.populate_on_access.set(false);
925915
for child in self.r.cstore.item_children_untracked(def_id, self.r.session) {
926916
let res = child.res.map_id(|_| panic!("unexpected id"));
927917
let ns = if let Res::Def(DefKind::AssocTy, _) = res {
@@ -935,7 +925,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
935925
self.r.has_self.insert(res.def_id());
936926
}
937927
}
938-
module.populated.set(true);
939928
}
940929
Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
941930
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
@@ -952,7 +941,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
952941
}
953942

954943
fn legacy_import_macro(&mut self,
955-
name: Name,
944+
name: ast::Name,
956945
binding: &'a NameBinding<'a>,
957946
span: Span,
958947
allow_shadowing: bool) {
@@ -1021,9 +1010,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
10211010
if let Some(span) = import_all {
10221011
let directive = macro_use_directive(self, span);
10231012
self.r.potentially_unused_imports.push(directive);
1024-
module.for_each_child(|ident, ns, binding| if ns == MacroNS {
1025-
let imported_binding = self.r.import(binding, directive);
1026-
self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
1013+
module.for_each_child(self, |this, ident, ns, binding| if ns == MacroNS {
1014+
let imported_binding = this.r.import(binding, directive);
1015+
this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
10271016
});
10281017
} else {
10291018
for ident in single_imports.iter().cloned() {

src/librustc_resolve/diagnostics.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,13 @@ crate fn add_typo_suggestion(
7373
false
7474
}
7575

76-
crate fn add_module_candidates(
77-
module: Module<'_>, names: &mut Vec<TypoSuggestion>, filter_fn: &impl Fn(Res) -> bool
76+
crate fn add_module_candidates<'a>(
77+
resolver: &mut Resolver<'a>,
78+
module: Module<'a>,
79+
names: &mut Vec<TypoSuggestion>,
80+
filter_fn: &impl Fn(Res) -> bool,
7881
) {
79-
for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
82+
for (&(ident, _), resolution) in resolver.resolutions(module).borrow().iter() {
8083
if let Some(binding) = resolution.borrow().binding {
8184
let res = binding.res();
8285
if filter_fn(res) {
@@ -402,10 +405,10 @@ impl<'a> Resolver<'a> {
402405
Scope::CrateRoot => {
403406
let root_ident = Ident::new(kw::PathRoot, ident.span);
404407
let root_module = this.resolve_crate_root(root_ident);
405-
add_module_candidates(root_module, &mut suggestions, filter_fn);
408+
add_module_candidates(this, root_module, &mut suggestions, filter_fn);
406409
}
407410
Scope::Module(module) => {
408-
add_module_candidates(module, &mut suggestions, filter_fn);
411+
add_module_candidates(this, module, &mut suggestions, filter_fn);
409412
}
410413
Scope::MacroUsePrelude => {
411414
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
@@ -453,7 +456,7 @@ impl<'a> Resolver<'a> {
453456
Scope::StdLibPrelude => {
454457
if let Some(prelude) = this.prelude {
455458
let mut tmp_suggestions = Vec::new();
456-
add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
459+
add_module_candidates(this, prelude, &mut tmp_suggestions, filter_fn);
457460
suggestions.extend(tmp_suggestions.into_iter().filter(|s| {
458461
use_prelude || this.is_builtin_macro(s.res)
459462
}));
@@ -509,11 +512,9 @@ impl<'a> Resolver<'a> {
509512
while let Some((in_module,
510513
path_segments,
511514
in_module_is_extern)) = worklist.pop() {
512-
self.populate_module_if_necessary(in_module);
513-
514515
// We have to visit module children in deterministic order to avoid
515516
// instabilities in reported imports (#43552).
516-
in_module.for_each_child_stable(|ident, ns, name_binding| {
517+
in_module.for_each_child_stable(self, |this, ident, ns, name_binding| {
517518
// avoid imports entirely
518519
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
519520
// avoid non-importable candidates as well
@@ -547,7 +548,7 @@ impl<'a> Resolver<'a> {
547548
// outside crate private modules => no need to check this)
548549
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
549550
let did = match res {
550-
Res::Def(DefKind::Ctor(..), did) => self.parent(did),
551+
Res::Def(DefKind::Ctor(..), did) => this.parent(did),
551552
_ => res.opt_def_id(),
552553
};
553554
candidates.push(ImportSuggestion { did, path });
@@ -607,8 +608,6 @@ impl<'a> Resolver<'a> {
607608
krate: crate_id,
608609
index: CRATE_DEF_INDEX,
609610
});
610-
self.populate_module_if_necessary(&crate_root);
611-
612611
suggestions.extend(self.lookup_import_candidates_from_module(
613612
lookup_ident, namespace, crate_root, ident, &filter_fn));
614613
}
@@ -805,7 +804,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
805804
/// at the root of the crate instead of the module where it is defined
806805
/// ```
807806
pub(crate) fn check_for_module_export_macro(
808-
&self,
807+
&mut self,
809808
directive: &'b ImportDirective<'b>,
810809
module: ModuleOrUniformRoot<'b>,
811810
ident: Ident,
@@ -826,7 +825,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
826825
return None;
827826
}
828827

829-
let resolutions = crate_module.resolutions.borrow();
828+
let resolutions = self.r.resolutions(crate_module).borrow();
830829
let resolution = resolutions.get(&(ident, MacroNS))?;
831830
let binding = resolution.borrow().binding()?;
832831
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {

src/librustc_resolve/late.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
19291929
let mut traits = module.traits.borrow_mut();
19301930
if traits.is_none() {
19311931
let mut collected_traits = Vec::new();
1932-
module.for_each_child(|name, ns, binding| {
1932+
module.for_each_child(self.r, |_, name, ns, binding| {
19331933
if ns != TypeNS { return }
19341934
match binding.res() {
19351935
Res::Def(DefKind::Trait, _) |

src/librustc_resolve/late/diagnostics.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
548548
// Items in scope
549549
if let RibKind::ModuleRibKind(module) = rib.kind {
550550
// Items from this module
551-
add_module_candidates(module, &mut names, &filter_fn);
551+
add_module_candidates(self.r, module, &mut names, &filter_fn);
552552

553553
if let ModuleKind::Block(..) = module.kind {
554554
// We can see through blocks
@@ -577,7 +577,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
577577
}));
578578

579579
if let Some(prelude) = self.r.prelude {
580-
add_module_candidates(prelude, &mut names, &filter_fn);
580+
add_module_candidates(self.r, prelude, &mut names, &filter_fn);
581581
}
582582
}
583583
break;
@@ -599,7 +599,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
599599
mod_path, Some(TypeNS), false, span, CrateLint::No
600600
) {
601601
if let ModuleOrUniformRoot::Module(module) = module {
602-
add_module_candidates(module, &mut names, &filter_fn);
602+
add_module_candidates(self.r, module, &mut names, &filter_fn);
603603
}
604604
}
605605
}
@@ -717,9 +717,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
717717
// abort if the module is already found
718718
if result.is_some() { break; }
719719

720-
self.r.populate_module_if_necessary(in_module);
721-
722-
in_module.for_each_child_stable(|ident, _, name_binding| {
720+
in_module.for_each_child_stable(self.r, |_, ident, _, name_binding| {
723721
// abort if the module is already found or if name_binding is private external
724722
if result.is_some() || !name_binding.vis.is_visible_locally() {
725723
return
@@ -750,10 +748,8 @@ impl<'a> LateResolutionVisitor<'a, '_> {
750748

751749
fn collect_enum_variants(&mut self, def_id: DefId) -> Option<Vec<Path>> {
752750
self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
753-
self.r.populate_module_if_necessary(enum_module);
754-
755751
let mut variants = Vec::new();
756-
enum_module.for_each_child_stable(|ident, _, name_binding| {
752+
enum_module.for_each_child_stable(self.r, |_, ident, _, name_binding| {
757753
if let Res::Def(DefKind::Variant, _) = name_binding.res() {
758754
let mut segms = enum_import_suggestion.path.segments.clone();
759755
segms.push(ast::PathSegment::from_ident(ident));

src/librustc_resolve/lib.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,8 @@ impl ModuleKind {
431431
}
432432
}
433433

434+
type Resolutions<'a> = RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>;
435+
434436
/// One node in the tree of modules.
435437
pub struct ModuleData<'a> {
436438
parent: Option<Module<'a>>,
@@ -439,7 +441,11 @@ pub struct ModuleData<'a> {
439441
// The def id of the closest normal module (`mod`) ancestor (including this module).
440442
normal_ancestor_id: DefId,
441443

442-
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
444+
// Mapping between names and their (possibly in-progress) resolutions in this module.
445+
// Resolutions in modules from other crates are not populated until accessed.
446+
lazy_resolutions: Resolutions<'a>,
447+
// True if this is a module from other crate that needs to be populated on access.
448+
populate_on_access: Cell<bool>,
443449

444450
// Macro invocations that can expand into items in this module.
445451
unresolved_invocations: RefCell<FxHashSet<ExpnId>>,
@@ -452,11 +458,6 @@ pub struct ModuleData<'a> {
452458
// Used to memoize the traits in this module for faster searches through all traits in scope.
453459
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
454460

455-
// Whether this module is populated. If not populated, any attempt to
456-
// access the children must be preceded with a
457-
// `populate_module_if_necessary` call.
458-
populated: Cell<bool>,
459-
460461
/// Span of the module itself. Used for error reporting.
461462
span: Span,
462463

@@ -475,30 +476,34 @@ impl<'a> ModuleData<'a> {
475476
parent,
476477
kind,
477478
normal_ancestor_id,
478-
resolutions: Default::default(),
479+
lazy_resolutions: Default::default(),
480+
populate_on_access: Cell::new(!normal_ancestor_id.is_local()),
479481
unresolved_invocations: Default::default(),
480482
no_implicit_prelude: false,
481483
glob_importers: RefCell::new(Vec::new()),
482484
globs: RefCell::new(Vec::new()),
483485
traits: RefCell::new(None),
484-
populated: Cell::new(normal_ancestor_id.is_local()),
485486
span,
486487
expansion,
487488
}
488489
}
489490

490-
fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
491-
for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() {
492-
name_resolution.borrow().binding.map(|binding| f(ident, ns, binding));
491+
fn for_each_child<R, F>(&'a self, resolver: &mut R, mut f: F)
492+
where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>)
493+
{
494+
for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
495+
name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
493496
}
494497
}
495498

496-
fn for_each_child_stable<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
497-
let resolutions = self.resolutions.borrow();
499+
fn for_each_child_stable<R, F>(&'a self, resolver: &mut R, mut f: F)
500+
where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>)
501+
{
502+
let resolutions = resolver.as_mut().resolutions(self).borrow();
498503
let mut resolutions = resolutions.iter().collect::<Vec<_>>();
499504
resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns));
500505
for &(&(ident, ns), &resolution) in resolutions.iter() {
501-
resolution.borrow().binding.map(|binding| f(ident, ns, binding));
506+
resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
502507
}
503508
}
504509

@@ -983,6 +988,10 @@ impl<'a> ResolverArenas<'a> {
983988
}
984989
}
985990

991+
impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
992+
fn as_mut(&mut self) -> &mut Resolver<'a> { self }
993+
}
994+
986995
impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> {
987996
fn parent(self, id: DefId) -> Option<DefId> {
988997
match id.krate {
@@ -2634,7 +2643,6 @@ impl<'a> Resolver<'a> {
26342643
return None;
26352644
};
26362645
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
2637-
self.populate_module_if_necessary(&crate_root);
26382646
Some((crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root())
26392647
.to_name_binding(self.arenas))
26402648
}

0 commit comments

Comments
 (0)