Rollup merge of #130259 - adwinwhite:lower-node-id-once, r=cjgillot

Lower AST node id only once

Fixes #96346.

I basically followed the given instructions except the inline part.

`lower_jump_destination` can't reuse local existing `HirId` due to unknown name resolution result so I created an additional mapping for labels.

r? ```@cjgillot```
This commit is contained in:
Jubilee 2024-10-28 10:18:48 -07:00 committed by GitHub
commit a24b3778d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 201 additions and 131 deletions

View File

@ -10,17 +10,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
b: &Block, b: &Block,
targeted_by_break: bool, targeted_by_break: bool,
) -> &'hir hir::Block<'hir> { ) -> &'hir hir::Block<'hir> {
self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break)) let hir_id = self.lower_node_id(b.id);
self.arena.alloc(self.lower_block_noalloc(hir_id, b, targeted_by_break))
} }
pub(super) fn lower_block_noalloc( pub(super) fn lower_block_noalloc(
&mut self, &mut self,
hir_id: hir::HirId,
b: &Block, b: &Block,
targeted_by_break: bool, targeted_by_break: bool,
) -> hir::Block<'hir> { ) -> hir::Block<'hir> {
let (stmts, expr) = self.lower_stmts(&b.stmts); let (stmts, expr) = self.lower_stmts(&b.stmts);
let rules = self.lower_block_check_mode(&b.rules); let rules = self.lower_block_check_mode(&b.rules);
let hir_id = self.lower_node_id(b.id);
hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break } hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }
} }

View File

@ -259,10 +259,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
self_param_id: pat_node_id, self_param_id: pat_node_id,
}; };
self_resolver.visit_block(block); self_resolver.visit_block(block);
// Target expr needs to lower `self` path.
this.ident_and_label_to_local_id.insert(pat_node_id, param.pat.hir_id.local_id);
this.lower_target_expr(&block) this.lower_target_expr(&block)
} else { } else {
let pat_hir_id = this.lower_node_id(pat_node_id); this.generate_arg(param.pat.hir_id, span)
this.generate_arg(pat_hir_id, span)
}; };
args.push(arg); args.push(arg);
} }

View File

@ -70,8 +70,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
_ => (), _ => (),
} }
let hir_id = self.lower_node_id(e.id); let expr_hir_id = self.lower_node_id(e.id);
self.lower_attrs(hir_id, &e.attrs); self.lower_attrs(expr_hir_id, &e.attrs);
let kind = match &e.kind { let kind = match &e.kind {
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
@ -175,18 +175,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::If(cond, then, else_opt) => { ExprKind::If(cond, then, else_opt) => {
self.lower_expr_if(cond, then, else_opt.as_deref()) self.lower_expr_if(cond, then, else_opt.as_deref())
} }
ExprKind::While(cond, body, opt_label) => self.with_loop_scope(e.id, |this| { ExprKind::While(cond, body, opt_label) => {
let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); self.with_loop_scope(expr_hir_id, |this| {
this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label) let span =
}), this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None);
ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| { let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);
this.lower_expr_while_in_loop_scope(span, cond, body, opt_label)
})
}
ExprKind::Loop(body, opt_label, span) => {
self.with_loop_scope(expr_hir_id, |this| {
let opt_label = this.lower_label(*opt_label, e.id, expr_hir_id);
hir::ExprKind::Loop( hir::ExprKind::Loop(
this.lower_block(body, false), this.lower_block(body, false),
this.lower_label(*opt_label), opt_label,
hir::LoopSource::Loop, hir::LoopSource::Loop,
this.lower_span(*span), this.lower_span(*span),
) )
}), })
}
ExprKind::TryBlock(body) => self.lower_expr_try_block(body), ExprKind::TryBlock(body) => self.lower_expr_try_block(body),
ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match( ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match(
self.lower_expr(expr), self.lower_expr(expr),
@ -212,7 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
binder, binder,
*capture_clause, *capture_clause,
e.id, e.id,
hir_id, expr_hir_id,
*coroutine_kind, *coroutine_kind,
fn_decl, fn_decl,
body, body,
@ -223,7 +230,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
binder, binder,
*capture_clause, *capture_clause,
e.id, e.id,
hir_id, expr_hir_id,
*constness, *constness,
*movability, *movability,
fn_decl, fn_decl,
@ -250,8 +257,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
) )
} }
ExprKind::Block(blk, opt_label) => { ExprKind::Block(blk, opt_label) => {
let opt_label = self.lower_label(*opt_label); // Different from loops, label of block resolves to block id rather than
hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) // expr node id.
let block_hir_id = self.lower_node_id(blk.id);
let opt_label = self.lower_label(*opt_label, blk.id, block_hir_id);
let hir_block = self.arena.alloc(self.lower_block_noalloc(
block_hir_id,
blk,
opt_label.is_some(),
));
hir::ExprKind::Block(hir_block, opt_label)
} }
ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span), ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span),
ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp( ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp(
@ -354,7 +369,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span), ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
}; };
hir::Expr { hir_id, kind, span: self.lower_span(e.span) } hir::Expr { hir_id: expr_hir_id, kind, span: self.lower_span(e.span) }
}) })
} }
@ -504,7 +519,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
let if_expr = self.expr(span, if_kind); let if_expr = self.expr(span, if_kind);
let block = self.block_expr(self.arena.alloc(if_expr)); let block = self.block_expr(self.arena.alloc(if_expr));
let span = self.lower_span(span.with_hi(cond.span.hi())); let span = self.lower_span(span.with_hi(cond.span.hi()));
let opt_label = self.lower_label(opt_label);
hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span) hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
} }
@ -512,8 +526,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }` /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`
/// and save the block id to use it as a break target for desugaring of the `?` operator. /// and save the block id to use it as a break target for desugaring of the `?` operator.
fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> { fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
self.with_catch_scope(body.id, |this| { let body_hir_id = self.lower_node_id(body.id);
let mut block = this.lower_block_noalloc(body, true); self.with_catch_scope(body_hir_id, |this| {
let mut block = this.lower_block_noalloc(body_hir_id, body, true);
// Final expression of the block (if present) or `()` with span at the end of block // Final expression of the block (if present) or `()` with span at the end of block
let (try_span, tail_expr) = if let Some(expr) = block.expr.take() { let (try_span, tail_expr) = if let Some(expr) = block.expr.take() {
@ -869,7 +884,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid); let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid);
let ready_field = self.single_pat_field(gen_future_span, x_pat); let ready_field = self.single_pat_field(gen_future_span, x_pat);
let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field); let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field);
let break_x = self.with_loop_scope(loop_node_id, move |this| { let break_x = self.with_loop_scope(loop_hir_id, move |this| {
let expr_break = let expr_break =
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
this.arena.alloc(this.expr(gen_future_span, expr_break)) this.arena.alloc(this.expr(gen_future_span, expr_break))
@ -1101,8 +1116,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::CoroutineSource::Closure, hir::CoroutineSource::Closure,
); );
let hir_id = this.lower_node_id(coroutine_kind.closure_id()); this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id);
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
(parameters, expr) (parameters, expr)
}); });
@ -1465,8 +1479,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
) )
} }
fn lower_label(&self, opt_label: Option<Label>) -> Option<Label> { // Record labelled expr's HirId so that we can retrieve it in `lower_jump_destination` without
// lowering node id again.
fn lower_label(
&mut self,
opt_label: Option<Label>,
dest_id: NodeId,
dest_hir_id: hir::HirId,
) -> Option<Label> {
let label = opt_label?; let label = opt_label?;
self.ident_and_label_to_local_id.insert(dest_id, dest_hir_id.local_id);
Some(Label { ident: self.lower_ident(label.ident) }) Some(Label { ident: self.lower_ident(label.ident) })
} }
@ -1474,17 +1496,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
let target_id = match destination { let target_id = match destination {
Some((id, _)) => { Some((id, _)) => {
if let Some(loop_id) = self.resolver.get_label_res(id) { if let Some(loop_id) = self.resolver.get_label_res(id) {
Ok(self.lower_node_id(loop_id)) let local_id = self.ident_and_label_to_local_id[&loop_id];
let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id };
Ok(loop_hir_id)
} else { } else {
Err(hir::LoopIdError::UnresolvedLabel) Err(hir::LoopIdError::UnresolvedLabel)
} }
} }
None => self None => {
.loop_scope self.loop_scope.map(|id| Ok(id)).unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
.map(|id| Ok(self.lower_node_id(id))) }
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
}; };
let label = self.lower_label(destination.map(|(_, label)| label)); let label = destination
.map(|(_, label)| label)
.map(|label| Label { ident: self.lower_ident(label.ident) });
hir::Destination { label, target_id } hir::Destination { label, target_id }
} }
@ -1499,14 +1524,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
} }
fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { fn with_catch_scope<T>(&mut self, catch_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {
let old_scope = self.catch_scope.replace(catch_id); let old_scope = self.catch_scope.replace(catch_id);
let result = f(self); let result = f(self);
self.catch_scope = old_scope; self.catch_scope = old_scope;
result result
} }
fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { fn with_loop_scope<T>(&mut self, loop_id: hir::HirId, f: impl FnOnce(&mut Self) -> T) -> T {
// We're no longer in the base loop's condition; we're in another loop. // We're no longer in the base loop's condition; we're in another loop.
let was_in_loop_condition = self.is_in_loop_condition; let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false; self.is_in_loop_condition = false;
@ -1658,9 +1683,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None); let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None); let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None);
let loop_hir_id = self.lower_node_id(e.id);
let label = self.lower_label(opt_label, e.id, loop_hir_id);
// `None => break` // `None => break`
let none_arm = { let none_arm = {
let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span)); let break_expr =
self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span));
let pat = self.pat_none(for_span); let pat = self.pat_none(for_span);
self.arm(pat, break_expr) self.arm(pat, break_expr)
}; };
@ -1668,7 +1697,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Some(<pat>) => <body>, // Some(<pat>) => <body>,
let some_arm = { let some_arm = {
let some_pat = self.pat_some(pat_span, pat); let some_pat = self.pat_some(pat_span, pat);
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); let body_block =
self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false));
let body_expr = self.arena.alloc(self.expr_block(body_block)); let body_expr = self.arena.alloc(self.expr_block(body_block));
self.arm(some_pat, body_expr) self.arm(some_pat, body_expr)
}; };
@ -1722,12 +1752,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `[opt_ident]: loop { ... }` // `[opt_ident]: loop { ... }`
let kind = hir::ExprKind::Loop( let kind = hir::ExprKind::Loop(
loop_block, loop_block,
self.lower_label(opt_label), label,
hir::LoopSource::ForLoop, hir::LoopSource::ForLoop,
self.lower_span(for_span.with_hi(head.span.hi())), self.lower_span(for_span.with_hi(head.span.hi())),
); );
let loop_expr = let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span });
self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: for_span });
// `mut iter => { ... }` // `mut iter => { ... }`
let iter_arm = self.arm(iter_pat, loop_expr); let iter_arm = self.arm(iter_pat, loop_expr);
@ -1867,8 +1896,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.arena.alloc(residual_expr), self.arena.alloc(residual_expr),
unstable_span, unstable_span,
); );
let ret_expr = if let Some(catch_node) = self.catch_scope { let ret_expr = if let Some(catch_id) = self.catch_scope {
let target_id = Ok(self.lower_node_id(catch_node)); let target_id = Ok(catch_id);
self.arena.alloc(self.expr( self.arena.alloc(self.expr(
try_span, try_span,
hir::ExprKind::Break( hir::ExprKind::Break(
@ -1922,8 +1951,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
yeeted_span, yeeted_span,
); );
if let Some(catch_node) = self.catch_scope { if let Some(catch_id) = self.catch_scope {
let target_id = Ok(self.lower_node_id(catch_node)); let target_id = Ok(catch_id);
hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr)) hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
} else { } else {
hir::ExprKind::Ret(Some(from_yeet_expr)) hir::ExprKind::Ret(Some(from_yeet_expr))

View File

@ -154,7 +154,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
let mut ident = i.ident; let mut ident = i.ident;
let vis_span = self.lower_span(i.vis.span); let vis_span = self.lower_span(i.vis.span);
let hir_id = self.lower_node_id(i.id); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let attrs = self.lower_attrs(hir_id, &i.attrs); let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind); let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
let item = hir::Item { let item = hir::Item {
@ -604,7 +604,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
let owner_id = hir_id.expect_owner(); let owner_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs); self.lower_attrs(hir_id, &i.attrs);
let item = hir::ForeignItem { let item = hir::ForeignItem {
@ -728,7 +728,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let hir_id = self.lower_node_id(i.id); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
self.lower_attrs(hir_id, &i.attrs); self.lower_attrs(hir_id, &i.attrs);
let trait_item_def_id = hir_id.expect_owner(); let trait_item_def_id = hir_id.expect_owner();
@ -858,7 +858,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Since `default impl` is not yet implemented, this is always true in impls. // Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true; let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = self.lower_node_id(i.id); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
self.lower_attrs(hir_id, &i.attrs); self.lower_attrs(hir_id, &i.attrs);
let (generics, kind) = match &i.kind { let (generics, kind) = match &i.kind {
@ -1086,7 +1086,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
); );
// FIXME(async_fn_track_caller): Can this be moved above? // FIXME(async_fn_track_caller): Can this be moved above?
let hir_id = this.lower_node_id(coroutine_kind.closure_id()); let hir_id = expr.hir_id;
this.maybe_forward_track_caller(body.span, fn_id, hir_id); this.maybe_forward_track_caller(body.span, fn_id, hir_id);
(parameters, expr) (parameters, expr)

View File

@ -40,8 +40,6 @@
#![warn(unreachable_pub)] #![warn(unreachable_pub)]
// tidy-alphabetical-end // tidy-alphabetical-end
use std::collections::hash_map::Entry;
use rustc_ast::node_id::NodeMap; use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::{self as ast, *}; use rustc_ast::{self as ast, *};
@ -115,8 +113,8 @@ struct LoweringContext<'a, 'hir> {
/// outside of an `async fn`. /// outside of an `async fn`.
current_item: Option<Span>, current_item: Option<Span>,
catch_scope: Option<NodeId>, catch_scope: Option<HirId>,
loop_scope: Option<NodeId>, loop_scope: Option<HirId>,
is_in_loop_condition: bool, is_in_loop_condition: bool,
is_in_trait_impl: bool, is_in_trait_impl: bool,
is_in_dyn_type: bool, is_in_dyn_type: bool,
@ -140,7 +138,10 @@ struct LoweringContext<'a, 'hir> {
impl_trait_defs: Vec<hir::GenericParam<'hir>>, impl_trait_defs: Vec<hir::GenericParam<'hir>>,
impl_trait_bounds: Vec<hir::WherePredicate<'hir>>, impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,
/// NodeIds that are lowered inside the current HIR owner. /// NodeIds of pattern identifiers and labelled nodes that are lowered inside the current HIR owner.
ident_and_label_to_local_id: NodeMap<hir::ItemLocalId>,
/// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering check.
#[cfg(debug_assertions)]
node_id_to_local_id: NodeMap<hir::ItemLocalId>, node_id_to_local_id: NodeMap<hir::ItemLocalId>,
allow_try_trait: Lrc<[Symbol]>, allow_try_trait: Lrc<[Symbol]>,
@ -171,6 +172,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
current_hir_id_owner: hir::CRATE_OWNER_ID, current_hir_id_owner: hir::CRATE_OWNER_ID,
current_def_id_parent: CRATE_DEF_ID, current_def_id_parent: CRATE_DEF_ID,
item_local_id_counter: hir::ItemLocalId::ZERO, item_local_id_counter: hir::ItemLocalId::ZERO,
ident_and_label_to_local_id: Default::default(),
#[cfg(debug_assertions)]
node_id_to_local_id: Default::default(), node_id_to_local_id: Default::default(),
trait_map: Default::default(), trait_map: Default::default(),
@ -588,7 +591,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let current_attrs = std::mem::take(&mut self.attrs); let current_attrs = std::mem::take(&mut self.attrs);
let current_bodies = std::mem::take(&mut self.bodies); let current_bodies = std::mem::take(&mut self.bodies);
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id); let current_ident_and_label_to_local_id =
std::mem::take(&mut self.ident_and_label_to_local_id);
#[cfg(debug_assertions)]
let current_node_id_to_local_id = std::mem::take(&mut self.node_id_to_local_id);
let current_trait_map = std::mem::take(&mut self.trait_map); let current_trait_map = std::mem::take(&mut self.trait_map);
let current_owner = let current_owner =
std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id }); std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
@ -602,8 +609,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s. // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s.
// Always allocate the first `HirId` for the owner itself. // Always allocate the first `HirId` for the owner itself.
#[cfg(debug_assertions)]
{
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO); let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
debug_assert_eq!(_old, None); debug_assert_eq!(_old, None);
}
let item = self.with_def_id_parent(def_id, f); let item = self.with_def_id_parent(def_id, f);
debug_assert_eq!(def_id, item.def_id().def_id); debug_assert_eq!(def_id, item.def_id().def_id);
@ -614,7 +624,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.attrs = current_attrs; self.attrs = current_attrs;
self.bodies = current_bodies; self.bodies = current_bodies;
self.node_id_to_local_id = current_node_ids; self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;
#[cfg(debug_assertions)]
{
self.node_id_to_local_id = current_node_id_to_local_id;
}
self.trait_map = current_trait_map; self.trait_map = current_trait_map;
self.current_hir_id_owner = current_owner; self.current_hir_id_owner = current_owner;
self.item_local_id_counter = current_local_counter; self.item_local_id_counter = current_local_counter;
@ -680,28 +695,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map }) self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
} }
/// This method allocates a new `HirId` for the given `NodeId` and stores it in /// This method allocates a new `HirId` for the given `NodeId`.
/// the `LoweringContext`'s `NodeId => HirId` map.
/// Take care not to call this method if the resulting `HirId` is then not /// Take care not to call this method if the resulting `HirId` is then not
/// actually used in the HIR, as that would trigger an assertion in the /// actually used in the HIR, as that would trigger an assertion in the
/// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
/// properly. Calling the method twice with the same `NodeId` is fine though. /// properly. Calling the method twice with the same `NodeId` is also forbidden.
#[instrument(level = "debug", skip(self), ret)] #[instrument(level = "debug", skip(self), ret)]
fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId { fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {
assert_ne!(ast_node_id, DUMMY_NODE_ID); assert_ne!(ast_node_id, DUMMY_NODE_ID);
match self.node_id_to_local_id.entry(ast_node_id) {
Entry::Occupied(o) => HirId { owner: self.current_hir_id_owner, local_id: *o.get() },
Entry::Vacant(v) => {
// Generate a new `HirId`.
let owner = self.current_hir_id_owner; let owner = self.current_hir_id_owner;
let local_id = self.item_local_id_counter; let local_id = self.item_local_id_counter;
assert_ne!(local_id, hir::ItemLocalId::ZERO);
self.item_local_id_counter.increment_by(1);
let hir_id = HirId { owner, local_id }; let hir_id = HirId { owner, local_id };
v.insert(local_id);
self.item_local_id_counter.increment_by(1);
assert_ne!(local_id, hir::ItemLocalId::ZERO);
if let Some(def_id) = self.opt_local_def_id(ast_node_id) { if let Some(def_id) = self.opt_local_def_id(ast_node_id) {
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
} }
@ -710,10 +718,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice()); self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice());
} }
// Check whether the same `NodeId` is lowered more than once.
#[cfg(debug_assertions)]
{
let old = self.node_id_to_local_id.insert(ast_node_id, local_id);
assert_eq!(old, None);
}
hir_id hir_id
} }
}
}
/// Generate a new `HirId` without a backing `NodeId`. /// Generate a new `HirId` without a backing `NodeId`.
#[instrument(level = "debug", skip(self), ret)] #[instrument(level = "debug", skip(self), ret)]
@ -729,7 +742,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_res(&mut self, res: Res<NodeId>) -> Res { fn lower_res(&mut self, res: Res<NodeId>) -> Res {
let res: Result<Res, ()> = res.apply_id(|id| { let res: Result<Res, ()> = res.apply_id(|id| {
let owner = self.current_hir_id_owner; let owner = self.current_hir_id_owner;
let local_id = self.node_id_to_local_id.get(&id).copied().ok_or(())?; let local_id = self.ident_and_label_to_local_id.get(&id).copied().ok_or(())?;
Ok(HirId { owner, local_id }) Ok(HirId { owner, local_id })
}); });
trace!(?res); trace!(?res);

View File

@ -21,13 +21,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> {
ensure_sufficient_stack(|| { ensure_sufficient_stack(|| {
// loop here to avoid recursion // loop here to avoid recursion
let pat_hir_id = self.lower_node_id(pattern.id);
let node = loop { let node = loop {
match &pattern.kind { match &pattern.kind {
PatKind::Wild => break hir::PatKind::Wild, PatKind::Wild => break hir::PatKind::Wild,
PatKind::Never => break hir::PatKind::Never, PatKind::Never => break hir::PatKind::Never,
PatKind::Ident(binding_mode, ident, sub) => { PatKind::Ident(binding_mode, ident, sub) => {
let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s)); let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s));
break self.lower_pat_ident(pattern, *binding_mode, *ident, lower_sub); break self.lower_pat_ident(
pattern,
*binding_mode,
*ident,
pat_hir_id,
lower_sub,
);
} }
PatKind::Lit(e) => { PatKind::Lit(e) => {
break hir::PatKind::Lit(self.lower_expr_within_pat(e, false)); break hir::PatKind::Lit(self.lower_expr_within_pat(e, false));
@ -119,7 +126,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
}; };
self.pat_with_node_id_of(pattern, node) self.pat_with_node_id_of(pattern, node, pat_hir_id)
}) })
} }
@ -187,10 +194,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let mut prev_rest_span = None; let mut prev_rest_span = None;
// Lowers `$bm $ident @ ..` to `$bm $ident @ _`. // Lowers `$bm $ident @ ..` to `$bm $ident @ _`.
let lower_rest_sub = |this: &mut Self, pat, &ann, &ident, sub| { let lower_rest_sub = |this: &mut Self, pat: &Pat, &ann, &ident, sub: &Pat| {
let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); let sub_hir_id = this.lower_node_id(sub.id);
let node = this.lower_pat_ident(pat, ann, ident, lower_sub); let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub, sub_hir_id));
this.pat_with_node_id_of(pat, node) let pat_hir_id = this.lower_node_id(pat.id);
let node = this.lower_pat_ident(pat, ann, ident, pat_hir_id, lower_sub);
this.pat_with_node_id_of(pat, node, pat_hir_id)
}; };
let mut iter = pats.iter(); let mut iter = pats.iter();
@ -200,7 +209,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here. // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here.
PatKind::Rest => { PatKind::Rest => {
prev_rest_span = Some(pat.span); prev_rest_span = Some(pat.span);
slice = Some(self.pat_wild_with_node_id_of(pat)); let hir_id = self.lower_node_id(pat.id);
slice = Some(self.pat_wild_with_node_id_of(pat, hir_id));
break; break;
} }
// Found a sub-slice pattern `$binding_mode $ident @ ..`. // Found a sub-slice pattern `$binding_mode $ident @ ..`.
@ -248,19 +258,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
p: &Pat, p: &Pat,
annotation: BindingMode, annotation: BindingMode,
ident: Ident, ident: Ident,
hir_id: hir::HirId,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> { ) -> hir::PatKind<'hir> {
match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) { match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) {
// `None` can occur in body-less function signatures // `None` can occur in body-less function signatures
res @ (None | Some(Res::Local(_))) => { res @ (None | Some(Res::Local(_))) => {
let canonical_id = match res { let binding_id = match res {
Some(Res::Local(id)) => id, Some(Res::Local(id)) => {
_ => p.id, // In `Or` patterns like `VariantA(s) | VariantB(s, _)`, multiple identifier patterns
// will be resolved to the same `Res::Local`. Thus they just share a single
// `HirId`.
if id == p.id {
self.ident_and_label_to_local_id.insert(id, hir_id.local_id);
hir_id
} else {
hir::HirId {
owner: self.current_hir_id_owner,
local_id: self.ident_and_label_to_local_id[&id],
}
}
}
_ => {
self.ident_and_label_to_local_id.insert(p.id, hir_id.local_id);
hir_id
}
}; };
hir::PatKind::Binding( hir::PatKind::Binding(
annotation, annotation,
self.lower_node_id(canonical_id), binding_id,
self.lower_ident(ident), self.lower_ident(ident),
lower_sub(self), lower_sub(self),
) )
@ -280,18 +306,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> { fn pat_wild_with_node_id_of(&mut self, p: &Pat, hir_id: hir::HirId) -> &'hir hir::Pat<'hir> {
self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild)) self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild, hir_id))
} }
/// Construct a `Pat` with the `HirId` of `p.id` lowered. /// Construct a `Pat` with the `HirId` of `p.id` already lowered.
fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> { fn pat_with_node_id_of(
hir::Pat { &mut self,
hir_id: self.lower_node_id(p.id), p: &Pat,
kind, kind: hir::PatKind<'hir>,
span: self.lower_span(p.span), hir_id: hir::HirId,
default_binding_modes: true, ) -> hir::Pat<'hir> {
} hir::Pat { hir_id, kind, span: self.lower_span(p.span), default_binding_modes: true }
} }
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern. /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.

View File

@ -41,7 +41,7 @@ body:
Block { Block {
targeted_by_break: false targeted_by_break: false
span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
region_scope: Node(25) region_scope: Node(3)
safety_mode: Safe safety_mode: Safe
stmts: [] stmts: []
expr: expr:
@ -51,8 +51,8 @@ body:
span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(3) region_scope: Node(4)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).3)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4))
value: value:
Expr { Expr {
ty: bool ty: bool
@ -67,8 +67,8 @@ body:
span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(4) region_scope: Node(5)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).5))
value: value:
Expr { Expr {
ty: Foo ty: Foo
@ -123,16 +123,16 @@ body:
body: body:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: Some(Node(12)) temp_lifetime: Some(Node(13))
span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(13) region_scope: Node(14)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).14))
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: Some(Node(12)) temp_lifetime: Some(Node(13))
span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
kind: kind:
Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false) Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false)
@ -140,8 +140,8 @@ body:
} }
} }
} }
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).12)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13))
scope: Node(12) scope: Node(13)
span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0)
} }
Arm { Arm {
@ -175,16 +175,16 @@ body:
body: body:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: Some(Node(18)) temp_lifetime: Some(Node(19))
span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(19) region_scope: Node(20)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).20))
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: Some(Node(18)) temp_lifetime: Some(Node(19))
span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
kind: kind:
Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false) Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false)
@ -192,8 +192,8 @@ body:
} }
} }
} }
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).18)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19))
scope: Node(18) scope: Node(19)
span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0)
} }
Arm { Arm {
@ -219,16 +219,16 @@ body:
body: body:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: Some(Node(23)) temp_lifetime: Some(Node(24))
span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(24) region_scope: Node(25)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).25))
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: Some(Node(23)) temp_lifetime: Some(Node(24))
span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
kind: kind:
Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false) Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false)
@ -236,8 +236,8 @@ body:
} }
} }
} }
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).23)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24))
scope: Node(23) scope: Node(24)
span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0)
} }
] ]