Skip to content

Commit 08bf213

Browse files
committed
hir: Make sure all HirIds have corresponding HIR Nodes
1 parent d9d89fd commit 08bf213

File tree

12 files changed

+90
-45
lines changed

12 files changed

+90
-45
lines changed

compiler/rustc_ast_lowering/src/index.rs

+37-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub(super) fn index_hir<'hir>(
2929
tcx: TyCtxt<'hir>,
3030
item: hir::OwnerNode<'hir>,
3131
bodies: &SortedMap<ItemLocalId, &'hir Body<'hir>>,
32-
) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, LocalDefIdMap<ItemLocalId>) {
32+
) -> (IndexVec<ItemLocalId, ParentedNode<'hir>>, LocalDefIdMap<ItemLocalId>) {
3333
let mut nodes = IndexVec::new();
3434
// This node's parent should never be accessed: the owner's parent is computed by the
3535
// hir_owner_parent query. Make it invalid (= ItemLocalId::MAX) to force an ICE whenever it is
@@ -54,7 +54,18 @@ pub(super) fn index_hir<'hir>(
5454
OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item),
5555
};
5656

57-
(collector.nodes, collector.parenting)
57+
let err = || {
58+
let span = item.span();
59+
tcx.dcx().span_delayed_bug(*span, "ID not encountered when visiting item HIR");
60+
ParentedNode { parent: ItemLocalId::new(0), node: Node::Err(span) }
61+
};
62+
let nodes = collector
63+
.nodes
64+
.into_iter()
65+
.map(|parented_node| parented_node.unwrap_or_else(err))
66+
.collect();
67+
68+
(nodes, collector.parenting)
5869
}
5970

6071
impl<'a, 'hir> NodeCollector<'a, 'hir> {
@@ -348,4 +359,28 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
348359

349360
self.visit_nested_foreign_item(id);
350361
}
362+
363+
fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) {
364+
match predicate {
365+
WherePredicate::BoundPredicate(pred) => {
366+
self.insert(pred.span, pred.hir_id, Node::WhereBoundPredicate(pred));
367+
self.with_parent(pred.hir_id, |this| {
368+
intravisit::walk_where_predicate(this, predicate)
369+
})
370+
}
371+
_ => intravisit::walk_where_predicate(self, predicate),
372+
}
373+
}
374+
375+
fn visit_let_expr(&mut self, lex: &'hir Let<'hir>) {
376+
self.insert(lex.span, lex.hir_id, Node::Let(lex));
377+
self.with_parent(lex.hir_id, |this| intravisit::walk_let_expr(this, lex))
378+
}
379+
380+
fn visit_array_length(&mut self, len: &'hir ArrayLen) {
381+
match len {
382+
ArrayLen::Infer(hir_id, span) => self.insert(*span, *hir_id, Node::ArrayLenInfer(span)),
383+
ArrayLen::Body(..) => intravisit::walk_array_len(self, len),
384+
}
385+
}
351386
}

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
216216
if let Some(id) = placeholder.bound.kind.get_id()
217217
&& let Some(placeholder_id) = id.as_local()
218218
&& let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id)
219-
&& let Some(generics_impl) = hir.get_parent(gat_hir_id).generics()
219+
&& let Some(generics_impl) =
220+
hir.get_parent(hir.parent_id(gat_hir_id)).generics()
220221
{
221222
Some((gat_hir_id, generics_impl))
222223
} else {

compiler/rustc_hir/src/hir.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -835,17 +835,16 @@ pub struct OwnerNodes<'tcx> {
835835
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
836836
// hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally
837837
// used.
838-
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
838+
pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>,
839839
/// Content of local bodies.
840840
pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
841841
}
842842

843843
impl<'tcx> OwnerNodes<'tcx> {
844844
pub fn node(&self) -> OwnerNode<'tcx> {
845845
use rustc_index::Idx;
846-
let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
847-
let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
848-
node
846+
// Indexing must ensure it is an OwnerNode.
847+
self.nodes[ItemLocalId::new(0)].node.as_owner().unwrap()
849848
}
850849
}
851850

@@ -860,9 +859,7 @@ impl fmt::Debug for OwnerNodes<'_> {
860859
.nodes
861860
.iter_enumerated()
862861
.map(|(id, parented_node)| {
863-
let parented_node = parented_node.as_ref().map(|node| node.parent);
864-
865-
debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})"))
862+
debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent))
866863
})
867864
.collect::<Vec<_>>(),
868865
)
@@ -3356,13 +3353,14 @@ impl<'hir> OwnerNode<'hir> {
33563353
}
33573354
}
33583355

3359-
pub fn span(&self) -> Span {
3356+
#[allow(rustc::pass_by_value)]
3357+
pub fn span(&self) -> &'hir Span {
33603358
match self {
33613359
OwnerNode::Item(Item { span, .. })
33623360
| OwnerNode::ForeignItem(ForeignItem { span, .. })
33633361
| OwnerNode::ImplItem(ImplItem { span, .. })
3364-
| OwnerNode::TraitItem(TraitItem { span, .. }) => *span,
3365-
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span,
3362+
| OwnerNode::TraitItem(TraitItem { span, .. }) => span,
3363+
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span,
33663364
}
33673365
}
33683366

@@ -3491,17 +3489,20 @@ pub enum Node<'hir> {
34913489
Arm(&'hir Arm<'hir>),
34923490
Block(&'hir Block<'hir>),
34933491
Local(&'hir Local<'hir>),
3494-
34953492
/// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
34963493
/// with synthesized constructors.
34973494
Ctor(&'hir VariantData<'hir>),
3498-
34993495
Lifetime(&'hir Lifetime),
35003496
GenericParam(&'hir GenericParam<'hir>),
3501-
35023497
Crate(&'hir Mod<'hir>),
3503-
35043498
Infer(&'hir InferArg),
3499+
WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>),
3500+
Let(&'hir Let<'hir>),
3501+
// Span by reference to minimize `Node`'s size
3502+
#[allow(rustc::pass_by_value)]
3503+
ArrayLenInfer(&'hir Span),
3504+
#[allow(rustc::pass_by_value)]
3505+
Err(&'hir Span),
35053506
}
35063507

35073508
impl<'hir> Node<'hir> {
@@ -3546,7 +3547,11 @@ impl<'hir> Node<'hir> {
35463547
| Node::Crate(..)
35473548
| Node::Ty(..)
35483549
| Node::TraitRef(..)
3549-
| Node::Infer(..) => None,
3550+
| Node::Infer(..)
3551+
| Node::WhereBoundPredicate(..)
3552+
| Node::Let(..)
3553+
| Node::ArrayLenInfer(..)
3554+
| Node::Err(..) => None,
35503555
}
35513556
}
35523557

compiler/rustc_hir_analysis/src/collect/type_of.rs

+2
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
509509
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
510510
},
511511

512+
Node::ArrayLenInfer(_) => tcx.types.usize,
513+
512514
x => {
513515
bug!("unexpected sort of node in type_of(): {:?}", x);
514516
}

compiler/rustc_hir_pretty/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ impl<'a> State<'a> {
117117
Node::Ctor(..) => panic!("cannot print isolated Ctor"),
118118
Node::Local(a) => self.print_local_decl(a),
119119
Node::Crate(..) => panic!("cannot print Crate"),
120+
Node::WhereBoundPredicate(pred) => {
121+
self.print_formal_generic_params(pred.bound_generic_params);
122+
self.print_type(pred.bounded_ty);
123+
self.print_bounds(":", pred.bounds);
124+
}
125+
Node::Let(lex) => self.print_let(lex.pat, lex.ty, lex.init),
126+
Node::ArrayLenInfer(_) => self.word("_"),
127+
Node::Err(_) => self.word("/*ERROR*/"),
120128
}
121129
}
122130
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10521052
if self.can_coerce(found, ty) {
10531053
if let Some(node) = self.tcx.opt_hir_node(fn_id)
10541054
&& let Some(owner_node) = node.as_owner()
1055-
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
1055+
&& let Some(span) = expr.span.find_ancestor_inside(*owner_node.span())
10561056
{
10571057
err.multipart_suggestion(
10581058
"you might have meant to return this value",

compiler/rustc_metadata/src/rmeta/encoder.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -1388,13 +1388,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13881388
if should_encode_fn_sig(def_kind) {
13891389
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
13901390
}
1391-
// FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]`
1392-
// do not have corresponding HIR nodes, so some queries usually making sense for
1393-
// anonymous constants will not work on them and panic. It's not clear whether it
1394-
// can cause any observable issues or not.
1395-
let anon_const_without_hir = def_kind == DefKind::AnonConst
1396-
&& tcx.opt_hir_node(tcx.local_def_id_to_hir_id(local_id)).is_none();
1397-
if should_encode_generics(def_kind) && !anon_const_without_hir {
1391+
if should_encode_generics(def_kind) {
13981392
let g = tcx.generics_of(def_id);
13991393
record!(self.tables.generics_of[def_id] <- g);
14001394
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
@@ -1408,7 +1402,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14081402
}
14091403
}
14101404
}
1411-
if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir {
1405+
if should_encode_type(tcx, local_id, def_kind) {
14121406
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
14131407
}
14141408
if should_encode_constness(def_kind) {

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

+11-4
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,8 @@ impl<'tcx> TyCtxt<'tcx> {
140140

141141
/// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
142142
pub fn opt_hir_node(self, id: HirId) -> Option<Node<'tcx>> {
143-
let owner = self.hir_owner_nodes(id.owner).as_owner()?;
144-
let node = owner.nodes[id.local_id].as_ref()?;
145-
Some(node.node)
143+
let owner_nodes = self.hir_owner_nodes(id.owner).unwrap();
144+
Some(owner_nodes.nodes[id.local_id].node)
146145
}
147146

148147
/// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
@@ -214,7 +213,7 @@ impl<'hir> Map<'hir> {
214213
Some(self.tcx.hir_owner_parent(id.owner))
215214
} else {
216215
let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?;
217-
let node = owner.nodes[id.local_id].as_ref()?;
216+
let node = &owner.nodes[id.local_id];
218217
let hir_id = HirId { owner: id.owner, local_id: node.parent };
219218
// HIR indexing should have checked that.
220219
debug_assert_ne!(id.local_id, node.parent);
@@ -989,6 +988,10 @@ impl<'hir> Map<'hir> {
989988
Node::Infer(i) => i.span,
990989
Node::Local(local) => local.span,
991990
Node::Crate(item) => item.spans.inner_span,
991+
Node::WhereBoundPredicate(pred) => pred.span,
992+
Node::Let(lex) => lex.span,
993+
Node::ArrayLenInfer(span) => *span,
994+
Node::Err(span) => *span,
992995
}
993996
}
994997

@@ -1250,6 +1253,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
12501253
format!("{id} (generic_param {})", path_str(param.def_id))
12511254
}
12521255
Some(Node::Crate(..)) => String::from("(root_crate)"),
1256+
Some(Node::WhereBoundPredicate(_)) => node_str("where bound predicate"),
1257+
Some(Node::Let(_)) => node_str("let expr"),
1258+
Some(Node::ArrayLenInfer(_)) => node_str("array len infer"),
1259+
Some(Node::Err(_)) => node_str("error"),
12531260
None => format!("{id} (unknown node)"),
12541261
}
12551262
}

src/tools/clippy/clippy_lints/src/min_ident_chars.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> {
9696
let Some(owner) = cx.tcx.hir_owner_nodes(hir_id.owner).as_owner() else {
9797
return;
9898
};
99-
owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node)
99+
owner.nodes.get(hir_id.local_id).copied().map(|p| p.node)
100100
};
101101
let Some(node) = node else {
102102
return;

src/tools/clippy/tests/ui/manual_map_option_2.fixed

+4-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ fn main() {
4242

4343
// Lint. `s` is captured by reference, so no lifetime issues.
4444
let s = Some(String::new());
45-
let _ = s.as_ref().map(|x| { if let Some(ref s) = s { (x.clone(), s) } else { panic!() } });
45+
let _ = match &s {
46+
Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
47+
None => None,
48+
};
4649

4750
// Issue #7820
4851
unsafe fn f(x: u32) -> u32 {

src/tools/clippy/tests/ui/manual_map_option_2.stderr

+1-11
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,6 @@ LL + (x, y.0)
2121
LL ~ });
2222
|
2323

24-
error: manual implementation of `Option::map`
25-
--> $DIR/manual_map_option_2.rs:48:13
26-
|
27-
LL | let _ = match &s {
28-
| _____________^
29-
LL | | Some(x) => Some({ if let Some(ref s) = s { (x.clone(), s) } else { panic!() } }),
30-
LL | | None => None,
31-
LL | | };
32-
| |_____^ help: try: `s.as_ref().map(|x| { if let Some(ref s) = s { (x.clone(), s) } else { panic!() } })`
33-
3424
error: manual implementation of `Option::map`
3525
--> $DIR/manual_map_option_2.rs:58:17
3626
|
@@ -61,5 +51,5 @@ LL | | None => None,
6151
LL | | };
6252
| |_____^ help: try: `Some(0).map(|x| unsafe { f(x) })`
6353

64-
error: aborting due to 5 previous errors
54+
error: aborting due to 4 previous errors
6555

src/tools/clippy/tests/ui/shadow.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ note: previous binding is here
244244
LL | let _ = |[x]: [u32; 1]| {
245245
| ^
246246

247-
error: `y` is shadowed
247+
error: `y` shadows a previous, unrelated binding
248248
--> $DIR/shadow.rs:76:17
249249
|
250250
LL | if let Some(y) = y {}

0 commit comments

Comments
 (0)