Skip to content

Commit a8017d6

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 ee36cfa commit a8017d6

File tree

7 files changed

+80
-85
lines changed

7 files changed

+80
-85
lines changed

src/librustc_resolve/build_reduced_graph.rs

+7-34
Original file line numberDiff line numberDiff line change
@@ -157,19 +157,6 @@ impl<'a> Resolver<'a> {
157157
self.macro_map.insert(def_id, ext.clone());
158158
Some(ext)
159159
}
160-
161-
/// Ensures that the reduced graph rooted at the given external module
162-
/// is built, building it if it is not.
163-
pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
164-
if module.populated.get() { return }
165-
let def_id = module.def_id().unwrap();
166-
for child in self.cstore.item_children_untracked(def_id, self.session) {
167-
let child = child.map_id(|_| panic!("unexpected id"));
168-
BuildReducedGraphVisitor { parent_scope: self.dummy_parent_scope(), r: self }
169-
.build_reduced_graph_for_external_crate_res(module, child);
170-
}
171-
module.populated.set(true)
172-
}
173160
}
174161

175162
pub struct BuildReducedGraphVisitor<'a, 'b> {
@@ -595,7 +582,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
595582
self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
596583
};
597584

598-
self.r.populate_module_if_necessary(module);
599585
if let Some(name) = self.r.session.parse_sess.injected_crate_name.try_get() {
600586
if name.as_str() == ident.name.as_str() {
601587
self.r.injected_crate = Some(module);
@@ -868,7 +854,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
868854
}
869855

870856
/// Builds the reduced graph for a single item in an external crate.
871-
fn build_reduced_graph_for_external_crate_res(
857+
crate fn build_reduced_graph_for_external_crate_res(
872858
&mut self,
873859
parent: Module<'a>,
874860
child: Export<ast::NodeId>,
@@ -922,6 +908,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
922908
span);
923909
self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
924910

911+
module.populate_on_access.set(false);
925912
for child in self.r.cstore.item_children_untracked(def_id, self.r.session) {
926913
let res = child.res.map_id(|_| panic!("unexpected id"));
927914
let ns = if let Res::Def(DefKind::AssocTy, _) = res {
@@ -935,7 +922,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
935922
self.r.has_self.insert(res.def_id());
936923
}
937924
}
938-
module.populated.set(true);
939925
}
940926
Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
941927
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
@@ -951,19 +937,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
951937
}
952938
}
953939

954-
fn legacy_import_macro(&mut self,
955-
name: Name,
956-
binding: &'a NameBinding<'a>,
957-
span: Span,
958-
allow_shadowing: bool) {
959-
if self.r.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing {
960-
let msg = format!("`{}` is already in scope", name);
961-
let note =
962-
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
963-
self.r.session.struct_span_err(span, &msg).note(note).emit();
964-
}
965-
}
966-
967940
/// Returns `true` if we should consider the underlying `extern crate` to be used.
968941
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> bool {
969942
let mut import_all = None;
@@ -1021,9 +994,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
1021994
if let Some(span) = import_all {
1022995
let directive = macro_use_directive(self, span);
1023996
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);
997+
module.for_each_child(&mut self.r, |this, ident, ns, binding| if ns == MacroNS {
998+
let imported_binding = this.import(binding, directive);
999+
this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
10271000
});
10281001
} else {
10291002
for ident in single_imports.iter().cloned() {
@@ -1039,8 +1012,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
10391012
let directive = macro_use_directive(self, ident.span);
10401013
self.r.potentially_unused_imports.push(directive);
10411014
let imported_binding = self.r.import(binding, directive);
1042-
self.legacy_import_macro(ident.name, imported_binding,
1043-
ident.span, allow_shadowing);
1015+
self.r.legacy_import_macro(ident.name, imported_binding,
1016+
ident.span, allow_shadowing);
10441017
} else {
10451018
span_err!(self.r.session, ident.span, E0469, "imported macro not found");
10461019
}

src/librustc_resolve/diagnostics.rs

+13-14
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) {
@@ -391,10 +394,10 @@ impl<'a> Resolver<'a> {
391394
Scope::CrateRoot => {
392395
let root_ident = Ident::new(kw::PathRoot, ident.span);
393396
let root_module = this.resolve_crate_root(root_ident);
394-
add_module_candidates(root_module, &mut suggestions, filter_fn);
397+
add_module_candidates(this, root_module, &mut suggestions, filter_fn);
395398
}
396399
Scope::Module(module) => {
397-
add_module_candidates(module, &mut suggestions, filter_fn);
400+
add_module_candidates(this, module, &mut suggestions, filter_fn);
398401
}
399402
Scope::MacroUsePrelude => {
400403
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
@@ -442,7 +445,7 @@ impl<'a> Resolver<'a> {
442445
Scope::StdLibPrelude => {
443446
if let Some(prelude) = this.prelude {
444447
let mut tmp_suggestions = Vec::new();
445-
add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
448+
add_module_candidates(this, prelude, &mut tmp_suggestions, filter_fn);
446449
suggestions.extend(tmp_suggestions.into_iter().filter(|s| {
447450
use_prelude || this.is_builtin_macro(s.res.opt_def_id())
448451
}));
@@ -498,11 +501,9 @@ impl<'a> Resolver<'a> {
498501
while let Some((in_module,
499502
path_segments,
500503
in_module_is_extern)) = worklist.pop() {
501-
self.populate_module_if_necessary(in_module);
502-
503504
// We have to visit module children in deterministic order to avoid
504505
// instabilities in reported imports (#43552).
505-
in_module.for_each_child_stable(|ident, ns, name_binding| {
506+
in_module.for_each_child_stable(self, |this, ident, ns, name_binding| {
506507
// avoid imports entirely
507508
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
508509
// avoid non-importable candidates as well
@@ -536,7 +537,7 @@ impl<'a> Resolver<'a> {
536537
// outside crate private modules => no need to check this)
537538
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
538539
let did = match res {
539-
Res::Def(DefKind::Ctor(..), did) => self.parent(did),
540+
Res::Def(DefKind::Ctor(..), did) => this.parent(did),
540541
_ => res.opt_def_id(),
541542
};
542543
candidates.push(ImportSuggestion { did, path });
@@ -596,8 +597,6 @@ impl<'a> Resolver<'a> {
596597
krate: crate_id,
597598
index: CRATE_DEF_INDEX,
598599
});
599-
self.populate_module_if_necessary(&crate_root);
600-
601600
suggestions.extend(self.lookup_import_candidates_from_module(
602601
lookup_ident, namespace, crate_root, ident, &filter_fn));
603602
}
@@ -794,7 +793,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
794793
/// at the root of the crate instead of the module where it is defined
795794
/// ```
796795
pub(crate) fn check_for_module_export_macro(
797-
&self,
796+
&mut self,
798797
directive: &'b ImportDirective<'b>,
799798
module: ModuleOrUniformRoot<'b>,
800799
ident: Ident,
@@ -815,7 +814,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
815814
return None;
816815
}
817816

818-
let resolutions = crate_module.resolutions.borrow();
817+
let resolutions = self.r.resolutions(crate_module).borrow();
819818
let resolution = resolutions.get(&(ident, MacroNS))?;
820819
let binding = resolution.borrow().binding()?;
821820
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {

src/librustc_resolve/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
19341934
let mut traits = module.traits.borrow_mut();
19351935
if traits.is_none() {
19361936
let mut collected_traits = Vec::new();
1937-
module.for_each_child(|name, ns, binding| {
1937+
module.for_each_child(&mut self.r, |_, name, ns, binding| {
19381938
if ns != TypeNS { return }
19391939
match binding.res() {
19401940
Res::Def(DefKind::Trait, _) |

src/librustc_resolve/late/diagnostics.rs

+5-9
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(&mut 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(&mut 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(&mut 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(&mut 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(&mut 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

+19-15
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ impl ModuleKind {
408408
}
409409
}
410410

411+
type Resolutions<'a> = RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>;
412+
411413
/// One node in the tree of modules.
412414
pub struct ModuleData<'a> {
413415
parent: Option<Module<'a>>,
@@ -416,7 +418,11 @@ pub struct ModuleData<'a> {
416418
// The def id of the closest normal module (`mod`) ancestor (including this module).
417419
normal_ancestor_id: DefId,
418420

419-
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
421+
// Mapping between names and their (possibly in-progress) resolutions in this module.
422+
// Resolutions in modules from other crates are not populated until accessed.
423+
lazy_resolutions: Resolutions<'a>,
424+
// True if this is a module from other crate that needs to be populated on access.
425+
populate_on_access: Cell<bool>,
420426
single_segment_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
421427
Option<&'a NameBinding<'a>>)>>,
422428
multi_segment_macro_resolutions: RefCell<Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>,
@@ -434,11 +440,6 @@ pub struct ModuleData<'a> {
434440
// Used to memoize the traits in this module for faster searches through all traits in scope.
435441
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
436442

437-
// Whether this module is populated. If not populated, any attempt to
438-
// access the children must be preceded with a
439-
// `populate_module_if_necessary` call.
440-
populated: Cell<bool>,
441-
442443
/// Span of the module itself. Used for error reporting.
443444
span: Span,
444445

@@ -457,7 +458,8 @@ impl<'a> ModuleData<'a> {
457458
parent,
458459
kind,
459460
normal_ancestor_id,
460-
resolutions: Default::default(),
461+
lazy_resolutions: Default::default(),
462+
populate_on_access: Cell::new(!normal_ancestor_id.is_local()),
461463
single_segment_macro_resolutions: RefCell::new(Vec::new()),
462464
multi_segment_macro_resolutions: RefCell::new(Vec::new()),
463465
builtin_attrs: RefCell::new(Vec::new()),
@@ -466,24 +468,27 @@ impl<'a> ModuleData<'a> {
466468
glob_importers: RefCell::new(Vec::new()),
467469
globs: RefCell::new(Vec::new()),
468470
traits: RefCell::new(None),
469-
populated: Cell::new(normal_ancestor_id.is_local()),
470471
span,
471472
expansion,
472473
}
473474
}
474475

475-
fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
476-
for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() {
477-
name_resolution.borrow().binding.map(|binding| f(ident, ns, binding));
476+
fn for_each_child<F>(&'a self, resolver: &mut Resolver<'a>, mut f: F)
477+
where F: FnMut(&mut Resolver<'a>, Ident, Namespace, &'a NameBinding<'a>)
478+
{
479+
for (&(ident, ns), name_resolution) in resolver.resolutions(self).borrow().iter() {
480+
name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
478481
}
479482
}
480483

481-
fn for_each_child_stable<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
482-
let resolutions = self.resolutions.borrow();
484+
fn for_each_child_stable<F>(&'a self, resolver: &mut Resolver<'a>, mut f: F)
485+
where F: FnMut(&mut Resolver<'a>, Ident, Namespace, &'a NameBinding<'a>)
486+
{
487+
let resolutions = resolver.resolutions(self).borrow();
483488
let mut resolutions = resolutions.iter().collect::<Vec<_>>();
484489
resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns));
485490
for &(&(ident, ns), &resolution) in resolutions.iter() {
486-
resolution.borrow().binding.map(|binding| f(ident, ns, binding));
491+
resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
487492
}
488493
}
489494

@@ -2608,7 +2613,6 @@ impl<'a> Resolver<'a> {
26082613
return None;
26092614
};
26102615
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
2611-
self.populate_module_if_necessary(&crate_root);
26122616
Some((crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root())
26132617
.to_name_binding(self.arenas))
26142618
}

src/librustc_resolve/macros.rs

+13
Original file line numberDiff line numberDiff line change
@@ -869,4 +869,17 @@ impl<'a> Resolver<'a> {
869869

870870
Lrc::new(result)
871871
}
872+
873+
crate fn legacy_import_macro(&mut self,
874+
name: ast::Name,
875+
binding: &'a NameBinding<'a>,
876+
span: Span,
877+
allow_shadowing: bool) {
878+
if self.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing {
879+
let msg = format!("`{}` is already in scope", name);
880+
let note =
881+
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
882+
self.session.struct_span_err(span, &msg).note(note).emit();
883+
}
884+
}
872885
}

0 commit comments

Comments
 (0)