about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2023-12-15 15:16:24 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2023-12-18 16:54:58 +0000
commit68d684cbff361cbddf866919bd1b49a89301e242 (patch)
tree8c0d67b0f4ed96e882daeaa5531612110d5becbd
parente004adb5561b724ac18f5b24584648ca4e42b6ad (diff)
downloadrust-68d684cbff361cbddf866919bd1b49a89301e242.tar.gz
rust-68d684cbff361cbddf866919bd1b49a89301e242.zip
Pass THIR ExprIds in MIR building
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs20
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs26
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs57
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs97
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs97
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs46
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs69
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs17
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs4
10 files changed, 209 insertions, 235 deletions
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 8cad6976c0d..4046122b6fe 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -15,7 +15,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) -> BlockAnd<()> {
         let Block { region_scope, span, ref stmts, expr, targeted_by_break, safety_mode } =
             self.thir[ast_block];
-        let expr = expr.map(|expr| &self.thir[expr]);
         self.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
             if targeted_by_break {
                 this.in_breakable_scope(None, destination, span, |this| {
@@ -49,7 +48,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         mut block: BasicBlock,
         span: Span,
         stmts: &[StmtId],
-        expr: Option<&Expr<'tcx>>,
+        expr: Option<ExprId>,
         safety_mode: BlockSafety,
         region_scope: Scope,
     ) -> BlockAnd<()> {
@@ -90,7 +89,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let si = (*scope, source_info);
                     unpack!(
                         block = this.in_scope(si, LintLevel::Inherited, |this| {
-                            this.stmt_expr(block, &this.thir[*expr], Some(*scope))
+                            this.stmt_expr(block, *expr, Some(*scope))
                         })
                     );
                 }
@@ -205,8 +204,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let visibility_scope =
                         Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
 
-                    let init = &this.thir[*initializer];
-                    let initializer_span = init.span;
+                    let initializer_span = this.thir[*initializer].span;
                     let scope = (*init_scope, source_info);
                     let failure = unpack!(
                         block = this.in_scope(scope, *lint_level, |this| {
@@ -232,7 +230,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             );
                             this.ast_let_else(
                                 block,
-                                init,
+                                *initializer,
                                 initializer_span,
                                 *else_block,
                                 &last_remainder_scope,
@@ -276,9 +274,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
 
                     // Evaluate the initializer, if present.
-                    if let Some(init) = initializer {
-                        let init = &this.thir[*init];
-                        let initializer_span = init.span;
+                    if let Some(init) = *initializer {
+                        let initializer_span = this.thir[init].span;
                         let scope = (*init_scope, source_info);
 
                         unpack!(
@@ -334,13 +331,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // of the block, which is stored into `destination`.
         let tcx = this.tcx;
         let destination_ty = destination.ty(&this.local_decls, tcx).ty;
-        if let Some(expr) = expr {
+        if let Some(expr_id) = expr {
+            let expr = &this.thir[expr_id];
             let tail_result_is_ignored =
                 destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
             this.block_context
                 .push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });
 
-            unpack!(block = this.expr_into_dest(destination, block, expr));
+            unpack!(block = this.expr_into_dest(destination, block, expr_id));
             let popped = this.block_context.pop();
 
             assert!(popped.is_some_and(|bf| bf.is_tail_expr()));
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 744111edb84..076ee7f85ff 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -17,10 +17,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn as_local_operand(
         &mut self,
         block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<Operand<'tcx>> {
         let local_scope = self.local_scope();
-        self.as_operand(block, Some(local_scope), expr, LocalInfo::Boring, NeedsTemporary::Maybe)
+        self.as_operand(block, Some(local_scope), expr_id, LocalInfo::Boring, NeedsTemporary::Maybe)
     }
 
     /// Returns an operand suitable for use until the end of the current scope expression and
@@ -76,7 +76,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn as_local_call_operand(
         &mut self,
         block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr: ExprId,
     ) -> BlockAnd<Operand<'tcx>> {
         let local_scope = self.local_scope();
         self.as_call_operand(block, Some(local_scope), expr)
@@ -101,17 +101,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         mut block: BasicBlock,
         scope: Option<region::Scope>,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
         local_info: LocalInfo<'tcx>,
         needs_temporary: NeedsTemporary,
     ) -> BlockAnd<Operand<'tcx>> {
         let this = self;
 
+        let expr = &this.thir[expr_id];
         if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
             let source_info = this.source_info(expr.span);
             let region_scope = (region_scope, source_info);
             return this.in_scope(region_scope, lint_level, |this| {
-                this.as_operand(block, scope, &this.thir[value], local_info, needs_temporary)
+                this.as_operand(block, scope, value, local_info, needs_temporary)
             });
         }
 
@@ -126,7 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(Operand::Constant(Box::new(constant)))
             }
             Category::Constant | Category::Place | Category::Rvalue(..) => {
-                let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
+                let operand = unpack!(block = this.as_temp(block, scope, expr_id, Mutability::Mut));
                 // Overwrite temp local info if we have something more interesting to record.
                 if !matches!(local_info, LocalInfo::Boring) {
                     let decl_info =
@@ -144,16 +145,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         mut block: BasicBlock,
         scope: Option<region::Scope>,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<Operand<'tcx>> {
-        debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
         let this = self;
+        let expr = &this.thir[expr_id];
+        debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
 
         if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
             let source_info = this.source_info(expr.span);
             let region_scope = (region_scope, source_info);
             return this.in_scope(region_scope, lint_level, |this| {
-                this.as_call_operand(block, scope, &this.thir[value])
+                this.as_call_operand(block, scope, value)
             });
         }
 
@@ -171,9 +173,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // type, and that value is coming from the deref of a box.
                 if let ExprKind::Deref { arg } = expr.kind {
                     // Generate let tmp0 = arg0
-                    let operand = unpack!(
-                        block = this.as_temp(block, scope, &this.thir[arg], Mutability::Mut)
-                    );
+                    let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut));
 
                     // Return the operand *tmp0 to be used as the call argument
                     let place = Place {
@@ -186,6 +186,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::Maybe)
+        this.as_operand(block, scope, expr_id, LocalInfo::Boring, NeedsTemporary::Maybe)
     }
 }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 43e8348903e..f12e25db6fc 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -354,9 +354,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn as_place(
         &mut self,
         mut block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<Place<'tcx>> {
-        let place_builder = unpack!(block = self.as_place_builder(block, expr));
+        let place_builder = unpack!(block = self.as_place_builder(block, expr_id));
         block.and(place_builder.to_place(self))
     }
 
@@ -365,9 +365,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn as_place_builder(
         &mut self,
         block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
-        self.expr_as_place(block, expr, Mutability::Mut, None)
+        self.expr_as_place(block, expr_id, Mutability::Mut, None)
     }
 
     /// Compile `expr`, yielding a place that we can move from etc.
@@ -378,9 +378,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn as_read_only_place(
         &mut self,
         mut block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<Place<'tcx>> {
-        let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
+        let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr_id));
         block.and(place_builder.to_place(self))
     }
 
@@ -393,18 +393,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn as_read_only_place_builder(
         &mut self,
         block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
-        self.expr_as_place(block, expr, Mutability::Not, None)
+        self.expr_as_place(block, expr_id, Mutability::Not, None)
     }
 
     fn expr_as_place(
         &mut self,
         mut block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
         mutability: Mutability,
         fake_borrow_temps: Option<&mut Vec<Local>>,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
+        let expr = &self.thir[expr_id];
         debug!("expr_as_place(block={:?}, expr={:?}, mutability={:?})", block, expr, mutability);
 
         let this = self;
@@ -413,14 +414,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match expr.kind {
             ExprKind::Scope { region_scope, lint_level, value } => {
                 this.in_scope((region_scope, source_info), lint_level, |this| {
-                    this.expr_as_place(block, &this.thir[value], mutability, fake_borrow_temps)
+                    this.expr_as_place(block, value, mutability, fake_borrow_temps)
                 })
             }
             ExprKind::Field { lhs, variant_index, name } => {
-                let lhs = &this.thir[lhs];
+                let lhs_expr = &this.thir[lhs];
                 let mut place_builder =
                     unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,));
-                if let ty::Adt(adt_def, _) = lhs.ty.kind() {
+                if let ty::Adt(adt_def, _) = lhs_expr.ty.kind() {
                     if adt_def.is_enum() {
                         place_builder = place_builder.downcast(*adt_def, variant_index);
                     }
@@ -428,16 +429,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(place_builder.field(name, expr.ty))
             }
             ExprKind::Deref { arg } => {
-                let place_builder = unpack!(
-                    block =
-                        this.expr_as_place(block, &this.thir[arg], mutability, fake_borrow_temps,)
-                );
+                let place_builder =
+                    unpack!(block = this.expr_as_place(block, arg, mutability, fake_borrow_temps,));
                 block.and(place_builder.deref())
             }
             ExprKind::Index { lhs, index } => this.lower_index_expression(
                 block,
-                &this.thir[lhs],
-                &this.thir[index],
+                lhs,
+                index,
                 mutability,
                 fake_borrow_temps,
                 expr.temp_lifetime,
@@ -461,12 +460,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             ExprKind::PlaceTypeAscription { source, ref user_ty } => {
                 let place_builder = unpack!(
-                    block = this.expr_as_place(
-                        block,
-                        &this.thir[source],
-                        mutability,
-                        fake_borrow_temps,
-                    )
+                    block = this.expr_as_place(block, source, mutability, fake_borrow_temps,)
                 );
                 if let Some(user_ty) = user_ty {
                     let annotation_index =
@@ -494,9 +488,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(place_builder)
             }
             ExprKind::ValueTypeAscription { source, ref user_ty } => {
-                let source = &this.thir[source];
-                let temp =
-                    unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
+                let source_expr = &this.thir[source];
+                let temp = unpack!(
+                    block = this.as_temp(block, source_expr.temp_lifetime, source, mutability)
+                );
                 if let Some(user_ty) = user_ty {
                     let annotation_index =
                         this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
@@ -562,7 +557,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // these are not places, so we need to make a temporary.
                 debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));
                 let temp =
-                    unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
+                    unpack!(block = this.as_temp(block, expr.temp_lifetime, expr_id, mutability));
                 block.and(PlaceBuilder::from(temp))
             }
         }
@@ -591,8 +586,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn lower_index_expression(
         &mut self,
         mut block: BasicBlock,
-        base: &Expr<'tcx>,
-        index: &Expr<'tcx>,
+        base: ExprId,
+        index: ExprId,
         mutability: Mutability,
         fake_borrow_temps: Option<&mut Vec<Local>>,
         temp_lifetime: Option<region::Scope>,
@@ -609,7 +604,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Making this a *fresh* temporary means we do not have to worry about
         // the index changing later: Nothing will ever change this temporary.
         // The "retagging" transformation (for Stacked Borrows) relies on this.
-        let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not,));
+        let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not));
 
         block = self.bounds_check(block, &base_place, idx, expr_span, source_info);
 
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index a5f6bb12ee4..04dcc6854c7 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -27,10 +27,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn as_local_rvalue(
         &mut self,
         block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<Rvalue<'tcx>> {
         let local_scope = self.local_scope();
-        self.as_rvalue(block, Some(local_scope), expr)
+        self.as_rvalue(block, Some(local_scope), expr_id)
     }
 
     /// Compile `expr`, yielding an rvalue.
@@ -38,11 +38,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         mut block: BasicBlock,
         scope: Option<region::Scope>,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<Rvalue<'tcx>> {
+        let this = self;
+        let expr = &this.thir[expr_id];
         debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
 
-        let this = self;
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
 
@@ -50,9 +51,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)),
             ExprKind::Scope { region_scope, lint_level, value } => {
                 let region_scope = (region_scope, source_info);
-                this.in_scope(region_scope, lint_level, |this| {
-                    this.as_rvalue(block, scope, &this.thir[value])
-                })
+                this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value))
             }
             ExprKind::Repeat { value, count } => {
                 if Some(0) == count.try_eval_target_usize(this.tcx, this.param_env) {
@@ -62,7 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         block = this.as_operand(
                             block,
                             scope,
-                            &this.thir[value],
+                            value,
                             LocalInfo::Boring,
                             NeedsTemporary::No
                         )
@@ -75,31 +74,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     block = this.as_operand(
                         block,
                         scope,
-                        &this.thir[lhs],
+                        lhs,
                         LocalInfo::Boring,
                         NeedsTemporary::Maybe
                     )
                 );
                 let rhs = unpack!(
-                    block = this.as_operand(
-                        block,
-                        scope,
-                        &this.thir[rhs],
-                        LocalInfo::Boring,
-                        NeedsTemporary::No
-                    )
+                    block =
+                        this.as_operand(block, scope, rhs, LocalInfo::Boring, NeedsTemporary::No)
                 );
                 this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
             }
             ExprKind::Unary { op, arg } => {
                 let arg = unpack!(
-                    block = this.as_operand(
-                        block,
-                        scope,
-                        &this.thir[arg],
-                        LocalInfo::Boring,
-                        NeedsTemporary::No
-                    )
+                    block =
+                        this.as_operand(block, scope, arg, LocalInfo::Boring, NeedsTemporary::No)
                 );
                 // Check for -MIN on signed integers
                 if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
@@ -126,7 +115,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(Rvalue::UnaryOp(op, arg))
             }
             ExprKind::Box { value } => {
-                let value = &this.thir[value];
+                let value_ty = this.thir[value].ty;
                 let tcx = this.tcx;
 
                 // `exchange_malloc` is unsafe but box is safe, so need a new scope.
@@ -142,7 +131,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     block,
                     synth_info,
                     size,
-                    Rvalue::NullaryOp(NullOp::SizeOf, value.ty),
+                    Rvalue::NullaryOp(NullOp::SizeOf, value_ty),
                 );
 
                 let align = this.temp(tcx.types.usize, expr_span);
@@ -150,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     block,
                     synth_info,
                     align,
-                    Rvalue::NullaryOp(NullOp::AlignOf, value.ty),
+                    Rvalue::NullaryOp(NullOp::AlignOf, value_ty),
                 );
 
                 // malloc some memory of suitable size and align:
@@ -192,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
 
                 // Transmute `*mut u8` to the box (thus far, uninitialized):
-                let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value.ty);
+                let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value_ty);
                 this.cfg.push_assign(block, source_info, Place::from(result), box_);
 
                 // initialize the box contents:
@@ -200,24 +189,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     block = this.expr_into_dest(
                         this.tcx.mk_place_deref(Place::from(result)),
                         block,
-                        value
+                        value,
                     )
                 );
                 block.and(Rvalue::Use(Operand::Move(Place::from(result))))
             }
             ExprKind::Cast { source } => {
-                let source = &this.thir[source];
+                let source_expr = &this.thir[source];
 
                 // Casting an enum to an integer is equivalent to computing the discriminant and casting the
                 // discriminant. Previously every backend had to repeat the logic for this operation. Now we
                 // create all the steps directly in MIR with operations all backends need to support anyway.
-                let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind()
+                let (source, ty) = if let ty::Adt(adt_def, ..) = source_expr.ty.kind()
                     && adt_def.is_enum()
                 {
                     let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
                     let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
-                    let layout = this.tcx.layout_of(this.param_env.and(source.ty));
-                    let discr = this.temp(discr_ty, source.span);
+                    let layout = this.tcx.layout_of(this.param_env.and(source_expr.ty));
+                    let discr = this.temp(discr_ty, source_expr.span);
                     this.cfg.push_assign(
                         block,
                         source_info,
@@ -296,7 +285,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                     (op, ty)
                 } else {
-                    let ty = source.ty;
+                    let ty = source_expr.ty;
                     let source = unpack!(
                         block = this.as_operand(
                             block,
@@ -310,7 +299,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 };
                 let from_ty = CastTy::from_ty(ty);
                 let cast_ty = CastTy::from_ty(expr.ty);
-                debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty,);
+                debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty);
                 let cast_kind = mir_cast_kind(ty, expr.ty);
                 block.and(Rvalue::Cast(cast_kind, source, expr.ty))
             }
@@ -319,7 +308,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     block = this.as_operand(
                         block,
                         scope,
-                        &this.thir[source],
+                        source,
                         LocalInfo::Boring,
                         NeedsTemporary::No
                     )
@@ -363,7 +352,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             block = this.as_operand(
                                 block,
                                 scope,
-                                &this.thir[f],
+                                f,
                                 LocalInfo::Boring,
                                 NeedsTemporary::Maybe
                             )
@@ -384,7 +373,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             block = this.as_operand(
                                 block,
                                 scope,
-                                &this.thir[f],
+                                f,
                                 LocalInfo::Boring,
                                 NeedsTemporary::Maybe
                             )
@@ -416,8 +405,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // ```
                 //
                 for (thir_place, cause, hir_id) in fake_reads.into_iter() {
-                    let place_builder =
-                        unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
+                    let place_builder = unpack!(block = this.as_place_builder(block, *thir_place));
 
                     if let Some(mir_place) = place_builder.try_to_place(this) {
                         this.cfg.push_fake_read(
@@ -434,8 +422,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .into_iter()
                     .copied()
                     .map(|upvar| {
-                        let upvar = &this.thir[upvar];
-                        match Category::of(&upvar.kind) {
+                        let upvar_expr = &this.thir[upvar];
+                        match Category::of(&upvar_expr.kind) {
                             // Use as_place to avoid creating a temporary when
                             // moving a variable into a closure, so that
                             // borrowck knows which variables to mark as being
@@ -453,18 +441,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 // borrow captures when capturing an immutable
                                 // variable. This is sound because the mutation
                                 // that caused the capture will cause an error.
-                                match upvar.kind {
+                                match upvar_expr.kind {
                                     ExprKind::Borrow {
                                         borrow_kind:
                                             BorrowKind::Mut { kind: MutBorrowKind::Default },
                                         arg,
                                     } => unpack!(
                                         block = this.limit_capture_mutability(
-                                            upvar.span,
-                                            upvar.ty,
+                                            upvar_expr.span,
+                                            upvar_expr.ty,
                                             scope,
                                             block,
-                                            &this.thir[arg],
+                                            arg,
                                         )
                                     ),
                                     _ => {
@@ -498,7 +486,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(Rvalue::Aggregate(result, operands))
             }
             ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
-                block = unpack!(this.stmt_expr(block, expr, None));
+                block = unpack!(this.stmt_expr(block, expr_id, None));
                 block.and(Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
                     span: expr_span,
                     user_ty: None,
@@ -553,8 +541,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Some(Category::Rvalue(RvalueFunc::AsRvalue) | Category::Constant)
                 ));
                 let operand = unpack!(
-                    block =
-                        this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)
+                    block = this.as_operand(
+                        block,
+                        scope,
+                        expr_id,
+                        LocalInfo::Boring,
+                        NeedsTemporary::No,
+                    )
                 );
                 block.and(Rvalue::Use(operand))
             }
@@ -719,9 +712,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         outer_source_info: SourceInfo,
     ) -> BlockAnd<Rvalue<'tcx>> {
         let this = self;
-        let value = &this.thir[value];
-        let elem_ty = value.ty;
-        if let Some(Category::Constant) = Category::of(&value.kind) {
+        let value_expr = &this.thir[value];
+        let elem_ty = value_expr.ty;
+        if let Some(Category::Constant) = Category::of(&value_expr.kind) {
             // Repeating a const does nothing
         } else {
             // For a non-const, we may need to generate an appropriate `Drop`
@@ -754,7 +747,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         upvar_ty: Ty<'tcx>,
         temp_lifetime: Option<region::Scope>,
         mut block: BasicBlock,
-        arg: &Expr<'tcx>,
+        arg: ExprId,
     ) -> BlockAnd<Operand<'tcx>> {
         let this = self;
 
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index a4ab365fa9a..4be73e6f03c 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -14,13 +14,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         block: BasicBlock,
         temp_lifetime: Option<region::Scope>,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
         mutability: Mutability,
     ) -> BlockAnd<Local> {
         // this is the only place in mir building that we need to truly need to worry about
         // infinite recursion. Everything else does recurse, too, but it always gets broken up
         // at some point by inserting an intermediate temporary
-        ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
+        ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr_id, mutability))
     }
 
     #[instrument(skip(self), level = "debug")]
@@ -28,16 +28,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         mut block: BasicBlock,
         temp_lifetime: Option<region::Scope>,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
         mutability: Mutability,
     ) -> BlockAnd<Local> {
         let this = self;
 
+        let expr = &this.thir[expr_id];
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
         if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
             return this.in_scope((region_scope, source_info), lint_level, |this| {
-                this.as_temp(block, temp_lifetime, &this.thir[value], mutability)
+                this.as_temp(block, temp_lifetime, value, mutability)
             });
         }
 
@@ -103,7 +104,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        unpack!(block = this.expr_into_dest(temp_place, block, expr));
+        unpack!(block = this.expr_into_dest(temp_place, block, expr_id));
 
         if let Some(temp_lifetime) = temp_lifetime {
             this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value);
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 054661cf237..f50945a4de0 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -19,12 +19,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         destination: Place<'tcx>,
         mut block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<()> {
         // since we frequently have to reference `self` from within a
         // closure, where `self` would be shadowed, it's easier to
         // just use the name `this` uniformly
         let this = self;
+        let expr = &this.thir[expr_id];
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
 
@@ -40,20 +41,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let region_scope = (region_scope, source_info);
                 ensure_sufficient_stack(|| {
                     this.in_scope(region_scope, lint_level, |this| {
-                        this.expr_into_dest(destination, block, &this.thir[value])
+                        this.expr_into_dest(destination, block, value)
                     })
                 })
             }
             ExprKind::Block { block: ast_block } => {
                 this.ast_block(destination, block, ast_block, source_info)
             }
-            ExprKind::Match { scrutinee, ref arms, .. } => {
-                this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms)
-            }
+            ExprKind::Match { scrutinee, ref arms, .. } => this.match_expr(
+                destination,
+                block,
+                scrutinee,
+                arms,
+                expr_span,
+                this.thir[scrutinee].span,
+            ),
             ExprKind::If { cond, then, else_opt, if_then_scope } => {
                 let then_blk;
-                let then_expr = &this.thir[then];
-                let then_source_info = this.source_info(then_expr.span);
+                let then_span = this.thir[then].span;
+                let then_source_info = this.source_info(then_span);
                 let condition_scope = this.local_scope();
 
                 let mut else_blk = unpack!(
@@ -62,27 +68,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         LintLevel::Inherited,
                         |this| {
                             let source_info = if this.is_let(cond) {
-                                let variable_scope = this.new_source_scope(
-                                    then_expr.span,
-                                    LintLevel::Inherited,
-                                    None,
-                                );
+                                let variable_scope =
+                                    this.new_source_scope(then_span, LintLevel::Inherited, None);
                                 this.source_scope = variable_scope;
-                                SourceInfo { span: then_expr.span, scope: variable_scope }
+                                SourceInfo { span: then_span, scope: variable_scope }
                             } else {
-                                this.source_info(then_expr.span)
+                                this.source_info(then_span)
                             };
                             let (then_block, else_block) =
-                                this.in_if_then_scope(condition_scope, then_expr.span, |this| {
+                                this.in_if_then_scope(condition_scope, then_span, |this| {
                                     let then_blk = unpack!(this.then_else_break(
                                         block,
-                                        &this.thir[cond],
+                                        cond,
                                         Some(condition_scope),
                                         condition_scope,
                                         source_info
                                     ));
 
-                                    this.expr_into_dest(destination, then_blk, then_expr)
+                                    this.expr_into_dest(destination, then_blk, then)
                                 });
                             then_block.and(else_block)
                         },
@@ -90,7 +93,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 );
 
                 else_blk = if let Some(else_opt) = else_opt {
-                    unpack!(this.expr_into_dest(destination, else_blk, &this.thir[else_opt]))
+                    unpack!(this.expr_into_dest(destination, else_blk, else_opt))
                 } else {
                     // Body of the `if` expression without an `else` clause must return `()`, thus
                     // we implicitly generate an `else {}` if it is not specified.
@@ -107,7 +110,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::Let { expr, ref pat } => {
                 let scope = this.local_scope();
                 let (true_block, false_block) = this.in_if_then_scope(scope, expr_span, |this| {
-                    this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span, true)
+                    this.lower_let_expr(block, expr, pat, scope, None, expr_span, true)
                 });
 
                 this.cfg.push_assign_constant(
@@ -138,14 +141,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 join_block.unit()
             }
             ExprKind::NeverToAny { source } => {
-                let source = &this.thir[source];
+                let source_expr = &this.thir[source];
                 let is_call =
-                    matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });
+                    matches!(source_expr.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });
 
                 // (#66975) Source could be a const of type `!`, so has to
                 // exist in the generated MIR.
                 unpack!(
-                    block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,)
+                    block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut)
                 );
 
                 // This is an optimization. If the expression was a call then we already have an
@@ -166,7 +169,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.in_if_then_scope(condition_scope, expr.span, |this| {
                         this.then_else_break(
                             block,
-                            &this.thir[lhs],
+                            lhs,
                             Some(condition_scope),
                             condition_scope,
                             source_info,
@@ -192,7 +195,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         const_: Const::from_bool(this.tcx, constant),
                     },
                 );
-                let rhs = unpack!(this.expr_into_dest(destination, continuation, &this.thir[rhs]));
+                let rhs = unpack!(this.expr_into_dest(destination, continuation, rhs));
                 let target = this.cfg.start_new_block();
                 this.cfg.goto(rhs, source_info, target);
                 this.cfg.goto(short_circuit, source_info, target);
@@ -231,8 +234,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // introduce a unit temporary as the destination for the loop body.
                     let tmp = this.get_unit_temp();
                     // Execute the body, branching back to the test.
-                    let body_block_end =
-                        unpack!(this.expr_into_dest(tmp, body_block, &this.thir[body]));
+                    let body_block_end = unpack!(this.expr_into_dest(tmp, body_block, body));
                     this.cfg.goto(body_block_end, source_info, loop_block);
 
                     // Loops are only exited by `break` expressions.
@@ -240,11 +242,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 })
             }
             ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
-                let fun = unpack!(block = this.as_local_operand(block, &this.thir[fun]));
+                let fun = unpack!(block = this.as_local_operand(block, fun));
                 let args: Vec<_> = args
                     .into_iter()
                     .copied()
-                    .map(|arg| unpack!(block = this.as_local_call_operand(block, &this.thir[arg])))
+                    .map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
                     .collect();
 
                 let success = this.cfg.start_new_block();
@@ -280,16 +282,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.diverge_from(block);
                 success.unit()
             }
-            ExprKind::Use { source } => this.expr_into_dest(destination, block, &this.thir[source]),
+            ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
             ExprKind::Borrow { arg, borrow_kind } => {
-                let arg = &this.thir[arg];
                 // We don't do this in `as_rvalue` because we use `as_place`
                 // for borrow expressions, so we cannot create an `RValue` that
                 // remains valid across user code. `as_rvalue` is usually called
                 // by this method anyway, so this shouldn't cause too many
                 // unnecessary temporaries.
                 let arg_place = match borrow_kind {
-                    BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, arg)),
+                    BorrowKind::Shared => {
+                        unpack!(block = this.as_read_only_place(block, arg))
+                    }
                     _ => unpack!(block = this.as_place(block, arg)),
                 };
                 let borrow = Rvalue::Ref(this.tcx.lifetimes.re_erased, borrow_kind, arg_place);
@@ -297,7 +300,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.unit()
             }
             ExprKind::AddressOf { mutability, arg } => {
-                let arg = &this.thir[arg];
                 let place = match mutability {
                     hir::Mutability::Not => this.as_read_only_place(block, arg),
                     hir::Mutability::Mut => this.as_place(block, arg),
@@ -332,7 +334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 block = this.as_operand(
                                     block,
                                     Some(scope),
-                                    &this.thir[f.expr],
+                                    f.expr,
                                     LocalInfo::AggregateTemp,
                                     NeedsTemporary::Maybe,
                                 )
@@ -344,8 +346,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let field_names = adt_def.variant(variant_index).fields.indices();
 
                 let fields = if let Some(FruInfo { base, field_types }) = base {
-                    let place_builder =
-                        unpack!(block = this.as_place_builder(block, &this.thir[*base]));
+                    let place_builder = unpack!(block = this.as_place_builder(block, *base));
 
                     // MIR does not natively support FRU, so for each
                     // base-supplied field, generate an operand that
@@ -398,19 +399,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .map(|op| match *op {
                         thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In {
                             reg,
-                            value: unpack!(block = this.as_local_operand(block, &this.thir[expr])),
+                            value: unpack!(block = this.as_local_operand(block, expr)),
                         },
                         thir::InlineAsmOperand::Out { reg, late, expr } => {
                             mir::InlineAsmOperand::Out {
                                 reg,
                                 late,
-                                place: expr.map(|expr| {
-                                    unpack!(block = this.as_place(block, &this.thir[expr]))
-                                }),
+                                place: expr.map(|expr| unpack!(block = this.as_place(block, expr))),
                             }
                         }
                         thir::InlineAsmOperand::InOut { reg, late, expr } => {
-                            let place = unpack!(block = this.as_place(block, &this.thir[expr]));
+                            let place = unpack!(block = this.as_place(block, expr));
                             mir::InlineAsmOperand::InOut {
                                 reg,
                                 late,
@@ -423,11 +422,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             mir::InlineAsmOperand::InOut {
                                 reg,
                                 late,
-                                in_value: unpack!(
-                                    block = this.as_local_operand(block, &this.thir[in_expr])
-                                ),
+                                in_value: unpack!(block = this.as_local_operand(block, in_expr)),
                                 out_place: out_expr.map(|out_expr| {
-                                    unpack!(block = this.as_place(block, &this.thir[out_expr]))
+                                    unpack!(block = this.as_place(block, out_expr))
                                 }),
                             }
                         }
@@ -488,7 +485,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             // These cases don't actually need a destination
             ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
-                unpack!(block = this.stmt_expr(block, expr, None));
+                unpack!(block = this.stmt_expr(block, expr_id, None));
                 this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
                 block.unit()
             }
@@ -497,7 +494,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::Break { .. }
             | ExprKind::Return { .. }
             | ExprKind::Become { .. } => {
-                unpack!(block = this.stmt_expr(block, expr, None));
+                unpack!(block = this.stmt_expr(block, expr_id, None));
                 // No assign, as these have type `!`.
                 block.unit()
             }
@@ -509,7 +506,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | ExprKind::ValueTypeAscription { .. } => {
                 debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
 
-                let place = unpack!(block = this.as_place(block, expr));
+                let place = unpack!(block = this.as_place(block, expr_id));
                 let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
                 this.cfg.push_assign(block, source_info, destination, rvalue);
                 block.unit()
@@ -524,7 +521,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.local_decls.push(LocalDecl::new(expr.ty, expr.span));
                 }
 
-                let place = unpack!(block = this.as_place(block, expr));
+                let place = unpack!(block = this.as_place(block, expr_id));
                 let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place));
                 this.cfg.push_assign(block, source_info, destination, rvalue);
                 block.unit()
@@ -536,7 +533,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     block = this.as_operand(
                         block,
                         Some(scope),
-                        &this.thir[value],
+                        value,
                         LocalInfo::Boring,
                         NeedsTemporary::No
                     )
@@ -582,7 +579,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     _ => true,
                 });
 
-                let rvalue = unpack!(block = this.as_local_rvalue(block, expr));
+                let rvalue = unpack!(block = this.as_local_rvalue(block, expr_id));
                 this.cfg.push_assign(block, source_info, destination, rvalue);
                 block.unit()
             }
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 7beaef602a8..7f5e45e20cc 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -11,10 +11,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
         statement_scope: Option<region::Scope>,
     ) -> BlockAnd<()> {
         let this = self;
+        let expr = &this.thir[expr_id];
         let expr_span = expr.span;
         let source_info = this.source_info(expr.span);
         // Handle a number of expressions that don't need a destination at all. This
@@ -22,13 +23,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         match expr.kind {
             ExprKind::Scope { region_scope, lint_level, value } => {
                 this.in_scope((region_scope, source_info), lint_level, |this| {
-                    this.stmt_expr(block, &this.thir[value], statement_scope)
+                    this.stmt_expr(block, value, statement_scope)
                 })
             }
             ExprKind::Assign { lhs, rhs } => {
-                let lhs = &this.thir[lhs];
-                let rhs = &this.thir[rhs];
-                let lhs_span = lhs.span;
+                let lhs_expr = &this.thir[lhs];
 
                 // Note: we evaluate assignments right-to-left. This
                 // is better for borrowck interaction with overloaded
@@ -39,10 +38,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 // Generate better code for things that don't need to be
                 // dropped.
-                if lhs.ty.needs_drop(this.tcx, this.param_env) {
+                if lhs_expr.ty.needs_drop(this.tcx, this.param_env) {
                     let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
-                    unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
+                    unpack!(block = this.build_drop_and_replace(block, lhs_expr.span, lhs, rhs));
                 } else {
                     let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
@@ -61,9 +60,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // only affects weird things like `x += {x += 1; x}`
                 // -- is that equal to `x + (x + 1)` or `2*(x+1)`?
 
-                let lhs = &this.thir[lhs];
-                let rhs = &this.thir[rhs];
-                let lhs_ty = lhs.ty;
+                let lhs_ty = this.thir[lhs].ty;
 
                 debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr);
                 this.block_context.push(BlockFrame::SubExpr);
@@ -87,25 +84,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::Continue { label } => {
                 this.break_scope(block, None, BreakableTarget::Continue(label), source_info)
             }
-            ExprKind::Break { label, value } => this.break_scope(
-                block,
-                value.map(|value| &this.thir[value]),
-                BreakableTarget::Break(label),
-                source_info,
-            ),
-            ExprKind::Return { value } => this.break_scope(
-                block,
-                value.map(|value| &this.thir[value]),
-                BreakableTarget::Return,
-                source_info,
-            ),
+            ExprKind::Break { label, value } => {
+                this.break_scope(block, value, BreakableTarget::Break(label), source_info)
+            }
+            ExprKind::Return { value } => {
+                this.break_scope(block, value, BreakableTarget::Return, source_info)
+            }
             // FIXME(explicit_tail_calls): properly lower tail calls here
-            ExprKind::Become { value } => this.break_scope(
-                block,
-                Some(&this.thir[value]),
-                BreakableTarget::Return,
-                source_info,
-            ),
+            ExprKind::Become { value } => {
+                this.break_scope(block, Some(value), BreakableTarget::Return, source_info)
+            }
             _ => {
                 assert!(
                     statement_scope.is_some(),
@@ -147,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 };
 
                 let temp =
-                    unpack!(block = this.as_temp(block, statement_scope, expr, Mutability::Not));
+                    unpack!(block = this.as_temp(block, statement_scope, expr_id, Mutability::Not));
 
                 if let Some(span) = adjusted_span {
                     this.local_decls[temp].source_info.span = span;
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 541b87af797..5d5084c0b66 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -36,19 +36,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn then_else_break(
         &mut self,
         mut block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
         temp_scope_override: Option<region::Scope>,
         break_scope: region::Scope,
         variable_source_info: SourceInfo,
     ) -> BlockAnd<()> {
         let this = self;
+        let expr = &this.thir[expr_id];
         let expr_span = expr.span;
 
         match expr.kind {
             ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
                 let lhs_then_block = unpack!(this.then_else_break(
                     block,
-                    &this.thir[lhs],
+                    lhs,
                     temp_scope_override,
                     break_scope,
                     variable_source_info,
@@ -56,7 +57,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 let rhs_then_block = unpack!(this.then_else_break(
                     lhs_then_block,
-                    &this.thir[rhs],
+                    rhs,
                     temp_scope_override,
                     break_scope,
                     variable_source_info,
@@ -70,7 +71,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.in_if_then_scope(local_scope, expr_span, |this| {
                         this.then_else_break(
                             block,
-                            &this.thir[lhs],
+                            lhs,
                             temp_scope_override,
                             local_scope,
                             variable_source_info,
@@ -78,7 +79,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     });
                 let rhs_success_block = unpack!(this.then_else_break(
                     failure_block,
-                    &this.thir[rhs],
+                    rhs,
                     temp_scope_override,
                     break_scope,
                     variable_source_info,
@@ -97,7 +98,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         }
                         this.then_else_break(
                             block,
-                            &this.thir[arg],
+                            arg,
                             temp_scope_override,
                             local_scope,
                             variable_source_info,
@@ -111,7 +112,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.in_scope(region_scope, lint_level, |this| {
                     this.then_else_break(
                         block,
-                        &this.thir[value],
+                        value,
                         temp_scope_override,
                         break_scope,
                         variable_source_info,
@@ -120,14 +121,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             ExprKind::Use { source } => this.then_else_break(
                 block,
-                &this.thir[source],
+                source,
                 temp_scope_override,
                 break_scope,
                 variable_source_info,
             ),
             ExprKind::Let { expr, ref pat } => this.lower_let_expr(
                 block,
-                &this.thir[expr],
+                expr,
                 pat,
                 break_scope,
                 Some(variable_source_info.scope),
@@ -138,7 +139,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
                 let mutability = Mutability::Mut;
                 let place =
-                    unpack!(block = this.as_temp(block, Some(temp_scope), expr, mutability));
+                    unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability));
                 let operand = Operand::Move(Place::from(place));
 
                 let then_block = this.cfg.start_new_block();
@@ -208,14 +209,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn match_expr(
         &mut self,
         destination: Place<'tcx>,
-        span: Span,
         mut block: BasicBlock,
-        scrutinee: &Expr<'tcx>,
+        scrutinee_id: ExprId,
         arms: &[ArmId],
+        span: Span,
+        scrutinee_span: Span,
     ) -> BlockAnd<()> {
-        let scrutinee_span = scrutinee.span;
+        let scrutinee_span = scrutinee_span;
         let scrutinee_place =
-            unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
+            unpack!(block = self.lower_scrutinee(block, scrutinee_id, scrutinee_span));
 
         let mut arm_candidates = self.create_match_candidates(&scrutinee_place, arms);
 
@@ -223,7 +225,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let mut candidates =
             arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
 
-        let match_start_span = span.shrink_to_lo().to(scrutinee.span);
+        let match_start_span = span.shrink_to_lo().to(scrutinee_span);
 
         let fake_borrow_temps = self.lower_match_tree(
             block,
@@ -248,10 +250,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn lower_scrutinee(
         &mut self,
         mut block: BasicBlock,
-        scrutinee: &Expr<'tcx>,
+        scrutinee_id: ExprId,
         scrutinee_span: Span,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
-        let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee));
+        let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee_id));
         if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) {
             let source_info = self.source_info(scrutinee_span);
             self.cfg.push_place_mention(block, source_info, scrutinee_place);
@@ -429,7 +431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         this.source_scope = source_scope;
                     }
 
-                    this.expr_into_dest(destination, arm_block, &this.thir[arm.body])
+                    this.expr_into_dest(destination, arm_block, arm.body)
                 })
             })
             .collect();
@@ -538,14 +540,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         mut block: BasicBlock,
         irrefutable_pat: &Pat<'tcx>,
-        initializer: &Expr<'tcx>,
+        initializer_id: ExprId,
     ) -> BlockAnd<()> {
         match irrefutable_pat.kind {
             // Optimize the case of `let x = ...` to write directly into `x`
             PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
-                unpack!(block = self.expr_into_dest(place, block, initializer));
+                unpack!(block = self.expr_into_dest(place, block, initializer_id));
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let source_info = self.source_info(irrefutable_pat.span);
@@ -576,7 +578,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             } => {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
-                unpack!(block = self.expr_into_dest(place, block, initializer));
+                unpack!(block = self.expr_into_dest(place, block, initializer_id));
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let pattern_source_info = self.source_info(irrefutable_pat.span);
@@ -616,8 +618,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
 
             _ => {
+                let initializer = &self.thir[initializer_id];
                 let place_builder =
-                    unpack!(block = self.lower_scrutinee(block, initializer, initializer.span));
+                    unpack!(block = self.lower_scrutinee(block, initializer_id, initializer.span));
                 self.place_into_pattern(block, irrefutable_pat, place_builder, true)
             }
         }
@@ -1839,15 +1842,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn lower_let_expr(
         &mut self,
         mut block: BasicBlock,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
         pat: &Pat<'tcx>,
         else_target: region::Scope,
         source_scope: Option<SourceScope>,
         span: Span,
         declare_bindings: bool,
     ) -> BlockAnd<()> {
-        let expr_span = expr.span;
-        let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
+        let expr_span = self.thir[expr_id].span;
+        let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
         let wildcard = Pat::wildcard_from_ty(pat.ty);
         let mut guard_candidate = Candidate::new(expr_place_builder.clone(), pat, false, self);
         let mut otherwise_candidate =
@@ -1873,7 +1876,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.source_info(pat.span),
             guard_candidate,
             &fake_borrow_temps,
-            expr.span,
+            expr_span,
             None,
             false,
         );
@@ -2036,8 +2039,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let (post_guard_block, otherwise_post_guard_block) =
                 self.in_if_then_scope(match_scope, guard_span, |this| match *guard {
                     Guard::If(e) => {
-                        let e = &this.thir[e];
-                        guard_span = e.span;
+                        guard_span = this.thir[e].span;
                         this.then_else_break(
                             block,
                             e,
@@ -2046,9 +2048,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             this.source_info(arm.span),
                         )
                     }
-                    Guard::IfLet(ref pat, scrutinee) => {
-                        let s = &this.thir[scrutinee];
-                        guard_span = s.span;
+                    Guard::IfLet(ref pat, s) => {
+                        guard_span = this.thir[s].span;
                         this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false)
                     }
                 });
@@ -2342,7 +2343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn ast_let_else(
         &mut self,
         mut block: BasicBlock,
-        init: &Expr<'tcx>,
+        init_id: ExprId,
         initializer_span: Span,
         else_block: BlockId,
         let_else_scope: &region::Scope,
@@ -2350,8 +2351,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) -> BlockAnd<BasicBlock> {
         let else_block_span = self.thir[else_block].span;
         let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| {
-            let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
-            let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
+            let scrutinee = unpack!(block = this.lower_scrutinee(block, init_id, initializer_span));
+            let pat = Pat { ty: pattern.ty, span: else_block_span, kind: PatKind::Wild };
             let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false, this);
             let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this);
             let fake_borrow_temps = this.lower_match_tree(
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index dae83d4b41b..bef5c83d4a1 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -18,7 +18,7 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{
-    self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
+    self, BindingMode, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
 };
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::symbol::sym;
@@ -539,7 +539,7 @@ fn construct_fn<'tcx>(
         let return_block =
             unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
                 Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
-                    builder.args_and_body(START_BLOCK, arguments, arg_scope, &thir[expr])
+                    builder.args_and_body(START_BLOCK, arguments, arg_scope, expr)
                 }))
             }));
         let source_info = builder.source_info(fn_end);
@@ -606,7 +606,7 @@ fn construct_const<'a, 'tcx>(
     );
 
     let mut block = START_BLOCK;
-    unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr]));
+    unpack!(block = builder.expr_into_dest(Place::return_place(), block, expr));
 
     let source_info = builder.source_info(span);
     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
@@ -865,8 +865,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         mut block: BasicBlock,
         arguments: &IndexSlice<ParamId, Param<'tcx>>,
         argument_scope: region::Scope,
-        expr: &Expr<'tcx>,
+        expr_id: ExprId,
     ) -> BlockAnd<()> {
+        let expr_span = self.thir[expr_id].span;
         // Allocate locals for the function arguments
         for (argument_index, param) in arguments.iter().enumerate() {
             let source_info =
@@ -899,7 +900,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             // Make sure we drop (parts of) the argument even when not matched on.
             self.schedule_drop(
-                param.pat.as_ref().map_or(expr.span, |pat| pat.span),
+                param.pat.as_ref().map_or(expr_span, |pat| pat.span),
                 argument_scope,
                 local,
                 DropKind::Value,
@@ -941,8 +942,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 _ => {
                     scope = self.declare_bindings(
                         scope,
-                        expr.span,
-                        pat,
+                        expr_span,
+                        &pat,
                         None,
                         Some((Some(&place), span)),
                     );
@@ -958,7 +959,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.source_scope = source_scope;
         }
 
-        self.expr_into_dest(Place::return_place(), block, expr)
+        self.expr_into_dest(Place::return_place(), block, expr_id)
     }
 
     fn set_correct_source_scope_for_arg(
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 25b79e6a523..1a700ac7342 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -89,7 +89,7 @@ use rustc_hir::HirId;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
-use rustc_middle::thir::{Expr, LintLevel};
+use rustc_middle::thir::{ExprId, LintLevel};
 use rustc_session::lint::Level;
 use rustc_span::{Span, DUMMY_SP};
 
@@ -592,7 +592,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub(crate) fn break_scope(
         &mut self,
         mut block: BasicBlock,
-        value: Option<&Expr<'tcx>>,
+        value: Option<ExprId>,
         target: BreakableTarget,
         source_info: SourceInfo,
     ) -> BlockAnd<()> {