Skip to content

Commit bf37928

Browse files
committed
Make lowering incremental.
1 parent 3f18306 commit bf37928

File tree

9 files changed

+127
-119
lines changed

9 files changed

+127
-119
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3903,6 +3903,7 @@ dependencies = [
39033903
"rustc_expand",
39043904
"rustc_hir",
39053905
"rustc_incremental",
3906+
"rustc_index",
39063907
"rustc_lint",
39073908
"rustc_metadata",
39083909
"rustc_middle",

compiler/rustc_ast_lowering/src/item.rs

+35-51
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ use rustc_ast::visit::AssocCtxt;
77
use rustc_ast::*;
88
use rustc_data_structures::fx::FxHashMap;
99
use rustc_data_structures::sorted_map::SortedMap;
10-
use rustc_data_structures::steal::Steal;
1110
use rustc_errors::struct_span_err;
1211
use rustc_hir as hir;
1312
use rustc_hir::def::{DefKind, Res};
14-
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
15-
use rustc_index::vec::{Idx, IndexVec};
16-
use rustc_middle::ty::{AstOwner, ResolverOutputs, TyCtxt};
13+
use rustc_hir::def_id::CRATE_DEF_ID;
14+
use rustc_middle::ty::{DefIdTree, ResolverOutputs, TyCtxt};
1715
use rustc_session::utils::NtToTokenstream;
1816
use rustc_span::source_map::DesugaringKind;
1917
use rustc_span::symbol::{kw, sym, Ident};
@@ -24,12 +22,10 @@ use tracing::debug;
2422

2523
use std::iter;
2624

27-
pub(super) struct ItemLowerer<'a, 'hir> {
25+
pub(super) struct ItemLowerer<'hir> {
2826
pub(super) tcx: TyCtxt<'hir>,
2927
pub(super) resolver: &'hir ResolverOutputs,
3028
pub(super) nt_to_tokenstream: NtToTokenstream,
31-
pub(super) ast_index: &'a IndexVec<LocalDefId, Steal<AstOwner>>,
32-
pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
3329
}
3430

3531
/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
@@ -52,13 +48,13 @@ fn add_ty_alias_where_clause(
5248
}
5349
}
5450

55-
impl<'a, 'hir> ItemLowerer<'a, 'hir> {
51+
impl<'hir> ItemLowerer<'hir> {
5652
fn with_lctx(
5753
&mut self,
5854
owner: NodeId,
5955
f: impl FnOnce(&mut LoweringContext<'hir>) -> hir::OwnerNode<'hir>,
60-
) {
61-
let next_node_id = self.resolver.next_node_id;
56+
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
57+
let current_hir_id_owner = self.resolver.node_id_to_def_id[&owner];
6258
let mut lctx = LoweringContext {
6359
// Pseudo-globals.
6460
tcx: self.tcx,
@@ -71,13 +67,15 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
7167
bodies: Vec::new(),
7268
attrs: SortedMap::default(),
7369
children: FxHashMap::default(),
74-
current_hir_id_owner: CRATE_DEF_ID,
75-
item_local_id_counter: hir::ItemLocalId::new(0),
76-
node_id_to_local_id: Default::default(),
7770
local_id_to_def_id: SortedMap::new(),
7871
trait_map: Default::default(),
7972
local_node_id_to_def_id: FxHashMap::default(),
80-
next_node_id,
73+
next_node_id: self.resolver.next_node_id,
74+
75+
// HirId management.
76+
current_hir_id_owner,
77+
node_id_to_local_id: [(owner, hir::ItemLocalId::from_u32(0))].into_iter().collect(),
78+
item_local_id_counter: hir::ItemLocalId::from_u32(1), // 0 is `current_hir_id_owner`.
8179

8280
// Lowering state.
8381
catch_scope: None,
@@ -93,35 +91,15 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
9391
allow_gen_future: Some([sym::gen_future][..].into()),
9492
allow_into_future: Some([sym::into_future][..].into()),
9593
};
96-
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
9794

98-
for (def_id, info) in lctx.children {
99-
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
100-
debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom));
101-
self.owners[def_id] = info;
102-
}
103-
}
95+
let item = f(&mut lctx);
96+
debug_assert_eq!(current_hir_id_owner, item.def_id());
10497

105-
pub(super) fn lower_node(
106-
&mut self,
107-
def_id: LocalDefId,
108-
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
109-
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
110-
if let hir::MaybeOwner::Phantom = self.owners[def_id] {
111-
let node = self.ast_index[def_id].steal();
112-
match node {
113-
AstOwner::NonOwner | AstOwner::Synthetic(..) => {}
114-
AstOwner::Crate(c) => self.lower_crate(&c),
115-
AstOwner::Item(item) => self.lower_item(&item),
116-
AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(&item, ctxt),
117-
AstOwner::ForeignItem(item) => self.lower_foreign_item(&item),
118-
}
119-
}
120-
121-
self.owners[def_id]
98+
let info = lctx.make_owner_info(item);
99+
hir::MaybeOwner::Owner(self.tcx.hir_arena.alloc(info))
122100
}
123101

124-
fn lower_crate(&mut self, c: &Crate) {
102+
pub(super) fn lower_crate(&mut self, c: &Crate) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
125103
debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
126104
self.with_lctx(CRATE_NODE_ID, |lctx| {
127105
let module = lctx.lower_mod(&c.items, &c.spans);
@@ -130,25 +108,28 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
130108
})
131109
}
132110

133-
fn lower_item(&mut self, item: &Item) {
111+
pub(super) fn lower_item(
112+
&mut self,
113+
item: &Item,
114+
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
134115
self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
135116
}
136117

137-
fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
118+
pub(super) fn lower_assoc_item(
119+
&mut self,
120+
item: &AssocItem,
121+
ctxt: AssocCtxt,
122+
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
138123
let def_id = self.resolver.node_id_to_def_id[&item.id];
139124

140-
let parent_id = {
141-
let parent = self.tcx.hir().def_key(def_id).parent;
142-
let local_def_index = parent.unwrap();
143-
LocalDefId { local_def_index }
144-
};
125+
let parent_id = self.tcx.local_parent(def_id).unwrap();
145126

146-
let parent_hir = self.lower_node(parent_id).unwrap();
127+
let parent_hir = self.tcx.hir().expect_item(parent_id);
147128
self.with_lctx(item.id, |lctx| {
148129
// Evaluate with the lifetimes in `params` in-scope.
149130
// This is used to track which lifetimes have already been defined,
150131
// and which need to be replicated when lowering an async fn.
151-
match parent_hir.node().expect_item().kind {
132+
match parent_hir.kind {
152133
hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => {
153134
lctx.is_in_trait_impl = of_trait.is_some();
154135
}
@@ -162,7 +143,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
162143
})
163144
}
164145

165-
fn lower_foreign_item(&mut self, item: &ForeignItem) {
146+
pub(super) fn lower_foreign_item(
147+
&mut self,
148+
item: &ForeignItem,
149+
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
166150
self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
167151
}
168152
}
@@ -545,7 +529,7 @@ impl<'hir> LoweringContext<'hir> {
545529
let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
546530
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
547531
if let Some(attrs) = attrs {
548-
this.attrs.insert(hir::ItemLocalId::new(0), attrs);
532+
this.attrs.insert(hir::ItemLocalId::from_u32(0), attrs);
549533
}
550534

551535
let item = hir::Item {
@@ -619,7 +603,7 @@ impl<'hir> LoweringContext<'hir> {
619603
let kind =
620604
this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
621605
if let Some(attrs) = attrs {
622-
this.attrs.insert(hir::ItemLocalId::new(0), attrs);
606+
this.attrs.insert(hir::ItemLocalId::from_u32(0), attrs);
623607
}
624608

625609
let item = hir::Item {

compiler/rustc_ast_lowering/src/lib.rs

+38-44
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
5858
use rustc_hir::definitions::DefPathData;
5959
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
6060
use rustc_index::vec::{Idx, IndexVec};
61-
use rustc_middle::ty::{AstOwner, ResolverOutputs, TyCtxt};
61+
use rustc_middle::ty::{AstOwner, DefIdTree, ResolverOutputs, TyCtxt};
6262
use rustc_session::parse::feature_err;
6363
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
6464
use rustc_session::Session;
@@ -422,56 +422,46 @@ pub fn index_crate(
422422
}
423423
}
424424

425-
/// Compute the hash for the HIR of the full crate.
426-
/// This hash will then be part of the crate_hash which is stored in the metadata.
427-
fn compute_hir_hash(
428-
tcx: TyCtxt<'_>,
429-
owners: &IndexVec<LocalDefId, hir::MaybeOwner<&hir::OwnerInfo<'_>>>,
430-
) -> Fingerprint {
431-
let mut hir_body_nodes: Vec<_> = owners
432-
.iter_enumerated()
433-
.filter_map(|(def_id, info)| {
434-
let info = info.as_owner()?;
435-
let def_path_hash = tcx.hir().def_path_hash(def_id);
436-
Some((def_path_hash, info))
437-
})
438-
.collect();
439-
hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
440-
441-
tcx.with_stable_hashing_context(|mut hcx| {
442-
let mut stable_hasher = StableHasher::new();
443-
hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher);
444-
stable_hasher.finish()
445-
})
446-
}
447-
448-
pub fn lower_crate<'hir>(
425+
pub fn lower_to_hir<'hir>(
449426
tcx: TyCtxt<'hir>,
427+
def_id: LocalDefId,
450428
nt_to_tokenstream: NtToTokenstream,
451-
) -> hir::Crate<'hir> {
429+
) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> {
452430
let _prof_timer = tcx.sess.prof.verbose_generic_activity("hir_lowering");
453431

454432
let resolver = tcx.resolutions(());
455-
let ast_index = &tcx.untracked_crate;
433+
let node = tcx.untracked_crate.get(def_id);
456434

457-
let mut owners = IndexVec::from_fn_n(
458-
|_| hir::MaybeOwner::Phantom,
459-
tcx.definitions_untracked().def_index_count(),
460-
);
435+
let mut item_lowerer = item::ItemLowerer { tcx, resolver, nt_to_tokenstream };
461436

462-
for def_id in ast_index.indices() {
463-
item::ItemLowerer {
464-
tcx,
465-
resolver,
466-
nt_to_tokenstream,
467-
ast_index: ast_index,
468-
owners: &mut owners,
469-
}
470-
.lower_node(def_id);
471-
}
437+
let node = node.map(Steal::steal);
472438

473-
let hir_hash = compute_hir_hash(tcx, &owners);
474-
hir::Crate { owners, hir_hash }
439+
// The item existed in the AST.
440+
let parent_id = match node {
441+
Some(AstOwner::Crate(c)) => return item_lowerer.lower_crate(&c),
442+
Some(AstOwner::Item(item)) => return item_lowerer.lower_item(&item),
443+
Some(AstOwner::AssocItem(item, ctxt)) => {
444+
return item_lowerer.lower_assoc_item(&item, ctxt);
445+
}
446+
Some(AstOwner::ForeignItem(item)) => return item_lowerer.lower_foreign_item(&item),
447+
Some(AstOwner::Synthetic(parent_id)) => parent_id,
448+
Some(AstOwner::NonOwner) | None => tcx.local_parent(def_id).unwrap(),
449+
};
450+
451+
// The item did not exist in the AST, it was created by its parent.
452+
let mut parent_info = tcx.lower_to_hir(parent_id);
453+
if let hir::MaybeOwner::NonOwner(hir_id) = parent_info {
454+
parent_info = tcx.lower_to_hir(hir_id.owner);
455+
}
456+
457+
let parent_info = parent_info.unwrap();
458+
*parent_info.children.get(&def_id).unwrap_or_else(|| {
459+
panic!(
460+
"{:?} does not appear in children of {:?}",
461+
def_id,
462+
parent_info.nodes.node().def_id()
463+
)
464+
})
475465
}
476466

477467
#[derive(Copy, Clone, PartialEq)]
@@ -552,6 +542,7 @@ impl<'hir> LoweringContext<'hir> {
552542
let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
553543
let current_local_counter =
554544
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
545+
let current_children = std::mem::take(&mut self.children);
555546
// Do not reset `next_node_id` and `node_id_to_def_id` as we want to refer to the
556547
// subdefinitions' nodes.
557548

@@ -570,6 +561,8 @@ impl<'hir> LoweringContext<'hir> {
570561
self.trait_map = current_trait_map;
571562
self.current_hir_id_owner = current_owner;
572563
self.item_local_id_counter = current_local_counter;
564+
self.children = current_children;
565+
self.children.extend(&info.children);
573566

574567
let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info));
575568
debug_assert!(_old.is_none())
@@ -580,6 +573,7 @@ impl<'hir> LoweringContext<'hir> {
580573
let mut bodies = std::mem::take(&mut self.bodies);
581574
let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
582575
let trait_map = std::mem::take(&mut self.trait_map);
576+
let children = std::mem::take(&mut self.children);
583577

584578
#[cfg(debug_assertions)]
585579
for (id, attrs) in attrs.iter() {
@@ -610,7 +604,7 @@ impl<'hir> LoweringContext<'hir> {
610604
hir::AttributeMap { map: attrs, hash }
611605
};
612606

613-
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
607+
self.tcx.hir_arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map, children })
614608
}
615609

616610
/// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate

compiler/rustc_hir/src/hir.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,8 @@ pub struct OwnerInfo<'hir> {
756756
/// Map indicating what traits are in scope for places where this
757757
/// is relevant; generated by resolve.
758758
pub trait_map: FxHashMap<ItemLocalId, &'hir [TraitCandidate]>,
759+
/// Owners generated as side-effect by lowering.
760+
pub children: FxHashMap<LocalDefId, MaybeOwner<&'hir OwnerInfo<'hir>>>,
759761
}
760762

761763
impl<'tcx> OwnerInfo<'tcx> {
@@ -769,30 +771,27 @@ impl<'tcx> OwnerInfo<'tcx> {
769771
pub enum MaybeOwner<T> {
770772
Owner(T),
771773
NonOwner(HirId),
772-
/// Used as a placeholder for unused LocalDefId.
773-
Phantom,
774774
}
775775

776776
impl<T> MaybeOwner<T> {
777777
pub fn as_owner(self) -> Option<T> {
778778
match self {
779779
MaybeOwner::Owner(i) => Some(i),
780-
MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None,
780+
MaybeOwner::NonOwner(_) => None,
781781
}
782782
}
783783

784784
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> MaybeOwner<U> {
785785
match self {
786786
MaybeOwner::Owner(i) => MaybeOwner::Owner(f(i)),
787787
MaybeOwner::NonOwner(hir_id) => MaybeOwner::NonOwner(hir_id),
788-
MaybeOwner::Phantom => MaybeOwner::Phantom,
789788
}
790789
}
791790

792791
pub fn unwrap(self) -> T {
793792
match self {
794793
MaybeOwner::Owner(i) => i,
795-
MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => panic!("Not a HIR owner"),
794+
MaybeOwner::NonOwner(_) => panic!("Not a HIR owner"),
796795
}
797796
}
798797
}

compiler/rustc_interface/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
3232
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
3333
rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true }
3434
rustc_hir = { path = "../rustc_hir" }
35+
rustc_index = { path = "../rustc_index" }
3536
rustc_metadata = { path = "../rustc_metadata" }
3637
rustc_const_eval = { path = "../rustc_const_eval" }
3738
rustc_mir_build = { path = "../rustc_mir_build" }

0 commit comments

Comments
 (0)