From fa6f5adf73a6e9a2b73fd6792cab475e8108951d Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 18 Jul 2021 18:12:17 +0200 Subject: [PATCH 1/3] Gather module items after lowering. --- compiler/rustc_ast_lowering/src/item.rs | 6 -- compiler/rustc_ast_lowering/src/lib.rs | 19 +--- compiler/rustc_hir/src/hir.rs | 16 +--- compiler/rustc_interface/src/passes.rs | 8 +- compiler/rustc_lint/src/late.rs | 6 +- compiler/rustc_middle/src/hir/map/mod.rs | 89 ++++++++++++++++++- compiler/rustc_middle/src/hir/mod.rs | 15 +++- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_passes/src/hir_id_validator.rs | 6 +- compiler/rustc_typeck/src/impl_wf_check.rs | 4 +- compiler/rustc_typeck/src/lib.rs | 8 +- src/librustdoc/core.rs | 8 +- 13 files changed, 121 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b7497c713f3..252bc676dbe 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -50,12 +50,6 @@ fn visit_item(&mut self, item: &'a Item) { self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; match item.kind { - ItemKind::Mod(..) => { - let def_id = this.lctx.lower_node_id(item.id).expect_owner(); - let old_current_module = mem::replace(&mut this.lctx.current_module, def_id); - visit::walk_item(this, item); - this.lctx.current_module = old_current_module; - } ItemKind::Impl(box ImplKind { ref of_trait, .. }) => { this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8d731d7a578..5cda9c4aae3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -102,8 +102,6 @@ struct LoweringContext<'a, 'hir: 'a> { owners: IndexVec>>, bodies: BTreeMap>, - modules: BTreeMap, - generator_kind: Option, attrs: BTreeMap, @@ -152,8 +150,6 @@ struct LoweringContext<'a, 'hir: 'a> { /// vector. in_scope_lifetimes: Vec, - current_module: LocalDefId, - current_hir_id_owner: (LocalDefId, u32), item_local_id_counters: NodeMap, node_id_to_hir_id: IndexVec>, @@ -327,7 +323,6 @@ pub fn lower_crate<'a, 'hir>( arena, owners: IndexVec::default(), bodies: BTreeMap::new(), - modules: BTreeMap::new(), attrs: BTreeMap::default(), catch_scope: None, loop_scope: None, @@ -335,7 +330,6 @@ pub fn lower_crate<'a, 'hir>( is_in_trait_impl: false, is_in_dyn_type: false, anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, - current_module: CRATE_DEF_ID, current_hir_id_owner: (CRATE_DEF_ID, 0), item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), @@ -508,13 +502,8 @@ fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) { } } - let krate = hir::Crate { - owners: self.owners, - bodies: self.bodies, - modules: self.modules, - trait_map, - attrs: self.attrs, - }; + let krate = + hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs }; self.arena.alloc(krate) } @@ -523,7 +512,6 @@ fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId { let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::Item(item)); - self.modules.entry(self.current_module).or_default().items.insert(id); id } @@ -532,7 +520,6 @@ fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignI let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item)); - self.modules.entry(self.current_module).or_default().foreign_items.insert(id); id } @@ -541,7 +528,6 @@ fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId { let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item)); - self.modules.entry(self.current_module).or_default().impl_items.insert(id); id } @@ -550,7 +536,6 @@ fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId let item = self.arena.alloc(item); self.owners.ensure_contains_elem(id.def_id, || None); self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item)); - self.modules.entry(self.current_module).or_default().trait_items.insert(id); id } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 84bc37170c6..7ed74375c51 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -21,7 +21,7 @@ use rustc_target::spec::abi::Abi; use smallvec::SmallVec; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::fmt; #[derive(Copy, Clone, Encodable, HashStable_Generic)] @@ -653,16 +653,6 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(Default, Encodable, Debug, HashStable_Generic)] -pub struct ModuleItems { - // Use BTreeSets here so items are in the same order as in the - // list of all items in Crate - pub items: BTreeSet, - pub trait_items: BTreeSet, - pub impl_items: BTreeSet, - pub foreign_items: BTreeSet, -} - /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -674,10 +664,6 @@ pub struct Crate<'hir> { pub owners: IndexVec>>, pub bodies: BTreeMap>, - /// A list of modules written out in the order in which they - /// appear in the crate. This includes the main crate module. - pub modules: BTreeMap, - /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. pub trait_map: FxHashMap>>, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 1f3d6f70ff8..cb7529b527e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -8,7 +8,7 @@ use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; -use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal}; +use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; @@ -861,7 +861,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { CStore::from_tcx(tcx).report_unused_deps(tcx); }, { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { tcx.ensure().check_mod_loops(module); tcx.ensure().check_mod_attrs(module); tcx.ensure().check_mod_naked_functions(module); @@ -893,7 +893,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }, { sess.time("liveness_and_intrinsic_checking", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { // this must run before MIR dump, because // "not all control paths return a value" is reported here. // @@ -963,7 +963,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }, { sess.time("privacy_checking_modules", || { - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { + tcx.hir().par_for_each_module(|module| { tcx.ensure().check_mod_privacy(module); }); }); diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 2070fd69d3f..00c3a6fa25e 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -16,7 +16,7 @@ use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore}; use rustc_ast as ast; -use rustc_data_structures::sync::{join, par_iter, ParallelIterator}; +use rustc_data_structures::sync::join; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit as hir_visit; @@ -501,9 +501,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>( || { tcx.sess.time("module_lints", || { // Run per-module lints - par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().lint_mod(module); - }); + tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module)); }); }, ); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 10714a4b706..61ba933c32e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,11 +1,12 @@ use self::collector::NodeCollector; -use crate::hir::{AttributeMap, IndexedHir, Owner}; +use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner}; use crate::ty::TyCtxt; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; +use rustc_data_structures::sync::{self, par_iter}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; @@ -19,6 +20,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; +use std::collections::BTreeSet; pub mod blocks; mod collector; @@ -558,6 +560,31 @@ pub fn visit_item_likes_in_module(&self, module: LocalDefId, visitor: &mut V) } } + pub fn for_each_module(&self, f: impl Fn(LocalDefId)) { + let mut queue = BTreeSet::default(); + queue.insert(CRATE_DEF_ID); + + while let Some(id) = queue.pop_first() { + f(id); + let items = self.tcx.hir_module_items(id); + queue.extend(items.submodules.iter().copied()) + } + } + + pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + sync::Sync) { + use rustc_data_structures::sync::ParallelIterator; + par_iter_submodules(self.tcx, CRATE_DEF_ID, &f); + + fn par_iter_submodules(tcx: TyCtxt<'_>, module: LocalDefId, f: &F) + where + F: Fn(LocalDefId) + sync::Sync, + { + (*f)(module); + let items = tcx.hir_module_items(module); + par_iter(&items.submodules).for_each(|&sm| par_iter_submodules(tcx, sm, f)); + } + } + /// Returns an iterator for the nodes in the ancestor tree of the `current_id` /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> { @@ -1118,3 +1145,63 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { None => format!("unknown node{}", id_str), } } + +pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { + let mut collector = ModuleCollector { + tcx, + submodules: BTreeSet::default(), + items: BTreeSet::default(), + trait_items: BTreeSet::default(), + impl_items: BTreeSet::default(), + foreign_items: BTreeSet::default(), + }; + + let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); + collector.visit_mod(hir_mod, span, hir_id); + + let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = + collector; + return ModuleItems { submodules, items, trait_items, impl_items, foreign_items }; + + struct ModuleCollector<'tcx> { + tcx: TyCtxt<'tcx>, + submodules: BTreeSet, + items: BTreeSet, + trait_items: BTreeSet, + impl_items: BTreeSet, + foreign_items: BTreeSet, + } + + impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { + type Map = Map<'hir>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) + } + + fn visit_item(&mut self, item: &'hir Item<'hir>) { + self.items.insert(item.item_id()); + if let ItemKind::Mod(..) = item.kind { + // If this declares another module, do not recurse inside it. + self.submodules.insert(item.def_id); + } else { + intravisit::walk_item(self, item) + } + } + + fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { + self.trait_items.insert(item.trait_item_id()); + intravisit::walk_trait_item(self, item) + } + + fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { + self.impl_items.insert(item.impl_item_id()); + intravisit::walk_impl_item(self, item) + } + + fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { + self.foreign_items.insert(item.foreign_item_id()); + intravisit::walk_foreign_item(self, item) + } + } +} diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index c8ea7454f0b..7d660b18ae1 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -17,7 +17,7 @@ use rustc_hir::*; use rustc_index::vec::{Idx, IndexVec}; use rustc_span::DUMMY_SP; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; /// Result of HIR indexing. #[derive(Debug)] @@ -121,6 +121,17 @@ fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[At } } +#[derive(Default, Encodable, Debug, HashStable)] +pub struct ModuleItems { + // Use BTreeSets here so items are in the same order as in the + // list of all items in Crate + submodules: BTreeSet, + items: BTreeSet, + trait_items: BTreeSet, + impl_items: BTreeSet, + foreign_items: BTreeSet, +} + impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn hir(self) -> map::Map<'tcx> { @@ -140,7 +151,7 @@ pub fn provide(providers: &mut Providers) { providers.hir_crate = |tcx, ()| tcx.untracked_crate; providers.index_hir = map::index_hir; providers.crate_hash = map::crate_hash; - providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id]; + providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { let owner = tcx.index_hir(()).map[id].as_ref()?; let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 94267ec64c7..02f0294c8ad 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -33,6 +33,7 @@ #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(if_let_guard)] +#![feature(map_first_last)] #![feature(never_type)] #![feature(extern_types)] #![feature(new_uninit)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d6f3b6f3248..0ff444faa7a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -52,8 +52,8 @@ /// /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. /// Avoid calling this query directly. - query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems { - eval_always + query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems { + storage(ArenaCacheSelector<'tcx>) desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } } diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 18f61c6e1c1..eff1096c855 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; +use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; @@ -18,9 +18,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let errors = Lock::new(Vec::new()); let hir_map = tcx.hir(); - par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| { + hir_map.par_for_each_module(|module_id| { hir_map - .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors }); + .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors }) }); let errors = errors.into_inner(); diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 194c4efdbb0..9b23bf241cc 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -58,9 +58,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { // We will tag this as part of the WF check -- logically, it is, // but it's one that we must perform earlier than the rest of // WfCheck. - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_impl_wf(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)) } fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index c703ca96ada..f8714cdc70c 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -473,9 +473,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // FIXME(matthewjasper) We shouldn't need to use `track_errors`. tcx.sess.track_errors(|| { tcx.sess.time("type_collecting", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().collect_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module)) }); })?; @@ -505,9 +503,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync. tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(())); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index bd1d970fc19..2f3787535aa 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -330,18 +330,14 @@ impl<'tcx> DocContext<'tcx> { // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes. tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); tcx.sess.abort_if_errors(); tcx.sess.time("missing_docs", || { rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); }); tcx.sess.time("check_mod_attrs", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_attrs(module); - } + tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module)) }); rustc_passes::stability::check_unused_or_stable_features(tcx); From 6bbb0792ea7cf0322b896f1cf2a9d57b418ef106 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 7 Sep 2021 20:07:33 +0200 Subject: [PATCH 2/3] Use boxed slice instead of BTreeSet. --- compiler/rustc_middle/src/hir/map/mod.rs | 56 ++++++++++--------- compiler/rustc_middle/src/hir/mod.rs | 18 +++--- ...ime-used-in-debug-macro-issue-70152.stderr | 22 ++++---- 3 files changed, 51 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 61ba933c32e..ef46771cd0f 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -20,7 +20,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi::Abi; -use std::collections::BTreeSet; +use std::collections::VecDeque; pub mod blocks; mod collector; @@ -543,28 +543,28 @@ pub fn visit_item_likes_in_module(&self, module: LocalDefId, visitor: &mut V) { let module = self.tcx.hir_module_items(module); - for id in &module.items { + for id in module.items.iter() { visitor.visit_item(self.item(*id)); } - for id in &module.trait_items { + for id in module.trait_items.iter() { visitor.visit_trait_item(self.trait_item(*id)); } - for id in &module.impl_items { + for id in module.impl_items.iter() { visitor.visit_impl_item(self.impl_item(*id)); } - for id in &module.foreign_items { + for id in module.foreign_items.iter() { visitor.visit_foreign_item(self.foreign_item(*id)); } } pub fn for_each_module(&self, f: impl Fn(LocalDefId)) { - let mut queue = BTreeSet::default(); - queue.insert(CRATE_DEF_ID); + let mut queue = VecDeque::new(); + queue.push_back(CRATE_DEF_ID); - while let Some(id) = queue.pop_first() { + while let Some(id) = queue.pop_front() { f(id); let items = self.tcx.hir_module_items(id); queue.extend(items.submodules.iter().copied()) @@ -581,7 +581,7 @@ fn par_iter_submodules(tcx: TyCtxt<'_>, module: LocalDefId, f: &F) { (*f)(module); let items = tcx.hir_module_items(module); - par_iter(&items.submodules).for_each(|&sm| par_iter_submodules(tcx, sm, f)); + par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f)); } } @@ -1149,11 +1149,11 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String { pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems { let mut collector = ModuleCollector { tcx, - submodules: BTreeSet::default(), - items: BTreeSet::default(), - trait_items: BTreeSet::default(), - impl_items: BTreeSet::default(), - foreign_items: BTreeSet::default(), + submodules: Vec::default(), + items: Vec::default(), + trait_items: Vec::default(), + impl_items: Vec::default(), + foreign_items: Vec::default(), }; let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id); @@ -1161,15 +1161,21 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> Module let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } = collector; - return ModuleItems { submodules, items, trait_items, impl_items, foreign_items }; + return ModuleItems { + submodules: submodules.into_boxed_slice(), + items: items.into_boxed_slice(), + trait_items: trait_items.into_boxed_slice(), + impl_items: impl_items.into_boxed_slice(), + foreign_items: foreign_items.into_boxed_slice(), + }; struct ModuleCollector<'tcx> { tcx: TyCtxt<'tcx>, - submodules: BTreeSet, - items: BTreeSet, - trait_items: BTreeSet, - impl_items: BTreeSet, - foreign_items: BTreeSet, + submodules: Vec, + items: Vec, + trait_items: Vec, + impl_items: Vec, + foreign_items: Vec, } impl<'hir> Visitor<'hir> for ModuleCollector<'hir> { @@ -1180,27 +1186,27 @@ fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { } fn visit_item(&mut self, item: &'hir Item<'hir>) { - self.items.insert(item.item_id()); + self.items.push(item.item_id()); if let ItemKind::Mod(..) = item.kind { // If this declares another module, do not recurse inside it. - self.submodules.insert(item.def_id); + self.submodules.push(item.def_id); } else { intravisit::walk_item(self, item) } } fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) { - self.trait_items.insert(item.trait_item_id()); + self.trait_items.push(item.trait_item_id()); intravisit::walk_trait_item(self, item) } fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) { - self.impl_items.insert(item.impl_item_id()); + self.impl_items.push(item.impl_item_id()); intravisit::walk_impl_item(self, item) } fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { - self.foreign_items.insert(item.foreign_item_id()); + self.foreign_items.push(item.foreign_item_id()); intravisit::walk_foreign_item(self, item) } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 7d660b18ae1..de4b75f9463 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -17,7 +17,7 @@ use rustc_hir::*; use rustc_index::vec::{Idx, IndexVec}; use rustc_span::DUMMY_SP; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; /// Result of HIR indexing. #[derive(Debug)] @@ -121,15 +121,15 @@ fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[At } } -#[derive(Default, Encodable, Debug, HashStable)] +/// Gather the LocalDefId for each item-like within a module, including items contained within +/// bodies. The Ids are in visitor order. This is used to partition a pass between modules. +#[derive(Debug, HashStable)] pub struct ModuleItems { - // Use BTreeSets here so items are in the same order as in the - // list of all items in Crate - submodules: BTreeSet, - items: BTreeSet, - trait_items: BTreeSet, - impl_items: BTreeSet, - foreign_items: BTreeSet, + submodules: Box<[LocalDefId]>, + items: Box<[ItemId]>, + trait_items: Box<[TraitItemId]>, + impl_items: Box<[ImplItemId]>, + foreign_items: Box<[ForeignItemId]>, } impl<'tcx> TyCtxt<'tcx> { diff --git a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr index 8c87f6da8dc..e18d725faef 100644 --- a/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr +++ b/src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr @@ -8,6 +8,17 @@ LL | a: &'b str, | = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes +error[E0261]: use of undeclared lifetime name `'b` + --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 + | +LL | #[derive(Eq, PartialEq)] + | -- lifetime `'b` is missing in item created through this procedural macro +LL | struct Test { +LL | a: &'b str, + | ^^ undeclared lifetime + | + = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes + error[E0261]: use of undeclared lifetime name `'b` --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13 | @@ -24,17 +35,6 @@ help: consider introducing lifetime `'b` here LL | fn foo<'b>(&'b self) {} | ++++ -error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9 - | -LL | #[derive(Eq, PartialEq)] - | -- lifetime `'b` is missing in item created through this procedural macro -LL | struct Test { -LL | a: &'b str, - | ^^ undeclared lifetime - | - = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0261`. From 91575f89ccf6111f27ae8a65612e5a14ebd54900 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 8 Sep 2021 17:24:03 +0200 Subject: [PATCH 3/3] Use non-recursive algorithm in non-parallel compiler. --- compiler/rustc_middle/src/hir/map/mod.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ef46771cd0f..fa186f4a931 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -6,7 +6,6 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{self, par_iter}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; @@ -571,13 +570,20 @@ pub fn for_each_module(&self, f: impl Fn(LocalDefId)) { } } - pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + sync::Sync) { - use rustc_data_structures::sync::ParallelIterator; + #[cfg(not(parallel_compiler))] + #[inline] + pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) { + self.for_each_module(f) + } + + #[cfg(parallel_compiler)] + pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) { + use rustc_data_structures::sync::{par_iter, ParallelIterator}; par_iter_submodules(self.tcx, CRATE_DEF_ID, &f); fn par_iter_submodules(tcx: TyCtxt<'_>, module: LocalDefId, f: &F) where - F: Fn(LocalDefId) + sync::Sync, + F: Fn(LocalDefId) + Sync, { (*f)(module); let items = tcx.hir_module_items(module);