Skip to content

Commit 7b5f952

Browse files
committed
Auto merge of #88703 - cjgillot:lazymod, r=petrochenkov
Gather module items after lowering. This avoids having a non-local analysis inside lowering. By implementing `hir_module_items` using a visitor, we make sure that iterations and visitors are consistent.
2 parents 697118d + 91575f8 commit 7b5f952

File tree

14 files changed

+147
-83
lines changed

14 files changed

+147
-83
lines changed

compiler/rustc_ast_lowering/src/item.rs

-6
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,6 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
5151
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
5252
let this = &mut ItemLowerer { lctx: this };
5353
match item.kind {
54-
ItemKind::Mod(..) => {
55-
let def_id = this.lctx.lower_node_id(item.id).expect_owner();
56-
let old_current_module = mem::replace(&mut this.lctx.current_module, def_id);
57-
visit::walk_item(this, item);
58-
this.lctx.current_module = old_current_module;
59-
}
6054
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
6155
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
6256
}

compiler/rustc_ast_lowering/src/lib.rs

+2-17
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,6 @@ struct LoweringContext<'a, 'hir: 'a> {
102102
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
103103
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
104104

105-
modules: BTreeMap<LocalDefId, hir::ModuleItems>,
106-
107105
generator_kind: Option<hir::GeneratorKind>,
108106

109107
attrs: BTreeMap<hir::HirId, &'hir [Attribute]>,
@@ -152,8 +150,6 @@ struct LoweringContext<'a, 'hir: 'a> {
152150
/// vector.
153151
in_scope_lifetimes: Vec<ParamName>,
154152

155-
current_module: LocalDefId,
156-
157153
current_hir_id_owner: (LocalDefId, u32),
158154
item_local_id_counters: NodeMap<u32>,
159155
node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
@@ -327,15 +323,13 @@ pub fn lower_crate<'a, 'hir>(
327323
arena,
328324
owners: IndexVec::default(),
329325
bodies: BTreeMap::new(),
330-
modules: BTreeMap::new(),
331326
attrs: BTreeMap::default(),
332327
catch_scope: None,
333328
loop_scope: None,
334329
is_in_loop_condition: false,
335330
is_in_trait_impl: false,
336331
is_in_dyn_type: false,
337332
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
338-
current_module: CRATE_DEF_ID,
339333
current_hir_id_owner: (CRATE_DEF_ID, 0),
340334
item_local_id_counters: Default::default(),
341335
node_id_to_hir_id: IndexVec::new(),
@@ -457,13 +451,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
457451
}
458452
}
459453

460-
let krate = hir::Crate {
461-
owners: self.owners,
462-
bodies: self.bodies,
463-
modules: self.modules,
464-
trait_map,
465-
attrs: self.attrs,
466-
};
454+
let krate =
455+
hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs };
467456
self.arena.alloc(krate)
468457
}
469458

@@ -472,7 +461,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
472461
let item = self.arena.alloc(item);
473462
self.owners.ensure_contains_elem(id.def_id, || None);
474463
self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
475-
self.modules.entry(self.current_module).or_default().items.insert(id);
476464
id
477465
}
478466

@@ -481,7 +469,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
481469
let item = self.arena.alloc(item);
482470
self.owners.ensure_contains_elem(id.def_id, || None);
483471
self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
484-
self.modules.entry(self.current_module).or_default().foreign_items.insert(id);
485472
id
486473
}
487474

@@ -490,7 +477,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
490477
let item = self.arena.alloc(item);
491478
self.owners.ensure_contains_elem(id.def_id, || None);
492479
self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
493-
self.modules.entry(self.current_module).or_default().impl_items.insert(id);
494480
id
495481
}
496482

@@ -499,7 +485,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
499485
let item = self.arena.alloc(item);
500486
self.owners.ensure_contains_elem(id.def_id, || None);
501487
self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
502-
self.modules.entry(self.current_module).or_default().trait_items.insert(id);
503488
id
504489
}
505490

compiler/rustc_hir/src/hir.rs

+1-15
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_target::asm::InlineAsmRegOrRegClass;
2121
use rustc_target::spec::abi::Abi;
2222

2323
use smallvec::SmallVec;
24-
use std::collections::{BTreeMap, BTreeSet};
24+
use std::collections::BTreeMap;
2525
use std::fmt;
2626

2727
#[derive(Copy, Clone, Encodable, HashStable_Generic)]
@@ -653,16 +653,6 @@ pub struct WhereEqPredicate<'hir> {
653653
pub rhs_ty: &'hir Ty<'hir>,
654654
}
655655

656-
#[derive(Default, Encodable, Debug, HashStable_Generic)]
657-
pub struct ModuleItems {
658-
// Use BTreeSets here so items are in the same order as in the
659-
// list of all items in Crate
660-
pub items: BTreeSet<ItemId>,
661-
pub trait_items: BTreeSet<TraitItemId>,
662-
pub impl_items: BTreeSet<ImplItemId>,
663-
pub foreign_items: BTreeSet<ForeignItemId>,
664-
}
665-
666656
/// The top-level data structure that stores the entire contents of
667657
/// the crate currently being compiled.
668658
///
@@ -674,10 +664,6 @@ pub struct Crate<'hir> {
674664
pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
675665
pub bodies: BTreeMap<BodyId, Body<'hir>>,
676666

677-
/// A list of modules written out in the order in which they
678-
/// appear in the crate. This includes the main crate module.
679-
pub modules: BTreeMap<LocalDefId, ModuleItems>,
680-
681667
/// Map indicating what traits are in scope for places where this
682668
/// is relevant; generated by resolve.
683669
pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>,

compiler/rustc_interface/src/passes.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_borrowck as mir_borrowck;
88
use rustc_codegen_ssa::back::link::emit_metadata;
99
use rustc_codegen_ssa::traits::CodegenBackend;
1010
use rustc_data_structures::parallel;
11-
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
11+
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
1212
use rustc_data_structures::temp_dir::MaybeTempDir;
1313
use rustc_errors::{ErrorReported, PResult};
1414
use rustc_expand::base::ExtCtxt;
@@ -861,7 +861,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
861861
CStore::from_tcx(tcx).report_unused_deps(tcx);
862862
},
863863
{
864-
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
864+
tcx.hir().par_for_each_module(|module| {
865865
tcx.ensure().check_mod_loops(module);
866866
tcx.ensure().check_mod_attrs(module);
867867
tcx.ensure().check_mod_naked_functions(module);
@@ -893,7 +893,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
893893
},
894894
{
895895
sess.time("liveness_and_intrinsic_checking", || {
896-
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
896+
tcx.hir().par_for_each_module(|module| {
897897
// this must run before MIR dump, because
898898
// "not all control paths return a value" is reported here.
899899
//
@@ -963,7 +963,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
963963
},
964964
{
965965
sess.time("privacy_checking_modules", || {
966-
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
966+
tcx.hir().par_for_each_module(|module| {
967967
tcx.ensure().check_mod_privacy(module);
968968
});
969969
});

compiler/rustc_lint/src/late.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
1717
use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
1818
use rustc_ast as ast;
19-
use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
19+
use rustc_data_structures::sync::join;
2020
use rustc_hir as hir;
2121
use rustc_hir::def_id::LocalDefId;
2222
use rustc_hir::intravisit as hir_visit;
@@ -501,9 +501,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
501501
|| {
502502
tcx.sess.time("module_lints", || {
503503
// Run per-module lints
504-
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
505-
tcx.ensure().lint_mod(module);
506-
});
504+
tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module));
507505
});
508506
},
509507
);

compiler/rustc_middle/src/hir/map/mod.rs

+104-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use self::collector::NodeCollector;
22

3-
use crate::hir::{AttributeMap, IndexedHir, Owner};
3+
use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner};
44
use crate::ty::TyCtxt;
55
use rustc_ast as ast;
66
use rustc_data_structures::fingerprint::Fingerprint;
@@ -19,6 +19,7 @@ use rustc_span::source_map::Spanned;
1919
use rustc_span::symbol::{kw, sym, Ident, Symbol};
2020
use rustc_span::Span;
2121
use rustc_target::spec::abi::Abi;
22+
use std::collections::VecDeque;
2223

2324
pub mod blocks;
2425
mod collector;
@@ -536,23 +537,55 @@ impl<'hir> Map<'hir> {
536537
{
537538
let module = self.tcx.hir_module_items(module);
538539

539-
for id in &module.items {
540+
for id in module.items.iter() {
540541
visitor.visit_item(self.item(*id));
541542
}
542543

543-
for id in &module.trait_items {
544+
for id in module.trait_items.iter() {
544545
visitor.visit_trait_item(self.trait_item(*id));
545546
}
546547

547-
for id in &module.impl_items {
548+
for id in module.impl_items.iter() {
548549
visitor.visit_impl_item(self.impl_item(*id));
549550
}
550551

551-
for id in &module.foreign_items {
552+
for id in module.foreign_items.iter() {
552553
visitor.visit_foreign_item(self.foreign_item(*id));
553554
}
554555
}
555556

557+
pub fn for_each_module(&self, f: impl Fn(LocalDefId)) {
558+
let mut queue = VecDeque::new();
559+
queue.push_back(CRATE_DEF_ID);
560+
561+
while let Some(id) = queue.pop_front() {
562+
f(id);
563+
let items = self.tcx.hir_module_items(id);
564+
queue.extend(items.submodules.iter().copied())
565+
}
566+
}
567+
568+
#[cfg(not(parallel_compiler))]
569+
#[inline]
570+
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) {
571+
self.for_each_module(f)
572+
}
573+
574+
#[cfg(parallel_compiler)]
575+
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) {
576+
use rustc_data_structures::sync::{par_iter, ParallelIterator};
577+
par_iter_submodules(self.tcx, CRATE_DEF_ID, &f);
578+
579+
fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F)
580+
where
581+
F: Fn(LocalDefId) + Sync,
582+
{
583+
(*f)(module);
584+
let items = tcx.hir_module_items(module);
585+
par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f));
586+
}
587+
}
588+
556589
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
557590
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
558591
pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
@@ -1113,3 +1146,69 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
11131146
None => format!("unknown node{}", id_str),
11141147
}
11151148
}
1149+
1150+
pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems {
1151+
let mut collector = ModuleCollector {
1152+
tcx,
1153+
submodules: Vec::default(),
1154+
items: Vec::default(),
1155+
trait_items: Vec::default(),
1156+
impl_items: Vec::default(),
1157+
foreign_items: Vec::default(),
1158+
};
1159+
1160+
let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
1161+
collector.visit_mod(hir_mod, span, hir_id);
1162+
1163+
let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } =
1164+
collector;
1165+
return ModuleItems {
1166+
submodules: submodules.into_boxed_slice(),
1167+
items: items.into_boxed_slice(),
1168+
trait_items: trait_items.into_boxed_slice(),
1169+
impl_items: impl_items.into_boxed_slice(),
1170+
foreign_items: foreign_items.into_boxed_slice(),
1171+
};
1172+
1173+
struct ModuleCollector<'tcx> {
1174+
tcx: TyCtxt<'tcx>,
1175+
submodules: Vec<LocalDefId>,
1176+
items: Vec<ItemId>,
1177+
trait_items: Vec<TraitItemId>,
1178+
impl_items: Vec<ImplItemId>,
1179+
foreign_items: Vec<ForeignItemId>,
1180+
}
1181+
1182+
impl<'hir> Visitor<'hir> for ModuleCollector<'hir> {
1183+
type Map = Map<'hir>;
1184+
1185+
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1186+
intravisit::NestedVisitorMap::All(self.tcx.hir())
1187+
}
1188+
1189+
fn visit_item(&mut self, item: &'hir Item<'hir>) {
1190+
self.items.push(item.item_id());
1191+
if let ItemKind::Mod(..) = item.kind {
1192+
// If this declares another module, do not recurse inside it.
1193+
self.submodules.push(item.def_id);
1194+
} else {
1195+
intravisit::walk_item(self, item)
1196+
}
1197+
}
1198+
1199+
fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
1200+
self.trait_items.push(item.trait_item_id());
1201+
intravisit::walk_trait_item(self, item)
1202+
}
1203+
1204+
fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
1205+
self.impl_items.push(item.impl_item_id());
1206+
intravisit::walk_impl_item(self, item)
1207+
}
1208+
1209+
fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
1210+
self.foreign_items.push(item.foreign_item_id());
1211+
intravisit::walk_foreign_item(self, item)
1212+
}
1213+
}
1214+
}

compiler/rustc_middle/src/hir/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,17 @@ impl<'tcx> AttributeMap<'tcx> {
121121
}
122122
}
123123

124+
/// Gather the LocalDefId for each item-like within a module, including items contained within
125+
/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
126+
#[derive(Debug, HashStable)]
127+
pub struct ModuleItems {
128+
submodules: Box<[LocalDefId]>,
129+
items: Box<[ItemId]>,
130+
trait_items: Box<[TraitItemId]>,
131+
impl_items: Box<[ImplItemId]>,
132+
foreign_items: Box<[ForeignItemId]>,
133+
}
134+
124135
impl<'tcx> TyCtxt<'tcx> {
125136
#[inline(always)]
126137
pub fn hir(self) -> map::Map<'tcx> {
@@ -140,7 +151,7 @@ pub fn provide(providers: &mut Providers) {
140151
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
141152
providers.index_hir = map::index_hir;
142153
providers.crate_hash = map::crate_hash;
143-
providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
154+
providers.hir_module_items = map::hir_module_items;
144155
providers.hir_owner = |tcx, id| {
145156
let owner = tcx.index_hir(()).map[id].as_ref()?;
146157
let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;

compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#![feature(discriminant_kind)]
3434
#![feature(exhaustive_patterns)]
3535
#![feature(if_let_guard)]
36+
#![feature(map_first_last)]
3637
#![feature(never_type)]
3738
#![feature(extern_types)]
3839
#![feature(new_uninit)]

compiler/rustc_middle/src/query/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ rustc_queries! {
5252
///
5353
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
5454
/// Avoid calling this query directly.
55-
query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems {
56-
eval_always
55+
query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
56+
storage(ArenaCacheSelector<'tcx>)
5757
desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
5858
}
5959

compiler/rustc_passes/src/hir_id_validator.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_data_structures::fx::FxHashSet;
2-
use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
2+
use rustc_data_structures::sync::Lock;
33
use rustc_hir as hir;
44
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
55
use rustc_hir::intravisit;
@@ -18,9 +18,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
1818
let errors = Lock::new(Vec::new());
1919
let hir_map = tcx.hir();
2020

21-
par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| {
21+
hir_map.par_for_each_module(|module_id| {
2222
hir_map
23-
.visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors });
23+
.visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors })
2424
});
2525

2626
let errors = errors.into_inner();

0 commit comments

Comments
 (0)