Skip to content

Commit 804d973

Browse files
authored
Rollup merge of rust-lang#63149 - petrochenkov:lazypop2, r=eddyb
resolve: Populate external modules in more automatic and lazy way So, resolve had this function `populate_module_if_necessary` for loading module children from other crates from metadata. I never really understood when it should've been called and when not. This PR removes the function and loads the module children automatically on the first access instead. r? @eddyb
2 parents bdfd698 + 5e47cd4 commit 804d973

File tree

7 files changed

+126
-135
lines changed

7 files changed

+126
-135
lines changed

src/librustc_resolve/build_reduced_graph.rs

+53-66
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::{ResolutionError, Determinacy, PathResult, CrateLint};
1616
use rustc::bug;
1717
use rustc::hir::def::{self, *};
1818
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
19+
use rustc::hir::map::DefCollector;
1920
use rustc::ty;
2021
use rustc::middle::cstore::CrateStore;
2122
use rustc_metadata::cstore::LoadedMacro;
@@ -159,33 +160,34 @@ impl<'a> Resolver<'a> {
159160
Some(ext)
160161
}
161162

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-
175163
crate fn build_reduced_graph(
176164
&mut self, fragment: &AstFragment, parent_scope: ParentScope<'a>
177165
) -> LegacyScope<'a> {
166+
fragment.visit_with(&mut DefCollector::new(&mut self.definitions, parent_scope.expansion));
178167
let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
179168
fragment.visit_with(&mut visitor);
180169
visitor.parent_scope.legacy
181170
}
171+
172+
crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
173+
let def_id = module.def_id().expect("unpopulated module without a def-id");
174+
for child in self.cstore.item_children_untracked(def_id, self.session) {
175+
let child = child.map_id(|_| panic!("unexpected id"));
176+
BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) }
177+
.build_reduced_graph_for_external_crate_res(child);
178+
}
179+
}
182180
}
183181

184182
struct BuildReducedGraphVisitor<'a, 'b> {
185183
r: &'b mut Resolver<'a>,
186184
parent_scope: ParentScope<'a>,
187185
}
188186

187+
impl<'a> AsMut<Resolver<'a>> for BuildReducedGraphVisitor<'a, '_> {
188+
fn as_mut(&mut self) -> &mut Resolver<'a> { self.r }
189+
}
190+
189191
impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
190192
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
191193
let parent_scope = &self.parent_scope;
@@ -603,8 +605,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
603605
self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
604606
};
605607

606-
self.r.populate_module_if_necessary(module);
607-
608608
let used = self.process_legacy_macro_imports(item, module);
609609
let binding =
610610
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
@@ -879,80 +879,67 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
879879
// This is only a guess, two equivalent idents may incorrectly get different gensyms here.
880880
let ident = ident.gensym_if_underscore();
881881
let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene
882+
// Record primary definitions.
882883
match res {
883884
Res::Def(kind @ DefKind::Mod, def_id)
884-
| Res::Def(kind @ DefKind::Enum, def_id) => {
885+
| Res::Def(kind @ DefKind::Enum, def_id)
886+
| Res::Def(kind @ DefKind::Trait, def_id) => {
885887
let module = self.r.new_module(parent,
886888
ModuleKind::Def(kind, def_id, ident.name),
887889
def_id,
888890
expansion,
889891
span);
890892
self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
891893
}
892-
Res::Def(DefKind::Variant, _)
894+
Res::Def(DefKind::Struct, _)
895+
| Res::Def(DefKind::Union, _)
896+
| Res::Def(DefKind::Variant, _)
893897
| Res::Def(DefKind::TyAlias, _)
894898
| Res::Def(DefKind::ForeignTy, _)
895899
| Res::Def(DefKind::OpaqueTy, _)
896900
| Res::Def(DefKind::TraitAlias, _)
901+
| Res::Def(DefKind::AssocTy, _)
902+
| Res::Def(DefKind::AssocOpaqueTy, _)
897903
| Res::PrimTy(..)
898-
| Res::ToolMod => {
899-
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
900-
}
904+
| Res::ToolMod =>
905+
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)),
901906
Res::Def(DefKind::Fn, _)
907+
| Res::Def(DefKind::Method, _)
902908
| Res::Def(DefKind::Static, _)
903909
| Res::Def(DefKind::Const, _)
904-
| Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => {
905-
self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
906-
}
907-
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
908-
self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
909-
910-
if let Some(struct_def_id) =
911-
self.r.cstore.def_key(def_id).parent
912-
.map(|index| DefId { krate: def_id.krate, index: index }) {
913-
self.r.struct_constructors.insert(struct_def_id, (res, vis));
914-
}
915-
}
916-
Res::Def(DefKind::Trait, def_id) => {
917-
let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name);
918-
let module = self.r.new_module(parent,
919-
module_kind,
920-
parent.normal_ancestor_id,
921-
expansion,
922-
span);
923-
self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
924-
925-
for child in self.r.cstore.item_children_untracked(def_id, self.r.session) {
926-
let res = child.res.map_id(|_| panic!("unexpected id"));
927-
let ns = if let Res::Def(DefKind::AssocTy, _) = res {
928-
TypeNS
929-
} else { ValueNS };
930-
self.r.define(module, child.ident, ns,
931-
(res, ty::Visibility::Public, DUMMY_SP, expansion));
932-
933-
if self.r.cstore.associated_item_cloned_untracked(child.res.def_id())
934-
.method_has_self_argument {
935-
self.r.has_self.insert(res.def_id());
936-
}
937-
}
938-
module.populated.set(true);
939-
}
910+
| Res::Def(DefKind::AssocConst, _)
911+
| Res::Def(DefKind::Ctor(..), _) =>
912+
self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)),
913+
Res::Def(DefKind::Macro(..), _)
914+
| Res::NonMacroAttr(..) =>
915+
self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)),
916+
Res::Def(DefKind::TyParam, _) | Res::Def(DefKind::ConstParam, _)
917+
| Res::Local(..) | Res::SelfTy(..) | Res::SelfCtor(..) | Res::Err =>
918+
bug!("unexpected resolution: {:?}", res)
919+
}
920+
// Record some extra data for better diagnostics.
921+
match res {
940922
Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
941-
self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));
942-
943-
// Record field names for error reporting.
944923
let field_names = self.r.cstore.struct_field_names_untracked(def_id);
945924
self.insert_field_names(def_id, field_names);
946925
}
947-
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
948-
self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion));
926+
Res::Def(DefKind::Method, def_id) => {
927+
if self.r.cstore.associated_item_cloned_untracked(def_id).method_has_self_argument {
928+
self.r.has_self.insert(def_id);
929+
}
930+
}
931+
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
932+
let parent = self.r.cstore.def_key(def_id).parent;
933+
if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) {
934+
self.r.struct_constructors.insert(struct_def_id, (res, vis));
935+
}
949936
}
950-
_ => bug!("unexpected resolution: {:?}", res)
937+
_ => {}
951938
}
952939
}
953940

954941
fn legacy_import_macro(&mut self,
955-
name: Name,
942+
name: ast::Name,
956943
binding: &'a NameBinding<'a>,
957944
span: Span,
958945
allow_shadowing: bool) {
@@ -1021,9 +1008,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
10211008
if let Some(span) = import_all {
10221009
let directive = macro_use_directive(self, span);
10231010
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);
1011+
module.for_each_child(self, |this, ident, ns, binding| if ns == MacroNS {
1012+
let imported_binding = this.r.import(binding, directive);
1013+
this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
10271014
});
10281015
} else {
10291016
for ident in single_imports.iter().cloned() {

src/librustc_resolve/diagnostics.rs

+20-21
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,23 @@ 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
78-
) {
79-
for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
80-
if let Some(binding) = resolution.borrow().binding {
81-
let res = binding.res();
82-
if filter_fn(res) {
83-
names.push(TypoSuggestion::from_res(ident.name, res));
76+
impl<'a> Resolver<'a> {
77+
crate fn add_module_candidates(
78+
&mut self,
79+
module: Module<'a>,
80+
names: &mut Vec<TypoSuggestion>,
81+
filter_fn: &impl Fn(Res) -> bool,
82+
) {
83+
for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() {
84+
if let Some(binding) = resolution.borrow().binding {
85+
let res = binding.res();
86+
if filter_fn(res) {
87+
names.push(TypoSuggestion::from_res(ident.name, res));
88+
}
8489
}
8590
}
8691
}
87-
}
8892

89-
impl<'a> Resolver<'a> {
9093
/// Combines an error with provided span and emits it.
9194
///
9295
/// This takes the error provided, combines it with the span and any additional spans inside the
@@ -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+
this.add_module_candidates(root_module, &mut suggestions, filter_fn);
406409
}
407410
Scope::Module(module) => {
408-
add_module_candidates(module, &mut suggestions, filter_fn);
411+
this.add_module_candidates(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+
this.add_module_candidates(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

+1-1
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

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot};
22
use crate::{PathResult, PathSource, Segment};
33
use crate::path_names_to_string;
4-
use crate::diagnostics::{add_typo_suggestion, add_module_candidates};
5-
use crate::diagnostics::{ImportSuggestion, TypoSuggestion};
4+
use crate::diagnostics::{add_typo_suggestion, ImportSuggestion, TypoSuggestion};
65
use crate::late::{LateResolutionVisitor, RibKind};
76

87
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
@@ -548,7 +547,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
548547
// Items in scope
549548
if let RibKind::ModuleRibKind(module) = rib.kind {
550549
// Items from this module
551-
add_module_candidates(module, &mut names, &filter_fn);
550+
self.r.add_module_candidates(module, &mut names, &filter_fn);
552551

553552
if let ModuleKind::Block(..) = module.kind {
554553
// We can see through blocks
@@ -577,7 +576,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
577576
}));
578577

579578
if let Some(prelude) = self.r.prelude {
580-
add_module_candidates(prelude, &mut names, &filter_fn);
579+
self.r.add_module_candidates(prelude, &mut names, &filter_fn);
581580
}
582581
}
583582
break;
@@ -599,7 +598,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
599598
mod_path, Some(TypeNS), false, span, CrateLint::No
600599
) {
601600
if let ModuleOrUniformRoot::Module(module) = module {
602-
add_module_candidates(module, &mut names, &filter_fn);
601+
self.r.add_module_candidates(module, &mut names, &filter_fn);
603602
}
604603
}
605604
}
@@ -717,9 +716,7 @@ impl<'a> LateResolutionVisitor<'a, '_> {
717716
// abort if the module is already found
718717
if result.is_some() { break; }
719718

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

751748
fn collect_enum_variants(&mut self, def_id: DefId) -> Option<Vec<Path>> {
752749
self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
753-
self.r.populate_module_if_necessary(enum_module);
754-
755750
let mut variants = Vec::new();
756-
enum_module.for_each_child_stable(|ident, _, name_binding| {
751+
enum_module.for_each_child_stable(self.r, |_, ident, _, name_binding| {
757752
if let Res::Def(DefKind::Variant, _) = name_binding.res() {
758753
let mut segms = enum_import_suggestion.path.segments.clone();
759754
segms.push(ast::PathSegment::from_ident(ident));

0 commit comments

Comments
 (0)