Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 1c7f85f

Browse files
committed
Perform indexing during lowering.
Do not access DefId<->HirId maps before they are initialized.
1 parent c09eaea commit 1c7f85f

File tree

12 files changed

+117
-169
lines changed

12 files changed

+117
-169
lines changed

compiler/rustc_middle/src/hir/map/collector.rs renamed to compiler/rustc_ast_lowering/src/index.rs

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use crate::hir::map::Map;
2-
use crate::hir::{IndexedHir, OwnerNodes, ParentedNode};
31
use rustc_data_structures::fx::FxHashMap;
42
use rustc_hir as hir;
53
use rustc_hir::def_id::LocalDefId;
@@ -12,16 +10,16 @@ use rustc_span::source_map::SourceMap;
1210
use rustc_span::{Span, DUMMY_SP};
1311

1412
use std::iter::repeat;
13+
use tracing::debug;
1514

1615
/// A visitor that walks over the HIR and collects `Node`s into a HIR map.
1716
pub(super) struct NodeCollector<'a, 'hir> {
18-
/// The crate
19-
krate: &'hir Crate<'hir>,
20-
2117
/// Source map
2218
source_map: &'a SourceMap,
19+
bodies: &'a IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
2320

24-
nodes: OwnerNodes<'hir>,
21+
/// Outputs
22+
nodes: IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>,
2523
parenting: FxHashMap<LocalDefId, ItemLocalId>,
2624

2725
/// The parent of this node
@@ -42,28 +40,21 @@ fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V
4240
map[k] = Some(v);
4341
}
4442

45-
pub(super) fn collect<'a, 'hir: 'a>(
46-
sess: &'a Session,
47-
krate: &'hir Crate<'hir>,
48-
definitions: &'a definitions::Definitions,
49-
owner: LocalDefId,
50-
) -> Option<IndexedHir<'hir>> {
51-
let info = krate.owners.get(owner)?.as_ref()?;
52-
let item = info.node;
43+
pub(super) fn index_hir<'hir>(
44+
sess: &Session,
45+
definitions: &definitions::Definitions,
46+
item: hir::OwnerNode<'hir>,
47+
bodies: &IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
48+
) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, FxHashMap<LocalDefId, ItemLocalId>) {
5349
let mut nodes = IndexVec::new();
5450
nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: item.into() }));
5551
let mut collector = NodeCollector {
56-
krate,
5752
source_map: sess.source_map(),
58-
owner,
59-
parent_node: ItemLocalId::new(0),
6053
definitions,
61-
nodes: OwnerNodes {
62-
hash: info.hash,
63-
node_hash: info.node_hash,
64-
nodes,
65-
bodies: &info.bodies,
66-
},
54+
owner: item.def_id(),
55+
parent_node: ItemLocalId::new(0),
56+
nodes,
57+
bodies,
6758
parenting: FxHashMap::default(),
6859
};
6960

@@ -75,7 +66,7 @@ pub(super) fn collect<'a, 'hir: 'a>(
7566
OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item),
7667
};
7768

78-
Some(IndexedHir { nodes: collector.nodes, parenting: collector.parenting })
69+
(collector.nodes, collector.parenting)
7970
}
8071

8172
impl<'a, 'hir> NodeCollector<'a, 'hir> {
@@ -87,17 +78,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
8778
// owner of that node.
8879
if cfg!(debug_assertions) {
8980
if hir_id.owner != self.owner {
90-
let node_str = match self.definitions.opt_hir_id_to_local_def_id(hir_id) {
91-
Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate_verbose(),
92-
None => format!("{:?}", node),
93-
};
94-
95-
span_bug!(
96-
span,
97-
"inconsistent DepNode at `{:?}` for `{}`: \
81+
panic!(
82+
"inconsistent DepNode at `{:?}` for `{:?}`: \
9883
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
9984
self.source_map.span_to_diagnostic_string(span),
100-
node_str,
85+
node,
10186
self.definitions.def_path(self.owner).to_string_no_crate_verbose(),
10287
self.owner,
10388
self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(),
@@ -107,7 +92,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
10792
}
10893

10994
insert_vec_map(
110-
&mut self.nodes.nodes,
95+
&mut self.nodes,
11196
hir_id.local_id,
11297
ParentedNode { parent: self.parent_node, node: node },
11398
);
@@ -122,18 +107,12 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
122107
}
123108

124109
fn insert_nested(&mut self, item: LocalDefId) {
125-
let dk_parent = self.definitions.def_key(item).parent.unwrap();
126-
let dk_parent = LocalDefId { local_def_index: dk_parent };
127-
let dk_parent = self.definitions.local_def_id_to_hir_id(dk_parent);
128-
debug_assert_eq!(dk_parent.owner, self.owner, "Different parents for {:?}", item);
129-
if dk_parent.local_id != self.parent_node {
130-
self.parenting.insert(item, self.parent_node);
131-
}
110+
self.parenting.insert(item, self.parent_node);
132111
}
133112
}
134113

135114
impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
136-
type Map = Map<'hir>;
115+
type Map = !;
137116

138117
/// Because we want to track parent items and so forth, enable
139118
/// deep walking so that we walk nested items in the context of
@@ -161,8 +140,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
161140
}
162141

163142
fn visit_nested_body(&mut self, id: BodyId) {
164-
let body = self.krate.body(id);
165143
debug_assert_eq!(id.hir_id.owner, self.owner);
144+
let body = self.bodies[id.hir_id.local_id].unwrap();
166145
self.visit_body(body);
167146
}
168147

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
101101
let old_len = self.in_scope_lifetimes.len();
102102

103103
let parent_generics =
104-
match self.owners[parent_hir_id].as_ref().unwrap().node.expect_item().kind {
104+
match self.owners[parent_hir_id].as_ref().unwrap().node().expect_item().kind {
105105
hir::ItemKind::Impl(hir::Impl { ref generics, .. })
106106
| hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
107107
_ => &[],

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#![feature(crate_visibility_modifier)]
3434
#![feature(box_patterns)]
3535
#![feature(iter_zip)]
36+
#![feature(never_type)]
3637
#![recursion_limit = "256"]
3738

3839
use rustc_ast::token::{self, Token};
@@ -78,6 +79,7 @@ macro_rules! arena_vec {
7879
mod asm;
7980
mod block;
8081
mod expr;
82+
mod index;
8183
mod item;
8284
mod pat;
8385
mod path;
@@ -434,6 +436,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
434436
self.local_node_ids.push(owner);
435437

436438
let item = f(self);
439+
debug_assert_eq!(def_id, item.def_id());
437440
let info = self.make_owner_info(item);
438441

439442
self.attrs = current_attrs;
@@ -470,8 +473,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
470473
}
471474

472475
let (hash, node_hash) = self.hash_body(node, &bodies);
476+
let (nodes, parenting) =
477+
index::index_hir(self.sess, self.resolver.definitions(), node, &bodies);
478+
let nodes = hir::OwnerNodes { hash, node_hash, nodes, bodies };
473479

474-
hir::OwnerInfo { hash, node_hash, node, attrs, bodies, trait_map }
480+
hir::OwnerInfo { nodes, parenting, attrs, trait_map }
475481
}
476482

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

compiler/rustc_hir/src/arena.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ macro_rules! arena_types {
3737
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
3838
[] local: rustc_hir::Local<$tcx>,
3939
[few] mod_: rustc_hir::Mod<$tcx>,
40+
[] owner_info: rustc_hir::OwnerInfo<$tcx>,
4041
[] param: rustc_hir::Param<$tcx>,
4142
[] pat: rustc_hir::Pat<$tcx>,
4243
[] path: rustc_hir::Path<$tcx>,

compiler/rustc_hir/src/hir.rs

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::def::{CtorKind, DefKind, Res};
2-
use crate::def_id::{DefId, CRATE_DEF_ID};
2+
use crate::def_id::DefId;
33
crate use crate::hir_id::{HirId, ItemLocalId};
44
use crate::LangItem;
55

@@ -663,18 +663,49 @@ pub struct WhereEqPredicate<'hir> {
663663
pub rhs_ty: &'hir Ty<'hir>,
664664
}
665665

666+
/// HIR node coupled with its parent's id in the same HIR owner.
667+
///
668+
/// The parent is trash when the node is a HIR owner.
669+
#[derive(Clone, Debug)]
670+
pub struct ParentedNode<'tcx> {
671+
pub parent: ItemLocalId,
672+
pub node: Node<'tcx>,
673+
}
674+
675+
#[derive(Debug)]
676+
pub struct OwnerNodes<'tcx> {
677+
/// Pre-computed hash of the full HIR.
678+
pub hash: Fingerprint,
679+
/// Pre-computed hash of the top node.
680+
pub node_hash: Fingerprint,
681+
/// Full HIR for the current owner.
682+
// The zeroth node's parent is trash, but is never accessed.
683+
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
684+
/// Content of local bodies.
685+
pub bodies: IndexVec<ItemLocalId, Option<&'tcx Body<'tcx>>>,
686+
}
687+
666688
#[derive(Debug)]
667689
pub struct OwnerInfo<'hir> {
668-
pub node: OwnerNode<'hir>,
690+
/// Contents of the HIR.
691+
pub nodes: OwnerNodes<'hir>,
692+
/// Map from each nested owner to its parent's local id.
693+
pub parenting: FxHashMap<LocalDefId, ItemLocalId>,
694+
669695
pub attrs: BTreeMap<ItemLocalId, &'hir [Attribute]>,
670-
pub bodies: IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
671696
/// Map indicating what traits are in scope for places where this
672697
/// is relevant; generated by resolve.
673698
pub trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
674-
/// Pre-computed hash of the full HIR.
675-
pub hash: Fingerprint,
676-
/// Pre-computed hash of the top node.
677-
pub node_hash: Fingerprint,
699+
}
700+
701+
impl<'tcx> OwnerInfo<'tcx> {
702+
#[inline]
703+
pub fn node(&self) -> OwnerNode<'tcx> {
704+
use rustc_index::vec::Idx;
705+
let node = self.nodes.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
706+
let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
707+
node
708+
}
678709
}
679710

680711
/// The top-level data structure that stores the entire contents of
@@ -688,39 +719,6 @@ pub struct Crate<'hir> {
688719
pub owners: IndexVec<LocalDefId, Option<OwnerInfo<'hir>>>,
689720
}
690721

691-
impl Crate<'hir> {
692-
pub fn module(&self) -> &'hir Mod<'hir> {
693-
let i = self.owners[CRATE_DEF_ID].as_ref().unwrap().node;
694-
if let OwnerNode::Crate(m) = i { m } else { panic!() }
695-
}
696-
697-
pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
698-
self.owners[id.def_id].as_ref().unwrap().node.expect_item()
699-
}
700-
701-
pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
702-
self.owners[id.def_id].as_ref().unwrap().node.expect_trait_item()
703-
}
704-
705-
pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
706-
self.owners[id.def_id].as_ref().unwrap().node.expect_impl_item()
707-
}
708-
709-
pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
710-
self.owners[id.def_id].as_ref().unwrap().node.expect_foreign_item()
711-
}
712-
713-
pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
714-
let HirId { owner, local_id } = id.hir_id;
715-
self.owners[owner].as_ref().unwrap().bodies[local_id].unwrap()
716-
}
717-
718-
pub fn attrs(&self, id: HirId) -> &'hir [Attribute] {
719-
let HirId { owner, local_id } = id;
720-
&self.owners[owner].as_ref().unwrap().attrs.get(&local_id).map(|la| *la).unwrap_or(&[])
721-
}
722-
}
723-
724722
/// A block of statements `{ .. }`, which may have a label (in this case the
725723
/// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
726724
/// the `rules` being anything but `DefaultBlock`.

compiler/rustc_hir/src/intravisit.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,28 @@ pub trait Map<'hir> {
130130
fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
131131
}
132132

133+
// Used when no map is actually available, forcing manual implementation of nested visitors.
134+
impl Map<'hir> for ! {
135+
fn find(&self, _: HirId) -> Option<Node<'hir>> {
136+
unreachable!()
137+
}
138+
fn body(&self, _: BodyId) -> &'hir Body<'hir> {
139+
unreachable!()
140+
}
141+
fn item(&self, _: ItemId) -> &'hir Item<'hir> {
142+
unreachable!()
143+
}
144+
fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
145+
unreachable!()
146+
}
147+
fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
148+
unreachable!()
149+
}
150+
fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
151+
unreachable!()
152+
}
153+
}
154+
133155
/// An erased version of `Map<'hir>`, using dynamic dispatch.
134156
/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`.
135157
pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>);

compiler/rustc_hir/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(in_band_lifetimes)]
77
#![feature(once_cell)]
88
#![feature(min_specialization)]
9+
#![feature(never_type)]
910
#![recursion_limit = "256"]
1011

1112
#[macro_use]

compiler/rustc_hir/src/stable_hash_impls.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
22

33
use crate::hir::{
4-
BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem,
5-
TraitItemId, Ty, VisibilityKind,
4+
BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, OwnerNodes,
5+
TraitItem, TraitItemId, Ty, VisibilityKind,
66
};
77
use crate::hir_id::{HirId, ItemLocalId};
88
use rustc_span::def_id::DefPathHash;
@@ -209,3 +209,12 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
209209
});
210210
}
211211
}
212+
213+
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'tcx> {
214+
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
215+
// We ignore the `nodes` and `bodies` fields since these refer to information included in
216+
// `hash` which is hashed in the collector and used for the crate hash.
217+
let OwnerNodes { hash, node_hash: _, nodes: _, bodies: _ } = *self;
218+
hash.hash_stable(hcx, hasher);
219+
}
220+
}

compiler/rustc_middle/src/arena.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,6 @@ macro_rules! arena_types {
9292
[] tys: rustc_middle::ty::TyS<$tcx>,
9393
[] predicates: rustc_middle::ty::PredicateInner<$tcx>,
9494

95-
// HIR query types
96-
[] indexed_hir: rustc_middle::hir::IndexedHir<$tcx>,
97-
9895
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
9996
// since we need to allocate this type on both the `rustc_hir` arena
10097
// (during lowering) and the `librustc_middle` arena (for decoding MIR)

0 commit comments

Comments
 (0)