diff options
| author | Adwin White <adwinw01@gmail.com> | 2024-09-12 11:32:39 +0800 |
|---|---|---|
| committer | Adwin White <adwinw01@gmail.com> | 2024-10-28 14:12:17 +0800 |
| commit | cb08e087221ba0263a338e959264520a8ed8080e (patch) | |
| tree | ded08bcb8de3507fb846e054b01fc863e8d4a05b /compiler/rustc_ast_lowering | |
| parent | df4ca44d3fbc9301ee17f30f4d474e6ae4b05252 (diff) | |
| download | rust-cb08e087221ba0263a338e959264520a8ed8080e.tar.gz rust-cb08e087221ba0263a338e959264520a8ed8080e.zip | |
Lower AST node id only once
Diffstat (limited to 'compiler/rustc_ast_lowering')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/block.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/delegation.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 113 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 65 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/pat.rs | 58 |
6 files changed, 161 insertions, 108 deletions
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 9d2b5690c23..8e02cbfd2ca 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -10,17 +10,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { b: &Block, targeted_by_break: bool, ) -> &'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_with_hir_id( + &mut self, + b: &Block, + hir_id: hir::HirId, + targeted_by_break: bool, + ) -> &'hir hir::Block<'hir> { + self.arena.alloc(self.lower_block_noalloc(hir_id, b, targeted_by_break)) } pub(super) fn lower_block_noalloc( &mut self, + hir_id: hir::HirId, b: &Block, targeted_by_break: bool, ) -> hir::Block<'hir> { let (stmts, expr) = self.lower_stmts(&b.stmts); 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 } } diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 3b85f1737bd..37eea707929 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -259,10 +259,11 @@ impl<'hir> LoweringContext<'_, 'hir> { self_param_id: pat_node_id, }; self_resolver.visit_block(block); + // Target expr needs to lower `self` path. + this.ident_to_local_id.insert(pat_node_id, param.pat.hir_id.local_id); this.lower_target_expr(&block) } else { - let pat_hir_id = this.lower_node_id(pat_node_id); - this.generate_arg(pat_hir_id, span) + this.generate_arg(param.pat.hir_id, span) }; args.push(arg); } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a1a16d0ca26..3df945a18e8 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -70,8 +70,8 @@ impl<'hir> LoweringContext<'_, 'hir> { _ => (), } - let hir_id = self.lower_node_id(e.id); - self.lower_attrs(hir_id, &e.attrs); + let expr_hir_id = self.lower_node_id(e.id); + self.lower_attrs(expr_hir_id, &e.attrs); let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), @@ -175,18 +175,25 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::If(cond, then, else_opt) => { self.lower_expr_if(cond, then, else_opt.as_deref()) } - ExprKind::While(cond, body, opt_label) => self.with_loop_scope(e.id, |this| { - let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); - this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label) - }), - ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| { - hir::ExprKind::Loop( - this.lower_block(body, false), - this.lower_label(*opt_label), - hir::LoopSource::Loop, - this.lower_span(*span), - ) - }), + ExprKind::While(cond, body, opt_label) => { + self.with_loop_scope(expr_hir_id, |this| { + let span = + this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); + 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( + this.lower_block(body, false), + opt_label, + hir::LoopSource::Loop, + this.lower_span(*span), + ) + }) + } ExprKind::TryBlock(body) => self.lower_expr_try_block(body), ExprKind::Match(expr, arms, kind) => hir::ExprKind::Match( self.lower_expr(expr), @@ -212,7 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder, *capture_clause, e.id, - hir_id, + expr_hir_id, *coroutine_kind, fn_decl, body, @@ -223,7 +230,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder, *capture_clause, e.id, - hir_id, + expr_hir_id, *constness, *movability, fn_decl, @@ -250,8 +257,14 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } ExprKind::Block(blk, opt_label) => { - let opt_label = self.lower_label(*opt_label); - hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) + // Different from loops, label of block resolves to block id rather than + // 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); + hir::ExprKind::Block( + self.lower_block_with_hir_id(blk, block_hir_id, opt_label.is_some()), + opt_label, + ) } ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span), ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp( @@ -354,7 +367,7 @@ impl<'hir> LoweringContext<'_, 'hir> { 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 +517,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let if_expr = self.expr(span, if_kind); let block = self.block_expr(self.arena.alloc(if_expr)); 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) } @@ -512,8 +524,9 @@ impl<'hir> LoweringContext<'_, 'hir> { /// `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. fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> { - self.with_catch_scope(body.id, |this| { - let mut block = this.lower_block_noalloc(body, true); + let body_hir_id = self.lower_node_id(body.id); + 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 let (try_span, tail_expr) = if let Some(expr) = block.expr.take() { @@ -869,7 +882,7 @@ impl<'hir> LoweringContext<'_, 'hir> { 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_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 = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); this.arena.alloc(this.expr(gen_future_span, expr_break)) @@ -1101,8 +1114,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::CoroutineSource::Closure, ); - let hir_id = this.lower_node_id(coroutine_kind.closure_id()); - this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); + this.maybe_forward_track_caller(body.span, closure_hir_id, expr.hir_id); (parameters, expr) }); @@ -1465,8 +1477,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?; + self.labelled_node_id_to_local_id.insert(dest_id, dest_hir_id.local_id); Some(Label { ident: self.lower_ident(label.ident) }) } @@ -1474,17 +1494,20 @@ impl<'hir> LoweringContext<'_, 'hir> { let target_id = match destination { Some((id, _)) => { if let Some(loop_id) = self.resolver.get_label_res(id) { - Ok(self.lower_node_id(loop_id)) + let local_id = self.labelled_node_id_to_local_id[&loop_id]; + let loop_hir_id = HirId { owner: self.current_hir_id_owner, local_id }; + Ok(loop_hir_id) } else { Err(hir::LoopIdError::UnresolvedLabel) } } - None => self - .loop_scope - .map(|id| Ok(self.lower_node_id(id))) - .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)), + None => { + self.loop_scope.map(|id| Ok(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 } } @@ -1499,14 +1522,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 result = f(self); self.catch_scope = old_scope; 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. let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; @@ -1658,9 +1681,13 @@ impl<'hir> LoweringContext<'_, 'hir> { 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 loop_hir_id = self.lower_node_id(e.id); + let label = self.lower_label(opt_label, e.id, loop_hir_id); + // `None => break` 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); self.arm(pat, break_expr) }; @@ -1668,7 +1695,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // Some(<pat>) => <body>, let some_arm = { 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)); self.arm(some_pat, body_expr) }; @@ -1722,12 +1750,11 @@ impl<'hir> LoweringContext<'_, 'hir> { // `[opt_ident]: loop { ... }` let kind = hir::ExprKind::Loop( loop_block, - self.lower_label(opt_label), + label, hir::LoopSource::ForLoop, self.lower_span(for_span.with_hi(head.span.hi())), ); - let loop_expr = - self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: for_span }); + let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span }); // `mut iter => { ... }` let iter_arm = self.arm(iter_pat, loop_expr); @@ -1867,8 +1894,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(residual_expr), unstable_span, ); - let ret_expr = if let Some(catch_node) = self.catch_scope { - let target_id = Ok(self.lower_node_id(catch_node)); + let ret_expr = if let Some(catch_id) = self.catch_scope { + let target_id = Ok(catch_id); self.arena.alloc(self.expr( try_span, hir::ExprKind::Break( @@ -1922,8 +1949,8 @@ impl<'hir> LoweringContext<'_, 'hir> { yeeted_span, ); - if let Some(catch_node) = self.catch_scope { - let target_id = Ok(self.lower_node_id(catch_node)); + if let Some(catch_id) = self.catch_scope { + let target_id = Ok(catch_id); hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr)) } else { hir::ExprKind::Ret(Some(from_yeet_expr)) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 97fa90d340e..9cad03ae403 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -154,7 +154,8 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { let mut ident = i.ident; let vis_span = self.lower_span(i.vis.span); - let hir_id = self.lower_node_id(i.id); + let hir_id = + hir::HirId { owner: self.current_hir_id_owner, local_id: hir::ItemLocalId::ZERO }; 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 item = hir::Item { @@ -604,7 +605,8 @@ impl<'hir> LoweringContext<'_, '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 { owner: self.current_hir_id_owner, local_id: hir::ItemLocalId::ZERO }; let owner_id = hir_id.expect_owner(); self.lower_attrs(hir_id, &i.attrs); let item = hir::ForeignItem { @@ -728,7 +730,8 @@ impl<'hir> LoweringContext<'_, '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 { owner: self.current_hir_id_owner, local_id: hir::ItemLocalId::ZERO }; self.lower_attrs(hir_id, &i.attrs); let trait_item_def_id = hir_id.expect_owner(); @@ -858,7 +861,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); - let hir_id = self.lower_node_id(i.id); + let hir_id = + hir::HirId { owner: self.current_hir_id_owner, local_id: hir::ItemLocalId::ZERO }; self.lower_attrs(hir_id, &i.attrs); let (generics, kind) = match &i.kind { @@ -1086,7 +1090,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); // 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); (parameters, expr) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 34b8137aea8..3067cb7ccf2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -40,8 +40,6 @@ #![warn(unreachable_pub)] // tidy-alphabetical-end -use std::collections::hash_map::Entry; - use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; use rustc_ast::{self as ast, *}; @@ -115,8 +113,8 @@ struct LoweringContext<'a, 'hir> { /// outside of an `async fn`. current_item: Option<Span>, - catch_scope: Option<NodeId>, - loop_scope: Option<NodeId>, + catch_scope: Option<HirId>, + loop_scope: Option<HirId>, is_in_loop_condition: bool, is_in_trait_impl: bool, is_in_dyn_type: bool, @@ -140,8 +138,10 @@ struct LoweringContext<'a, 'hir> { impl_trait_defs: Vec<hir::GenericParam<'hir>>, impl_trait_bounds: Vec<hir::WherePredicate<'hir>>, - /// NodeIds that are lowered inside the current HIR owner. - node_id_to_local_id: NodeMap<hir::ItemLocalId>, + /// NodeIds of labelled nodes that are lowered inside the current HIR owner. + labelled_node_id_to_local_id: NodeMap<hir::ItemLocalId>, + /// NodeIds of identifier that are lowered inside the current HIR owner. + ident_to_local_id: NodeMap<hir::ItemLocalId>, allow_try_trait: Lrc<[Symbol]>, allow_gen_future: Lrc<[Symbol]>, @@ -171,7 +171,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { current_hir_id_owner: hir::CRATE_OWNER_ID, current_def_id_parent: CRATE_DEF_ID, item_local_id_counter: hir::ItemLocalId::ZERO, - node_id_to_local_id: Default::default(), + labelled_node_id_to_local_id: Default::default(), + ident_to_local_id: Default::default(), trait_map: Default::default(), // Lowering state. @@ -588,7 +589,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let current_attrs = std::mem::take(&mut self.attrs); 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_labelled_node_id_to_local_id = + std::mem::take(&mut self.labelled_node_id_to_local_id); + let current_ident_to_local_id = std::mem::take(&mut self.ident_to_local_id); let current_trait_map = std::mem::take(&mut self.trait_map); let current_owner = std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id }); @@ -601,10 +604,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we want `f` to be able to refer to the `LocalDefId`s that the caller created. // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s. - // Always allocate the first `HirId` for the owner itself. - let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO); - debug_assert_eq!(_old, None); - let item = self.with_def_id_parent(def_id, f); debug_assert_eq!(def_id, item.def_id().def_id); // `f` should have consumed all the elements in these vectors when constructing `item`. @@ -614,7 +613,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.attrs = current_attrs; self.bodies = current_bodies; - self.node_id_to_local_id = current_node_ids; + self.labelled_node_id_to_local_id = current_labelled_node_id_to_local_id; + self.ident_to_local_id = current_ident_to_local_id; self.trait_map = current_trait_map; self.current_hir_id_owner = current_owner; self.item_local_id_counter = current_local_counter; @@ -680,39 +680,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map }) } - /// This method allocates a new `HirId` for the given `NodeId` and stores it in - /// the `LoweringContext`'s `NodeId => HirId` map. + /// This method allocates a new `HirId` for the given `NodeId`. /// 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 /// `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)] fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId { 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 local_id = self.item_local_id_counter; - 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) { - self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); - } + let owner = self.current_hir_id_owner; + 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 }; - if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) { - self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice()); - } + if let Some(def_id) = self.opt_local_def_id(ast_node_id) { + self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); + } - hir_id - } + if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) { + self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice()); } + + hir_id } /// Generate a new `HirId` without a backing `NodeId`. @@ -729,7 +720,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_res(&mut self, res: Res<NodeId>) -> Res { let res: Result<Res, ()> = res.apply_id(|id| { 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_to_local_id.get(&id).copied().ok_or(())?; Ok(HirId { owner, local_id }) }); trace!(?res); diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 760f84564f1..21829ea25a9 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -21,13 +21,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { ensure_sufficient_stack(|| { // loop here to avoid recursion + let pat_hir_id = self.lower_node_id(pattern.id); let node = loop { match &pattern.kind { PatKind::Wild => break hir::PatKind::Wild, PatKind::Never => break hir::PatKind::Never, PatKind::Ident(binding_mode, ident, sub) => { 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) => { 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; // Lowers `$bm $ident @ ..` to `$bm $ident @ _`. - let lower_rest_sub = |this: &mut Self, pat, &ann, &ident, sub| { - let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); - let node = this.lower_pat_ident(pat, ann, ident, lower_sub); - this.pat_with_node_id_of(pat, node) + let lower_rest_sub = |this: &mut Self, pat: &Pat, &ann, &ident, sub: &Pat| { + let sub_hir_id = this.lower_node_id(sub.id); + let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub, sub_hir_id)); + 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(); @@ -200,7 +209,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here. PatKind::Rest => { 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; } // Found a sub-slice pattern `$binding_mode $ident @ ..`. @@ -248,6 +258,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &Pat, annotation: BindingMode, ident: Ident, + hir_id: hir::HirId, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, ) -> hir::PatKind<'hir> { match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) { @@ -257,10 +268,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Some(Res::Local(id)) => id, _ => p.id, }; - + // All identifiers resolves to this canonical identifier share its `HirId`. + let binding_id = if canonical_id == p.id { + self.ident_to_local_id.insert(canonical_id, hir_id.local_id); + hir_id + } else { + hir::HirId { + owner: self.current_hir_id_owner, + local_id: self.ident_to_local_id[&canonical_id], + } + }; hir::PatKind::Binding( annotation, - self.lower_node_id(canonical_id), + binding_id, self.lower_ident(ident), lower_sub(self), ) @@ -280,18 +300,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn pat_wild_with_node_id_of(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> { - self.arena.alloc(self.pat_with_node_id_of(p, hir::PatKind::Wild)) + 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, hir_id)) } - /// Construct a `Pat` with the `HirId` of `p.id` lowered. - fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> { - hir::Pat { - hir_id: self.lower_node_id(p.id), - kind, - span: self.lower_span(p.span), - default_binding_modes: true, - } + /// 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_id: hir::HirId, + ) -> 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. |
