Skip to content

Commit 6b099db

Browse files
committed
Record item-likes in ItemLowerer.
1 parent e5d482e commit 6b099db

File tree

2 files changed

+69
-61
lines changed

2 files changed

+69
-61
lines changed

compiler/rustc_ast_lowering/src/item.rs

+57-48
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{Arena, FnDeclKind};
55
use rustc_ast::ptr::P;
66
use rustc_ast::visit::AssocCtxt;
77
use rustc_ast::*;
8-
use rustc_data_structures::fx::FxHashSet;
8+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
99
use rustc_data_structures::sorted_map::SortedMap;
1010
use rustc_errors::struct_span_err;
1111
use rustc_hir as hir;
@@ -53,18 +53,22 @@ fn add_ty_alias_where_clause(
5353
}
5454

5555
impl<'a, 'hir> ItemLowerer<'a, 'hir> {
56-
fn make_lctx(&mut self) -> LoweringContext<'_, 'hir> {
57-
LoweringContext {
56+
fn with_lctx(
57+
&mut self,
58+
owner: NodeId,
59+
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
60+
) {
61+
let mut lctx = LoweringContext {
5862
// Pseudo-globals.
5963
sess: &self.sess,
6064
resolver: self.resolver,
6165
nt_to_tokenstream: self.nt_to_tokenstream,
6266
arena: self.arena,
63-
owners: self.owners,
6467

6568
// HirId handling.
6669
bodies: Vec::new(),
6770
attrs: SortedMap::default(),
71+
children: FxHashMap::default(),
6872
current_hir_id_owner: CRATE_DEF_ID,
6973
item_local_id_counter: hir::ItemLocalId::new(0),
7074
node_id_to_local_id: Default::default(),
@@ -87,6 +91,13 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
8791
allow_try_trait: Some([sym::try_trait_v2][..].into()),
8892
allow_gen_future: Some([sym::gen_future][..].into()),
8993
allow_into_future: Some([sym::into_future][..].into()),
94+
};
95+
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
96+
97+
for (def_id, info) in lctx.children {
98+
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
99+
debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom));
100+
self.owners[def_id] = info;
90101
}
91102
}
92103

@@ -109,23 +120,21 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
109120
self.owners[def_id]
110121
}
111122

112-
fn lower_crate(&mut self, c: &'a Crate) {
123+
fn lower_crate(&mut self, c: &Crate) {
113124
debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID);
114125

115-
let mut lctx = self.make_lctx();
116-
lctx.with_hir_id_owner(CRATE_NODE_ID, |lctx| {
126+
self.with_lctx(CRATE_NODE_ID, |lctx| {
117127
let module = lctx.lower_mod(&c.items, c.spans.inner_span);
118128
lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
119129
hir::OwnerNode::Crate(lctx.arena.alloc(module))
120130
})
121131
}
122132

123-
fn lower_item(&mut self, item: &'a Item) {
124-
let mut lctx = self.make_lctx();
125-
lctx.with_hir_id_owner(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
133+
fn lower_item(&mut self, item: &Item) {
134+
self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
126135
}
127136

128-
fn lower_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
137+
fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
129138
let def_id = self.resolver.local_def_id(item.id);
130139

131140
let parent_id = {
@@ -135,43 +144,44 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
135144
};
136145

137146
let parent_hir = self.lower_node(parent_id).unwrap().node().expect_item();
138-
let mut lctx = self.make_lctx();
139-
140-
// Evaluate with the lifetimes in `params` in-scope.
141-
// This is used to track which lifetimes have already been defined,
142-
// and which need to be replicated when lowering an async fn.
143-
match parent_hir.kind {
144-
hir::ItemKind::Impl(hir::Impl { ref of_trait, ref generics, .. }) => {
145-
lctx.is_in_trait_impl = of_trait.is_some();
146-
lctx.in_scope_lifetimes = generics
147-
.params
148-
.iter()
149-
.filter(|param| matches!(param.kind, hir::GenericParamKind::Lifetime { .. }))
150-
.map(|param| param.name)
151-
.collect();
152-
}
153-
hir::ItemKind::Trait(_, _, ref generics, ..) => {
154-
lctx.in_scope_lifetimes = generics
155-
.params
156-
.iter()
157-
.filter(|param| matches!(param.kind, hir::GenericParamKind::Lifetime { .. }))
158-
.map(|param| param.name)
159-
.collect();
160-
}
161-
_ => {}
162-
};
147+
self.with_lctx(item.id, |lctx| {
148+
// Evaluate with the lifetimes in `params` in-scope.
149+
// This is used to track which lifetimes have already been defined,
150+
// and which need to be replicated when lowering an async fn.
151+
match parent_hir.kind {
152+
hir::ItemKind::Impl(hir::Impl { ref of_trait, ref generics, .. }) => {
153+
lctx.is_in_trait_impl = of_trait.is_some();
154+
lctx.in_scope_lifetimes = generics
155+
.params
156+
.iter()
157+
.filter(|param| {
158+
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
159+
})
160+
.map(|param| param.name)
161+
.collect();
162+
}
163+
hir::ItemKind::Trait(_, _, ref generics, ..) => {
164+
lctx.in_scope_lifetimes = generics
165+
.params
166+
.iter()
167+
.filter(|param| {
168+
matches!(param.kind, hir::GenericParamKind::Lifetime { .. })
169+
})
170+
.map(|param| param.name)
171+
.collect();
172+
}
173+
_ => {}
174+
};
163175

164-
lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
165-
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
166-
AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
176+
match ctxt {
177+
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
178+
AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
179+
}
167180
})
168181
}
169182

170-
fn lower_foreign_item(&mut self, item: &'a ForeignItem) {
171-
let mut lctx = self.make_lctx();
172-
lctx.with_hir_id_owner(item.id, |lctx| {
173-
hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))
174-
})
183+
fn lower_foreign_item(&mut self, item: &ForeignItem) {
184+
self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
175185
}
176186
}
177187

@@ -555,12 +565,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
555565
let new_id = self.resolver.local_def_id(new_node_id);
556566
let Some(res) = resolutions.next() else {
557567
// Associate an HirId to both ids even if there is no resolution.
558-
self.owners.ensure_contains_elem(new_id, || hir::MaybeOwner::Phantom);
559-
let _old = std::mem::replace(
560-
&mut self.owners[new_id],
568+
let _old = self.children.insert(
569+
new_id,
561570
hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id)),
562571
);
563-
debug_assert!(matches!(_old, hir::MaybeOwner::Phantom));
572+
debug_assert!(_old.is_none());
564573
continue;
565574
};
566575
let ident = *ident;

compiler/rustc_ast_lowering/src/lib.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ mod path;
8585

8686
rustc_hir::arena_types!(rustc_arena::declare_arena);
8787

88-
struct LoweringContext<'a, 'hir> {
88+
struct LoweringContext<'a, 'hir: 'a> {
8989
/// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
9090
sess: &'a Session,
9191

@@ -99,12 +99,12 @@ struct LoweringContext<'a, 'hir> {
9999
/// Used to allocate HIR nodes.
100100
arena: &'hir Arena<'hir>,
101101

102-
/// The items being lowered are collected here.
103-
owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
104102
/// Bodies inside the owner being lowered.
105103
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
106104
/// Attributes inside the owner being lowered.
107105
attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
106+
/// Collect items that were created by lowering the current owner.
107+
children: FxHashMap<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
108108

109109
generator_kind: Option<hir::GeneratorKind>,
110110

@@ -536,13 +536,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
536536
self.current_hir_id_owner = current_owner;
537537
self.item_local_id_counter = current_local_counter;
538538

539-
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
540-
self.owners[def_id] = hir::MaybeOwner::Owner(self.arena.alloc(info));
539+
let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info));
540+
debug_assert!(_old.is_none())
541541
}
542542

543-
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> hir::OwnerInfo<'hir> {
543+
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
544544
let attrs = std::mem::take(&mut self.attrs);
545545
let mut bodies = std::mem::take(&mut self.bodies);
546+
let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
547+
let trait_map = std::mem::take(&mut self.trait_map);
546548

547549
#[cfg(debug_assertions)]
548550
for (id, attrs) in attrs.iter() {
@@ -562,7 +564,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
562564
hash_without_bodies,
563565
nodes,
564566
bodies,
565-
local_id_to_def_id: std::mem::take(&mut self.local_id_to_def_id),
567+
local_id_to_def_id,
566568
};
567569
let attrs = {
568570
let mut hcx = self.resolver.create_stable_hashing_context();
@@ -572,7 +574,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
572574
hir::AttributeMap { map: attrs, hash }
573575
};
574576

575-
hir::OwnerInfo { nodes, parenting, attrs, trait_map: std::mem::take(&mut self.trait_map) }
577+
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
576578
}
577579

578580
/// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate
@@ -620,11 +622,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
620622

621623
assert_ne!(local_id, hir::ItemLocalId::new(0));
622624
if let Some(def_id) = self.resolver.opt_local_def_id(ast_node_id) {
623-
self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
624-
if let o @ hir::MaybeOwner::Phantom = &mut self.owners[def_id] {
625-
// Do not override a `MaybeOwner::Owner` that may already here.
626-
*o = hir::MaybeOwner::NonOwner(hir_id);
627-
}
625+
// Do not override a `MaybeOwner::Owner` that may already here.
626+
self.children.entry(def_id).or_insert(hir::MaybeOwner::NonOwner(hir_id));
628627
self.local_id_to_def_id.insert(local_id, def_id);
629628
}
630629

0 commit comments

Comments
 (0)