hir: Make sure all HirId
s have corresponding HIR Node
s
This commit is contained in:
parent
d4f6f9ee6a
commit
363b098245
@ -15,7 +15,7 @@ struct NodeCollector<'a, 'hir> {
|
||||
bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>,
|
||||
|
||||
/// Outputs
|
||||
nodes: IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>,
|
||||
nodes: IndexVec<ItemLocalId, ParentedNode<'hir>>,
|
||||
parenting: LocalDefIdMap<ItemLocalId>,
|
||||
|
||||
/// The parent of this node
|
||||
@ -29,16 +29,19 @@ pub(super) fn index_hir<'hir>(
|
||||
tcx: TyCtxt<'hir>,
|
||||
item: hir::OwnerNode<'hir>,
|
||||
bodies: &SortedMap<ItemLocalId, &'hir Body<'hir>>,
|
||||
) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, LocalDefIdMap<ItemLocalId>) {
|
||||
let mut nodes = IndexVec::new();
|
||||
num_nodes: usize,
|
||||
) -> (IndexVec<ItemLocalId, ParentedNode<'hir>>, LocalDefIdMap<ItemLocalId>) {
|
||||
let zero_id = ItemLocalId::new(0);
|
||||
let err_node = ParentedNode { parent: zero_id, node: Node::Err(item.span()) };
|
||||
let mut nodes = IndexVec::from_elem_n(err_node, num_nodes);
|
||||
// This node's parent should never be accessed: the owner's parent is computed by the
|
||||
// hir_owner_parent query. Make it invalid (= ItemLocalId::MAX) to force an ICE whenever it is
|
||||
// used.
|
||||
nodes.push(Some(ParentedNode { parent: ItemLocalId::INVALID, node: item.into() }));
|
||||
nodes[zero_id] = ParentedNode { parent: ItemLocalId::INVALID, node: item.into() };
|
||||
let mut collector = NodeCollector {
|
||||
tcx,
|
||||
owner: item.def_id(),
|
||||
parent_node: ItemLocalId::new(0),
|
||||
parent_node: zero_id,
|
||||
nodes,
|
||||
bodies,
|
||||
parenting: Default::default(),
|
||||
@ -54,6 +57,14 @@ pub(super) fn index_hir<'hir>(
|
||||
OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item),
|
||||
};
|
||||
|
||||
for (local_id, node) in collector.nodes.iter_enumerated() {
|
||||
if let Node::Err(span) = node.node {
|
||||
let hir_id = HirId { owner: item.def_id(), local_id };
|
||||
let msg = format!("ID {hir_id} not encountered when visiting item HIR");
|
||||
tcx.dcx().span_delayed_bug(*span, msg);
|
||||
}
|
||||
}
|
||||
|
||||
(collector.nodes, collector.parenting)
|
||||
}
|
||||
|
||||
@ -88,7 +99,7 @@ fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) {
|
||||
}
|
||||
}
|
||||
|
||||
self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node });
|
||||
self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node };
|
||||
}
|
||||
|
||||
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) {
|
||||
@ -348,4 +359,23 @@ fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) {
|
||||
|
||||
self.visit_nested_foreign_item(id);
|
||||
}
|
||||
|
||||
fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) {
|
||||
match predicate {
|
||||
WherePredicate::BoundPredicate(pred) => {
|
||||
self.insert(pred.span, pred.hir_id, Node::WhereBoundPredicate(pred));
|
||||
self.with_parent(pred.hir_id, |this| {
|
||||
intravisit::walk_where_predicate(this, predicate)
|
||||
})
|
||||
}
|
||||
_ => intravisit::walk_where_predicate(self, predicate),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_array_length(&mut self, len: &'hir ArrayLen) {
|
||||
match len {
|
||||
ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)),
|
||||
ArrayLen::Body(..) => intravisit::walk_array_len(self, len),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +675,8 @@ fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInf
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies);
|
||||
let num_nodes = self.item_local_id_counter.as_usize();
|
||||
let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
|
||||
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
|
||||
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
|
||||
|
||||
|
@ -216,7 +216,8 @@ fn suggest_static_lifetime_for_gat_from_hrtb(
|
||||
if let Some(id) = placeholder.bound.kind.get_id()
|
||||
&& let Some(placeholder_id) = id.as_local()
|
||||
&& let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id)
|
||||
&& let Some(generics_impl) = hir.get_parent(gat_hir_id).generics()
|
||||
&& let Some(generics_impl) =
|
||||
hir.get_parent(hir.parent_id(gat_hir_id)).generics()
|
||||
{
|
||||
Some((gat_hir_id, generics_impl))
|
||||
} else {
|
||||
|
@ -835,7 +835,7 @@ pub struct OwnerNodes<'tcx> {
|
||||
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
|
||||
// hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally
|
||||
// used.
|
||||
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
|
||||
pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>,
|
||||
/// Content of local bodies.
|
||||
pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
|
||||
}
|
||||
@ -843,9 +843,8 @@ pub struct OwnerNodes<'tcx> {
|
||||
impl<'tcx> OwnerNodes<'tcx> {
|
||||
pub fn node(&self) -> OwnerNode<'tcx> {
|
||||
use rustc_index::Idx;
|
||||
let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
|
||||
let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
|
||||
node
|
||||
// Indexing must ensure it is an OwnerNode.
|
||||
self.nodes[ItemLocalId::new(0)].node.as_owner().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -860,9 +859,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
.nodes
|
||||
.iter_enumerated()
|
||||
.map(|(id, parented_node)| {
|
||||
let parented_node = parented_node.as_ref().map(|node| node.parent);
|
||||
|
||||
debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})"))
|
||||
debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent))
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
@ -3351,13 +3348,15 @@ pub fn ident(&self) -> Option<Ident> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
// Span by reference to pass to `Node::Err`.
|
||||
#[allow(rustc::pass_by_value)]
|
||||
pub fn span(&self) -> &'hir Span {
|
||||
match self {
|
||||
OwnerNode::Item(Item { span, .. })
|
||||
| OwnerNode::ForeignItem(ForeignItem { span, .. })
|
||||
| OwnerNode::ImplItem(ImplItem { span, .. })
|
||||
| OwnerNode::TraitItem(TraitItem { span, .. }) => *span,
|
||||
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span,
|
||||
| OwnerNode::TraitItem(TraitItem { span, .. }) => span,
|
||||
OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span,
|
||||
}
|
||||
}
|
||||
|
||||
@ -3486,17 +3485,18 @@ pub enum Node<'hir> {
|
||||
Arm(&'hir Arm<'hir>),
|
||||
Block(&'hir Block<'hir>),
|
||||
Local(&'hir Local<'hir>),
|
||||
|
||||
/// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
|
||||
/// with synthesized constructors.
|
||||
Ctor(&'hir VariantData<'hir>),
|
||||
|
||||
Lifetime(&'hir Lifetime),
|
||||
GenericParam(&'hir GenericParam<'hir>),
|
||||
|
||||
Crate(&'hir Mod<'hir>),
|
||||
|
||||
Infer(&'hir InferArg),
|
||||
WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>),
|
||||
ArrayLenInfer(&'hir InferArg),
|
||||
// Span by reference to minimize `Node`'s size
|
||||
#[allow(rustc::pass_by_value)]
|
||||
Err(&'hir Span),
|
||||
}
|
||||
|
||||
impl<'hir> Node<'hir> {
|
||||
@ -3541,7 +3541,10 @@ pub fn ident(&self) -> Option<Ident> {
|
||||
| Node::Crate(..)
|
||||
| Node::Ty(..)
|
||||
| Node::TraitRef(..)
|
||||
| Node::Infer(..) => None,
|
||||
| Node::Infer(..)
|
||||
| Node::WhereBoundPredicate(..)
|
||||
| Node::ArrayLenInfer(..)
|
||||
| Node::Err(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,6 +509,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
|
||||
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
|
||||
},
|
||||
|
||||
Node::ArrayLenInfer(_) => tcx.types.usize,
|
||||
|
||||
x => {
|
||||
bug!("unexpected sort of node in type_of(): {:?}", x);
|
||||
}
|
||||
|
@ -117,6 +117,13 @@ fn print_node(&mut self, node: Node<'_>) {
|
||||
Node::Ctor(..) => panic!("cannot print isolated Ctor"),
|
||||
Node::Local(a) => self.print_local_decl(a),
|
||||
Node::Crate(..) => panic!("cannot print Crate"),
|
||||
Node::WhereBoundPredicate(pred) => {
|
||||
self.print_formal_generic_params(pred.bound_generic_params);
|
||||
self.print_type(pred.bounded_ty);
|
||||
self.print_bounds(":", pred.bounds);
|
||||
}
|
||||
Node::ArrayLenInfer(_) => self.word("_"),
|
||||
Node::Err(_) => self.word("/*ERROR*/"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1055,7 +1055,7 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
|
||||
if self.can_coerce(found, ty) {
|
||||
if let Some(node) = self.tcx.opt_hir_node(fn_id)
|
||||
&& let Some(owner_node) = node.as_owner()
|
||||
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
|
||||
&& let Some(span) = expr.span.find_ancestor_inside(*owner_node.span())
|
||||
{
|
||||
err.multipart_suggestion(
|
||||
"you might have meant to return this value",
|
||||
|
@ -1388,13 +1388,7 @@ fn encode_def_ids(&mut self) {
|
||||
if should_encode_fn_sig(def_kind) {
|
||||
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
|
||||
}
|
||||
// FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]`
|
||||
// do not have corresponding HIR nodes, so some queries usually making sense for
|
||||
// anonymous constants will not work on them and panic. It's not clear whether it
|
||||
// can cause any observable issues or not.
|
||||
let anon_const_without_hir = def_kind == DefKind::AnonConst
|
||||
&& tcx.opt_hir_node(tcx.local_def_id_to_hir_id(local_id)).is_none();
|
||||
if should_encode_generics(def_kind) && !anon_const_without_hir {
|
||||
if should_encode_generics(def_kind) {
|
||||
let g = tcx.generics_of(def_id);
|
||||
record!(self.tables.generics_of[def_id] <- g);
|
||||
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
|
||||
@ -1408,7 +1402,7 @@ fn encode_def_ids(&mut self) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir {
|
||||
if should_encode_type(tcx, local_id, def_kind) {
|
||||
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
|
||||
}
|
||||
if should_encode_constness(def_kind) {
|
||||
|
@ -159,9 +159,7 @@ pub fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> {
|
||||
|
||||
/// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
|
||||
pub fn opt_hir_node(self, id: HirId) -> Option<Node<'tcx>> {
|
||||
let owner = self.hir_owner_nodes(id.owner);
|
||||
let node = owner.nodes[id.local_id].as_ref()?;
|
||||
Some(node.node)
|
||||
Some(self.hir_owner_nodes(id.owner).nodes[id.local_id].node)
|
||||
}
|
||||
|
||||
/// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found.
|
||||
@ -233,7 +231,7 @@ pub fn opt_parent_id(self, id: HirId) -> Option<HirId> {
|
||||
Some(self.tcx.hir_owner_parent(id.owner))
|
||||
} else {
|
||||
let owner = self.tcx.hir_owner_nodes(id.owner);
|
||||
let node = owner.nodes[id.local_id].as_ref()?;
|
||||
let node = &owner.nodes[id.local_id];
|
||||
let hir_id = HirId { owner: id.owner, local_id: node.parent };
|
||||
// HIR indexing should have checked that.
|
||||
debug_assert_ne!(id.local_id, node.parent);
|
||||
@ -994,6 +992,9 @@ pub fn span_with_body(self, hir_id: HirId) -> Span {
|
||||
Node::Infer(i) => i.span,
|
||||
Node::Local(local) => local.span,
|
||||
Node::Crate(item) => item.spans.inner_span,
|
||||
Node::WhereBoundPredicate(pred) => pred.span,
|
||||
Node::ArrayLenInfer(inf) => inf.span,
|
||||
Node::Err(span) => *span,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1255,6 +1256,9 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
||||
format!("{id} (generic_param {})", path_str(param.def_id))
|
||||
}
|
||||
Some(Node::Crate(..)) => String::from("(root_crate)"),
|
||||
Some(Node::WhereBoundPredicate(_)) => node_str("where bound predicate"),
|
||||
Some(Node::ArrayLenInfer(_)) => node_str("array len infer"),
|
||||
Some(Node::Err(_)) => node_str("error"),
|
||||
None => format!("{id} (unknown node)"),
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ fn visit_id(&mut self, hir_id: HirId) {
|
||||
cx.tcx.opt_hir_node(hir_id)
|
||||
} else {
|
||||
let owner = cx.tcx.hir_owner_nodes(hir_id.owner);
|
||||
owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node)
|
||||
owner.nodes.get(hir_id.local_id).copied().map(|p| p.node)
|
||||
};
|
||||
let Some(node) = node else {
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user