Skip to content

Commit 99d3798

Browse files
committed
Do not compute entry parent when not required.
1 parent 2d341e1 commit 99d3798

File tree

3 files changed

+127
-100
lines changed

3 files changed

+127
-100
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::arena::Arena;
2-
use crate::hir::map::{Entry, HirOwnerData, Map};
2+
use crate::hir::map::{HirOwnerData, Map};
33
use crate::hir::{Owner, OwnerNodes, ParentedNode};
44
use crate::ich::StableHashingContext;
55
use rustc_data_structures::fingerprint::Fingerprint;
@@ -61,6 +61,13 @@ fn hash_body(
6161
stable_hasher.finish()
6262
}
6363

64+
/// Represents an entry and its parent `HirId`.
65+
#[derive(Copy, Clone, Debug)]
66+
pub struct Entry<'hir> {
67+
parent: HirId,
68+
node: Node<'hir>,
69+
}
70+
6471
impl<'a, 'hir> NodeCollector<'a, 'hir> {
6572
pub(super) fn root(
6673
sess: &'a Session,

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

Lines changed: 117 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_hir::intravisit;
1414
use rustc_hir::intravisit::Visitor;
1515
use rustc_hir::itemlikevisit::ItemLikeVisitor;
1616
use rustc_hir::*;
17+
use rustc_index::vec::Idx;
1718
use rustc_span::hygiene::MacroKind;
1819
use rustc_span::source_map::Spanned;
1920
use rustc_span::symbol::{kw, Ident, Symbol};
@@ -23,13 +24,6 @@ use rustc_target::spec::abi::Abi;
2324
pub mod blocks;
2425
mod collector;
2526

26-
/// Represents an entry and its parent `HirId`.
27-
#[derive(Copy, Clone, Debug)]
28-
pub struct Entry<'hir> {
29-
parent: HirId,
30-
node: Node<'hir>,
31-
}
32-
3327
fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
3428
match node {
3529
Node::Item(Item { kind: ItemKind::Fn(sig, _, _), .. })
@@ -108,10 +102,48 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
108102
}
109103

110104
self.current_id = parent_id;
111-
if let Some(entry) = self.map.find_entry(parent_id) {
112-
return Some((parent_id, entry.node));
105+
if let Some(node) = self.map.find(parent_id) {
106+
return Some((parent_id, node));
107+
}
108+
// If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
109+
}
110+
}
111+
}
112+
113+
/// An iterator that walks up the ancestor tree of a given `HirId`.
114+
/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
115+
pub struct ParentOwnerIterator<'map, 'hir> {
116+
current_id: HirId,
117+
map: &'map Map<'hir>,
118+
}
119+
120+
impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> {
121+
type Item = (HirId, Node<'hir>);
122+
123+
fn next(&mut self) -> Option<Self::Item> {
124+
if self.current_id.local_id.index() != 0 {
125+
self.current_id.local_id = ItemLocalId::new(0);
126+
if let Some(node) = self.map.find(self.current_id) {
127+
return Some((self.current_id, node));
128+
}
129+
}
130+
if self.current_id == CRATE_HIR_ID {
131+
return None;
132+
}
133+
loop {
134+
// There are nodes that do not have entries, so we need to skip them.
135+
let parent_id = self.map.def_key(self.current_id.owner).parent;
136+
137+
let parent_id = parent_id.map_or(CRATE_HIR_ID.owner, |local_def_index| {
138+
let def_id = LocalDefId { local_def_index };
139+
self.map.local_def_id_to_hir_id(def_id).owner
140+
});
141+
self.current_id = HirId::make_owner(parent_id);
142+
143+
// If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
144+
if let Some(node) = self.map.find(self.current_id) {
145+
return Some((self.current_id, node));
113146
}
114-
// If this `HirId` doesn't have an `Entry`, skip it and look for its `parent_id`.
115147
}
116148
}
117149
}
@@ -144,7 +176,7 @@ impl<'hir> Map<'hir> {
144176
bug!(
145177
"local_def_id: no entry for `{:?}`, which has a map of `{:?}`",
146178
hir_id,
147-
self.find_entry(hir_id)
179+
self.find(hir_id)
148180
)
149181
})
150182
}
@@ -251,27 +283,61 @@ impl<'hir> Map<'hir> {
251283
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", local_def_id))
252284
}
253285

254-
fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
286+
pub fn find_parent_node(&self, id: HirId) -> Option<HirId> {
255287
if id.local_id == ItemLocalId::from_u32(0) {
256-
let owner = self.tcx.hir_owner(id.owner);
257-
owner.map(|owner| Entry { parent: owner.parent, node: owner.node })
288+
let owner = self.tcx.hir_owner(id.owner)?;
289+
Some(owner.parent)
258290
} else {
259-
let owner = self.tcx.hir_owner_nodes(id.owner);
260-
owner.and_then(|owner| {
261-
let node = owner.nodes[id.local_id].as_ref();
262-
// FIXME(eddyb) use a single generic type instead of having both
263-
// `Entry` and `ParentedNode`, which are effectively the same.
264-
// Alternatively, rewrite code using `Entry` to use `ParentedNode`.
265-
node.map(|node| Entry {
266-
parent: HirId { owner: id.owner, local_id: node.parent },
267-
node: node.node,
268-
})
269-
})
291+
let owner = self.tcx.hir_owner_nodes(id.owner)?;
292+
let node = owner.nodes[id.local_id].as_ref()?;
293+
let hir_id = HirId { owner: id.owner, local_id: node.parent };
294+
Some(hir_id)
270295
}
271296
}
272297

273-
fn get_entry(&self, id: HirId) -> Entry<'hir> {
274-
self.find_entry(id).unwrap()
298+
pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
299+
self.find_parent_node(hir_id).unwrap()
300+
}
301+
302+
/// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
303+
pub fn find(&self, id: HirId) -> Option<Node<'hir>> {
304+
if id.local_id == ItemLocalId::from_u32(0) {
305+
let owner = self.tcx.hir_owner(id.owner)?;
306+
Some(owner.node)
307+
} else {
308+
let owner = self.tcx.hir_owner_nodes(id.owner)?;
309+
let node = owner.nodes[id.local_id].as_ref()?;
310+
Some(node.node)
311+
}
312+
}
313+
314+
/// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
315+
pub fn get(&self, id: HirId) -> Node<'hir> {
316+
self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
317+
}
318+
319+
pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
320+
id.as_local().and_then(|id| self.find(self.local_def_id_to_hir_id(id)))
321+
}
322+
323+
pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
324+
self.get_if_local(id).and_then(|node| match &node {
325+
Node::ImplItem(impl_item) => Some(&impl_item.generics),
326+
Node::TraitItem(trait_item) => Some(&trait_item.generics),
327+
Node::Item(Item {
328+
kind:
329+
ItemKind::Fn(_, generics, _)
330+
| ItemKind::TyAlias(_, generics)
331+
| ItemKind::Enum(_, generics)
332+
| ItemKind::Struct(_, generics)
333+
| ItemKind::Union(_, generics)
334+
| ItemKind::Trait(_, _, generics, ..)
335+
| ItemKind::TraitAlias(generics, _)
336+
| ItemKind::Impl(Impl { generics, .. }),
337+
..
338+
}) => Some(generics),
339+
_ => None,
340+
})
275341
}
276342

277343
pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
@@ -436,7 +502,7 @@ impl<'hir> Map<'hir> {
436502

437503
pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
438504
let hir_id = self.local_def_id_to_hir_id(module);
439-
match self.get_entry(hir_id).node {
505+
match self.get(hir_id) {
440506
Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id),
441507
Node::Crate(item) => (&item, item.inner, hir_id),
442508
node => panic!("not a module: {:?}", node),
@@ -475,60 +541,18 @@ impl<'hir> Map<'hir> {
475541
}
476542
}
477543

478-
/// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found.
479-
pub fn get(&self, id: HirId) -> Node<'hir> {
480-
self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id))
481-
}
482-
483-
pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
484-
id.as_local().and_then(|id| self.find(self.local_def_id_to_hir_id(id)))
485-
}
486-
487-
pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
488-
self.get_if_local(id).and_then(|node| match &node {
489-
Node::ImplItem(impl_item) => Some(&impl_item.generics),
490-
Node::TraitItem(trait_item) => Some(&trait_item.generics),
491-
Node::Item(Item {
492-
kind:
493-
ItemKind::Fn(_, generics, _)
494-
| ItemKind::TyAlias(_, generics)
495-
| ItemKind::Enum(_, generics)
496-
| ItemKind::Struct(_, generics)
497-
| ItemKind::Union(_, generics)
498-
| ItemKind::Trait(_, _, generics, ..)
499-
| ItemKind::TraitAlias(generics, _)
500-
| ItemKind::Impl(Impl { generics, .. }),
501-
..
502-
}) => Some(generics),
503-
_ => None,
504-
})
505-
}
506-
507-
/// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
508-
pub fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
509-
self.find_entry(hir_id).map(|entry| entry.node)
510-
}
511-
512-
/// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there
513-
/// is no parent. Note that the parent may be `CRATE_HIR_ID`, which is not itself
514-
/// present in the map, so passing the return value of `get_parent_node` to
515-
/// `get` may in fact panic.
516-
/// This function returns the immediate parent in the HIR, whereas `get_parent`
517-
/// returns the enclosing item. Note that this might not be the actual parent
518-
/// node in the HIR -- some kinds of nodes are not in the map and these will
519-
/// never appear as the parent node. Thus, you can always walk the parent nodes
520-
/// from a node to the root of the HIR (unless you get back the same ID here,
521-
/// which can happen if the ID is not in the map itself or is just weird).
522-
pub fn get_parent_node(&self, hir_id: HirId) -> HirId {
523-
self.get_entry(hir_id).parent
524-
}
525-
526544
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
527545
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
528546
pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
529547
ParentHirIterator { current_id, map: self }
530548
}
531549

550+
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
551+
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
552+
pub fn parent_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> {
553+
ParentOwnerIterator { current_id, map: self }
554+
}
555+
532556
/// Checks if the node is left-hand side of an assignment.
533557
pub fn is_lhs(&self, id: HirId) -> bool {
534558
match self.find(self.get_parent_node(id)) {
@@ -549,7 +573,7 @@ impl<'hir> Map<'hir> {
549573
/// Whether `hir_id` corresponds to a `mod` or a crate.
550574
pub fn is_hir_id_module(&self, hir_id: HirId) -> bool {
551575
matches!(
552-
self.get_entry(hir_id).node,
576+
self.get(hir_id),
553577
Node::Item(Item { kind: ItemKind::Mod(_), .. }) | Node::Crate(..)
554578
)
555579
}
@@ -579,8 +603,8 @@ impl<'hir> Map<'hir> {
579603
pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
580604
let mut iter = self.parent_iter(id).peekable();
581605
let mut ignore_tail = false;
582-
if let Some(entry) = self.find_entry(id) {
583-
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = entry.node {
606+
if let Some(node) = self.find(id) {
607+
if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = node {
584608
// When dealing with `return` statements, we don't care about climbing only tail
585609
// expressions.
586610
ignore_tail = true;
@@ -617,23 +641,23 @@ impl<'hir> Map<'hir> {
617641
/// in the HIR which is recorded by the map and is an item, either an item
618642
/// in a module, trait, or impl.
619643
pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
620-
for (hir_id, node) in self.parent_iter(hir_id) {
621-
match node {
622-
Node::Crate(_)
623-
| Node::Item(_)
624-
| Node::ForeignItem(_)
625-
| Node::TraitItem(_)
626-
| Node::ImplItem(_) => return hir_id,
627-
_ => {}
644+
for (hir_id, node) in self.parent_owner_iter(hir_id) {
645+
if let Node::Crate(_)
646+
| Node::Item(_)
647+
| Node::ForeignItem(_)
648+
| Node::TraitItem(_)
649+
| Node::ImplItem(_) = node
650+
{
651+
return hir_id;
628652
}
629653
}
630-
hir_id
654+
CRATE_HIR_ID
631655
}
632656

633657
/// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
634658
/// module parent is in this map.
635659
pub(super) fn get_module_parent_node(&self, hir_id: HirId) -> HirId {
636-
for (hir_id, node) in self.parent_iter(hir_id) {
660+
for (hir_id, node) in self.parent_owner_iter(hir_id) {
637661
if let Node::Item(&Item { kind: ItemKind::Mod(_), .. }) = node {
638662
return hir_id;
639663
}
@@ -707,12 +731,8 @@ impl<'hir> Map<'hir> {
707731

708732
pub fn get_foreign_abi(&self, hir_id: HirId) -> Abi {
709733
let parent = self.get_parent_item(hir_id);
710-
if let Some(entry) = self.find_entry(parent) {
711-
if let Entry {
712-
node: Node::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }),
713-
..
714-
} = entry
715-
{
734+
if let Some(node) = self.find(parent) {
735+
if let Node::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node {
716736
return *abi;
717737
}
718738
}
@@ -806,7 +826,7 @@ impl<'hir> Map<'hir> {
806826
}
807827

808828
pub fn opt_span(&self, hir_id: HirId) -> Option<Span> {
809-
let span = match self.find_entry(hir_id)?.node {
829+
let span = match self.find(hir_id)? {
810830
Node::Param(param) => param.span,
811831
Node::Item(item) => match &item.kind {
812832
ItemKind::Fn(sig, _, _) => sig.span,
@@ -855,7 +875,7 @@ impl<'hir> Map<'hir> {
855875
/// Like `hir.span()`, but includes the body of function items
856876
/// (instead of just the function header)
857877
pub fn span_with_body(&self, hir_id: HirId) -> Span {
858-
match self.find_entry(hir_id).map(|entry| entry.node) {
878+
match self.find(hir_id) {
859879
Some(Node::TraitItem(item)) => item.span,
860880
Some(Node::ImplItem(impl_item)) => impl_item.span,
861881
Some(Node::Item(item)) => item.span,

compiler/rustc_middle/src/hir/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ pub struct Owner<'tcx> {
3838

3939
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
4040
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
41-
let Owner { parent, node } = self;
41+
let Owner { node, parent } = self;
4242
hcx.while_hashing_hir_bodies(false, |hcx| {
4343
parent.hash_stable(hcx, hasher);
44-
node.hash_stable(hcx, hasher);
44+
node.hash_stable(hcx, hasher)
4545
});
4646
}
4747
}

0 commit comments

Comments
 (0)