Skip to content

Commit

Permalink
Auto merge of #63149 - petrochenkov:lazypop2, r=<try>
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Jul 30, 2019
2 parents f690098 + 2245577 commit ac89e03
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 132 deletions.
86 changes: 29 additions & 57 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ impl<'a> Resolver<'a> {
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
};

self.populate_module_if_necessary(module);
if let Some(name) = self.session.parse_sess.injected_crate_name.try_get() {
if name.as_str() == ident.name.as_str() {
self.injected_crate = Some(module);
Expand Down Expand Up @@ -632,7 +631,7 @@ impl<'a> Resolver<'a> {
}

/// Builds the reduced graph for a single item in an external crate.
fn build_reduced_graph_for_external_crate_res(
crate fn build_reduced_graph_for_external_crate_res(
&mut self,
parent: Module<'a>,
child: Export<ast::NodeId>,
Expand All @@ -645,68 +644,53 @@ impl<'a> Resolver<'a> {
let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene
match res {
Res::Def(kind @ DefKind::Mod, def_id)
| Res::Def(kind @ DefKind::Enum, def_id) => {
| Res::Def(kind @ DefKind::Enum, def_id)
| Res::Def(kind @ DefKind::Trait, def_id) => {
let module = self.new_module(parent,
ModuleKind::Def(kind, def_id, ident.name),
def_id,
expansion,
span);
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
}
Res::Def(DefKind::Variant, _)
Res::Def(DefKind::Struct, _)
| Res::Def(DefKind::Union, _)
| Res::Def(DefKind::Variant, _)
| Res::Def(DefKind::TyAlias, _)
| Res::Def(DefKind::ForeignTy, _)
| Res::Def(DefKind::Existential, _)
| Res::Def(DefKind::TraitAlias, _)
| Res::Def(DefKind::AssocTy, _)
| Res::Def(DefKind::AssocExistential, _)
| Res::PrimTy(..)
| Res::ToolMod => {
self.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));

if let Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) = res {
// Record field names for error reporting.
let field_names = self.cstore.struct_field_names_untracked(def_id);
self.insert_field_names(def_id, field_names);
}
}
Res::Def(DefKind::Fn, _)
| Res::Def(DefKind::Method, _)
| Res::Def(DefKind::Static, _)
| Res::Def(DefKind::Const, _)
| Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => {
self.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));
}
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => {
| Res::Def(DefKind::AssocConst, _)
| Res::Def(DefKind::Ctor(..), _) => {
self.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion));

if let Some(struct_def_id) =
self.cstore.def_key(def_id).parent
.map(|index| DefId { krate: def_id.krate, index: index }) {
self.struct_constructors.insert(struct_def_id, (res, vis));
}
}
Res::Def(DefKind::Trait, def_id) => {
let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name);
let module = self.new_module(parent,
module_kind,
parent.normal_ancestor_id,
expansion,
span);
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));

for child in self.cstore.item_children_untracked(def_id, self.session) {
let res = child.res.map_id(|_| panic!("unexpected id"));
let ns = if let Res::Def(DefKind::AssocTy, _) = res {
TypeNS
} else { ValueNS };
self.define(module, child.ident, ns,
(res, ty::Visibility::Public, DUMMY_SP, expansion));

if self.cstore.associated_item_cloned_untracked(child.res.def_id())
.method_has_self_argument {
self.has_self.insert(res.def_id());
if let Res::Def(DefKind::Method, def_id) = res {
let assoc_item = self.cstore.associated_item_cloned_untracked(def_id);
if assoc_item.method_has_self_argument {
self.has_self.insert(def_id);
}
} else if let Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) = res {
let parent = self.cstore.def_key(def_id).parent;
if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) {
self.struct_constructors.insert(struct_def_id, (res, vis));
}
}
module.populated.set(true);
}
Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => {
self.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion));

// Record field names for error reporting.
let field_names = self.cstore.struct_field_names_untracked(def_id);
self.insert_field_names(def_id, field_names);
}
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
self.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion));
Expand Down Expand Up @@ -780,18 +764,6 @@ impl<'a> Resolver<'a> {
Some(ext)
}

/// Ensures that the reduced graph rooted at the given external module
/// is built, building it if it is not.
pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
if module.populated.get() { return }
let def_id = module.def_id().unwrap();
for child in self.cstore.item_children_untracked(def_id, self.session) {
let child = child.map_id(|_| panic!("unexpected id"));
self.build_reduced_graph_for_external_crate_res(module, child);
}
module.populated.set(true)
}

fn legacy_import_macro(&mut self,
name: Name,
binding: &'a NameBinding<'a>,
Expand Down Expand Up @@ -863,9 +835,9 @@ impl<'a> Resolver<'a> {
if let Some(span) = import_all {
let directive = macro_use_directive(span);
self.potentially_unused_imports.push(directive);
module.for_each_child(|ident, ns, binding| if ns == MacroNS {
let imported_binding = self.import(binding, directive);
self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
self.for_each_child(module, |this, ident, ns, binding| if ns == MacroNS {
let imported_binding = this.import(binding, directive);
this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
});
} else {
for ident in single_imports.iter().cloned() {
Expand Down
59 changes: 28 additions & 31 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,23 @@ fn add_typo_suggestion(
false
}

fn add_module_candidates(
module: Module<'_>, names: &mut Vec<TypoSuggestion>, filter_fn: &impl Fn(Res) -> bool
) {
for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
if let Some(binding) = resolution.borrow().binding {
let res = binding.res();
if filter_fn(res) {
names.push(TypoSuggestion::from_res(ident.name, res));
impl<'a> Resolver<'a> {
fn add_module_candidates(
&mut self,
module: Module<'a>,
names: &mut Vec<TypoSuggestion>,
filter_fn: &impl Fn(Res) -> bool,
) {
for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() {
if let Some(binding) = resolution.borrow().binding {
let res = binding.res();
if filter_fn(res) {
names.push(TypoSuggestion::from_res(ident.name, res));
}
}
}
}
}

impl<'a> Resolver<'a> {
/// Handles error reporting for `smart_resolve_path_fragment` function.
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
pub(crate) fn smart_resolve_report_errors(
Expand Down Expand Up @@ -593,10 +596,10 @@ impl<'a> Resolver<'a> {
Scope::CrateRoot => {
let root_ident = Ident::new(kw::PathRoot, ident.span);
let root_module = this.resolve_crate_root(root_ident);
add_module_candidates(root_module, &mut suggestions, filter_fn);
this.add_module_candidates(root_module, &mut suggestions, filter_fn);
}
Scope::Module(module) => {
add_module_candidates(module, &mut suggestions, filter_fn);
this.add_module_candidates(module, &mut suggestions, filter_fn);
}
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
Expand Down Expand Up @@ -644,7 +647,7 @@ impl<'a> Resolver<'a> {
Scope::StdLibPrelude => {
if let Some(prelude) = this.prelude {
let mut tmp_suggestions = Vec::new();
add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
suggestions.extend(tmp_suggestions.into_iter().filter(|s| {
use_prelude || this.is_builtin_macro(s.res.opt_def_id())
}));
Expand Down Expand Up @@ -694,7 +697,9 @@ impl<'a> Resolver<'a> {
if path.len() == 1 {
// Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates.
for rib in self.ribs[ns].iter().rev() {
// Ribs have to be cloned to avoid borrowing the resolver.
let ribs = self.ribs[ns].clone();
for rib in ribs.iter().rev() {
// Locals and type parameters
for (ident, &res) in &rib.bindings {
if filter_fn(res) {
Expand All @@ -704,7 +709,7 @@ impl<'a> Resolver<'a> {
// Items in scope
if let RibKind::ModuleRibKind(module) = rib.kind {
// Items from this module
add_module_candidates(module, &mut names, &filter_fn);
self.add_module_candidates(module, &mut names, &filter_fn);

if let ModuleKind::Block(..) = module.kind {
// We can see through blocks
Expand Down Expand Up @@ -732,7 +737,7 @@ impl<'a> Resolver<'a> {
}));

if let Some(prelude) = self.prelude {
add_module_candidates(prelude, &mut names, &filter_fn);
self.add_module_candidates(prelude, &mut names, &filter_fn);
}
}
break;
Expand All @@ -754,7 +759,7 @@ impl<'a> Resolver<'a> {
mod_path, Some(TypeNS), false, span, CrateLint::No
) {
if let ModuleOrUniformRoot::Module(module) = module {
add_module_candidates(module, &mut names, &filter_fn);
self.add_module_candidates(module, &mut names, &filter_fn);
}
}
}
Expand Down Expand Up @@ -792,11 +797,9 @@ impl<'a> Resolver<'a> {
while let Some((in_module,
path_segments,
in_module_is_extern)) = worklist.pop() {
self.populate_module_if_necessary(in_module);

// We have to visit module children in deterministic order to avoid
// instabilities in reported imports (#43552).
in_module.for_each_child_stable(|ident, ns, name_binding| {
self.for_each_child_stable(in_module, |this, ident, ns, name_binding| {
// avoid imports entirely
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
// avoid non-importable candidates as well
Expand Down Expand Up @@ -830,7 +833,7 @@ impl<'a> Resolver<'a> {
// outside crate private modules => no need to check this)
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
let did = match res {
Res::Def(DefKind::Ctor(..), did) => self.parent(did),
Res::Def(DefKind::Ctor(..), did) => this.parent(did),
_ => res.opt_def_id(),
};
candidates.push(ImportSuggestion { did, path });
Expand Down Expand Up @@ -890,8 +893,6 @@ impl<'a> Resolver<'a> {
krate: crate_id,
index: CRATE_DEF_INDEX,
});
self.populate_module_if_necessary(&crate_root);

suggestions.extend(self.lookup_import_candidates_from_module(
lookup_ident, namespace, crate_root, ident, &filter_fn));
}
Expand All @@ -910,9 +911,7 @@ impl<'a> Resolver<'a> {
// abort if the module is already found
if result.is_some() { break; }

self.populate_module_if_necessary(in_module);

in_module.for_each_child_stable(|ident, _, name_binding| {
self.for_each_child_stable(in_module, |_, ident, _, name_binding| {
// abort if the module is already found or if name_binding is private external
if result.is_some() || !name_binding.vis.is_visible_locally() {
return
Expand Down Expand Up @@ -943,10 +942,8 @@ impl<'a> Resolver<'a> {

fn collect_enum_variants(&mut self, def_id: DefId) -> Option<Vec<Path>> {
self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
self.populate_module_if_necessary(enum_module);

let mut variants = Vec::new();
enum_module.for_each_child_stable(|ident, _, name_binding| {
self.for_each_child_stable(enum_module, |_, ident, _, name_binding| {
if let Res::Def(DefKind::Variant, _) = name_binding.res() {
let mut segms = enum_import_suggestion.path.segments.clone();
segms.push(ast::PathSegment::from_ident(ident));
Expand Down Expand Up @@ -1147,7 +1144,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
/// at the root of the crate instead of the module where it is defined
/// ```
pub(crate) fn check_for_module_export_macro(
&self,
&mut self,
directive: &'b ImportDirective<'b>,
module: ModuleOrUniformRoot<'b>,
ident: Ident,
Expand All @@ -1168,7 +1165,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
return None;
}

let resolutions = crate_module.resolutions.borrow();
let resolutions = self.resolutions(crate_module).borrow();
let resolution = resolutions.get(&(ident, MacroNS))?;
let binding = resolution.borrow().binding()?;
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
Expand Down
Loading

0 comments on commit ac89e03

Please sign in to comment.