Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hir: Make sure all HirIds have corresponding HIR Nodes #120206

Merged
merged 3 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(),
Expand All @@ -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)
}

Expand Down Expand Up @@ -88,7 +99,7 @@ impl<'a, 'hir> NodeCollector<'a, '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) {
Expand Down Expand Up @@ -254,6 +265,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}

fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) {
// FIXME: walk path segment with `path_segment.hir_id` parent.
self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment));
intravisit::walk_path_segment(self, path_segment);
}
Expand Down Expand Up @@ -348,4 +360,23 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {

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),
}
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} 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 };

Expand Down
121 changes: 57 additions & 64 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,66 +401,60 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
let hir_id = hir.parent_id(expr.hir_id);
if let Some(parent) = self.infcx.tcx.opt_hir_node(hir_id) {
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
&& let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
{
(def_id.as_local(), args, 1)
} else if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
{
(def_id.as_local(), args, 0)
} else {
(None, &[][..], 0)
let parent = self.infcx.tcx.hir_node(hir_id);
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
&& let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
{
(def_id.as_local(), args, 1)
} else if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
{
(def_id.as_local(), args, 0)
} else {
(None, &[][..], 0)
};
if let Some(def_id) = def_id
&& let node =
self.infcx.tcx.hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id))
&& let Some(fn_sig) = node.fn_sig()
&& let Some(ident) = node.ident()
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
&& let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
{
let mut span: MultiSpan = arg.span.into();
span.push_span_label(
arg.span,
"this parameter takes ownership of the value".to_string(),
);
let descr = match node.fn_kind() {
Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
Some(hir::intravisit::FnKind::Method(..)) => "method",
Some(hir::intravisit::FnKind::Closure) => "closure",
};
if let Some(def_id) = def_id
&& let Some(node) = self
.infcx
.tcx
.opt_hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id))
&& let Some(fn_sig) = node.fn_sig()
&& let Some(ident) = node.ident()
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
&& let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
{
let mut span: MultiSpan = arg.span.into();
span.push_span_label(
arg.span,
"this parameter takes ownership of the value".to_string(),
);
let descr = match node.fn_kind() {
Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
Some(hir::intravisit::FnKind::Method(..)) => "method",
Some(hir::intravisit::FnKind::Closure) => "closure",
};
span.push_span_label(ident.span, format!("in this {descr}"));
err.span_note(
span,
format!(
"consider changing this parameter type in {descr} `{ident}` to \
span.push_span_label(ident.span, format!("in this {descr}"));
err.span_note(
span,
format!(
"consider changing this parameter type in {descr} `{ident}` to \
borrow instead if owning the value isn't necessary",
),
);
}
let place = &self.move_data.move_paths[mpi].place;
let ty = place.ty(self.body, self.infcx.tcx).ty;
if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
&& let hir::ExprKind::Path(hir::QPath::LangItem(
LangItem::IntoIterIntoIter,
_,
)) = call_expr.kind
{
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
} else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } =
move_spans
{
// We already suggest cloning for these cases in `explain_captures`.
} else {
self.suggest_cloning(err, ty, expr, move_span);
}
),
);
}
let place = &self.move_data.move_paths[mpi].place;
let ty = place.ty(self.body, self.infcx.tcx).ty;
if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
&& let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
call_expr.kind
{
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
} else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans
{
// We already suggest cloning for these cases in `explain_captures`.
} else {
self.suggest_cloning(err, ty, expr, move_span);
}
}
if let Some(pat) = finder.pat {
Expand Down Expand Up @@ -1762,7 +1756,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn_decl: hir::FnDecl { inputs, .. },
..
}) = e.kind
&& let Some(hir::Node::Expr(body)) = self.tcx.opt_hir_node(body.hir_id)
&& let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id)
{
self.suggest_arg = "this: &Self".to_string();
if inputs.len() > 0 {
Expand Down Expand Up @@ -1828,11 +1822,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}

if let Some(hir::Node::ImplItem(hir::ImplItem {
if let hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(_fn_sig, body_id),
..
})) = self.infcx.tcx.opt_hir_node(self.mir_hir_id())
&& let Some(hir::Node::Expr(expr)) = self.infcx.tcx.opt_hir_node(body_id.hir_id)
}) = self.infcx.tcx.hir_node(self.mir_hir_id())
&& let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id)
{
let mut finder = ExpressionFinder {
capture_span: *capture_kind_span,
Expand Down Expand Up @@ -2400,8 +2394,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let proper_span = proper_span.source_callsite();
if let Some(scope) = self.body.source_scopes.get(source_info.scope)
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
&& let Some(node) = self.infcx.tcx.opt_hir_node(scope_data.lint_root)
&& let Some(id) = node.body_id()
&& let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id()
&& let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind
{
for stmt in block.stmts {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind
&& let [hir::PathSegment { ident, args: None, .. }] = p.segments
&& let hir::def::Res::Local(hir_id) = p.res
&& let Some(hir::Node::Pat(pat)) = tcx.opt_hir_node(hir_id)
&& let hir::Node::Pat(pat) = tcx.hir_node(hir_id)
{
err.span_label(pat.span, format!("binding `{ident}` declared here"));
}
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {

let upvar_hir_id = captured_place.get_root_variable();

if let Some(Node::Pat(pat)) = self.infcx.tcx.opt_hir_node(upvar_hir_id)
if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id)
&& let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, upvar_ident, _) =
pat.kind
{
Expand Down Expand Up @@ -688,15 +688,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
break;
}
f_in_trait_opt.and_then(|f_in_trait| {
match self.infcx.tcx.opt_hir_node(f_in_trait) {
Some(Node::TraitItem(hir::TraitItem {
match self.infcx.tcx.hir_node(f_in_trait) {
Node::TraitItem(hir::TraitItem {
kind:
hir::TraitItemKind::Fn(
hir::FnSig { decl: hir::FnDecl { inputs, .. }, .. },
_,
),
..
})) => {
}) => {
let hir::Ty { span, .. } = inputs[local.index() - 1];
Some(span)
}
Expand Down Expand Up @@ -759,10 +759,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
//
// `let &b = a;` -> `let &(mut b) = a;`
if let Some(hir_id) = hir_id
&& let Some(hir::Node::Local(hir::Local {
&& let hir::Node::Local(hir::Local {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
..
})) = self.infcx.tcx.opt_hir_node(hir_id)
}) = self.infcx.tcx.hir_node(hir_id)
&& let Ok(name) =
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
{
Expand Down Expand Up @@ -1206,7 +1206,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};

if let Some(hir_id) = hir_id
&& let Some(hir::Node::Local(local)) = self.infcx.tcx.opt_hir_node(hir_id)
&& let hir::Node::Local(local) = self.infcx.tcx.hir_node(hir_id)
{
let tables = self.infcx.tcx.typeck(def_id.as_local().unwrap());
if let Some(clone_trait) = self.infcx.tcx.lang_items().clone_trait()
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
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 {
Expand Down
Loading
Loading