]> git.lizzy.rs Git - rust.git/commitdiff
[WIP] Eagerly construct bodies of THIR
authorLeSeulArtichaut <leseulartichaut@gmail.com>
Wed, 24 Feb 2021 20:29:09 +0000 (21:29 +0100)
committerLeSeulArtichaut <leseulartichaut@gmail.com>
Tue, 9 Mar 2021 19:12:41 +0000 (20:12 +0100)
18 files changed:
compiler/rustc_mir_build/src/build/block.rs
compiler/rustc_mir_build/src/build/expr/as_constant.rs
compiler/rustc_mir_build/src/build/expr/as_operand.rs
compiler/rustc_mir_build/src/build/expr/as_place.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
compiler/rustc_mir_build/src/build/expr/as_temp.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/expr/mod.rs
compiler/rustc_mir_build/src/build/expr/stmt.rs
compiler/rustc_mir_build/src/build/into.rs [deleted file]
compiler/rustc_mir_build/src/build/matches/mod.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/build/scope.rs
compiler/rustc_mir_build/src/thir/cx/block.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/cx/mod.rs
compiler/rustc_mir_build/src/thir/cx/to_ref.rs [deleted file]
compiler/rustc_mir_build/src/thir/mod.rs

index d5f72e6f22dfa29af8a3c5870d9ab593a17428b7..2d1fd4d09d1a447badca352e22ca50da067a8e4b 100644 (file)
@@ -2,7 +2,6 @@
 use crate::build::ForGuard::OutsideGuard;
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::thir::*;
-use rustc_hir as hir;
 use rustc_middle::mir::*;
 use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN;
 use rustc_session::lint::Level;
@@ -13,7 +12,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         destination: Place<'tcx>,
         block: BasicBlock,
-        ast_block: &'tcx hir::Block<'tcx>,
+        ast_block: &Block<'tcx>,
         source_info: SourceInfo,
     ) -> BlockAnd<()> {
         let Block {
@@ -24,22 +23,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             expr,
             targeted_by_break,
             safety_mode,
-        } = self.hir.mirror(ast_block);
+        } = ast_block;
         self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
-            this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
-                if targeted_by_break {
-                    this.in_breakable_scope(None, destination, span, |this| {
+            this.in_scope((*region_scope, source_info), LintLevel::Inherited, move |this| {
+                if *targeted_by_break {
+                    this.in_breakable_scope(None, destination, *span, |this| {
                         Some(this.ast_block_stmts(
                             destination,
                             block,
-                            span,
-                            stmts,
-                            expr,
-                            safety_mode,
+                            *span,
+                            &stmts,
+                            expr.as_deref(),
+                            *safety_mode,
                         ))
                     })
                 } else {
-                    this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
+                    this.ast_block_stmts(
+                        destination,
+                        block,
+                        *span,
+                        &stmts,
+                        expr.as_deref(),
+                        *safety_mode,
+                    )
                 }
             })
         })
@@ -50,8 +56,8 @@ fn ast_block_stmts(
         destination: Place<'tcx>,
         mut block: BasicBlock,
         span: Span,
-        stmts: Vec<StmtRef<'tcx>>,
-        expr: Option<ExprRef<'tcx>>,
+        stmts: &[Stmt<'tcx>],
+        expr: Option<&Expr<'tcx>>,
         safety_mode: BlockSafety,
     ) -> BlockAnd<()> {
         let this = self;
@@ -79,8 +85,7 @@ fn ast_block_stmts(
         this.update_source_scope_for_safety_mode(span, safety_mode);
 
         let source_info = this.source_info(span);
-        for stmt in stmts {
-            let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
+        for Stmt { kind, opt_destruction_scope } in stmts {
             match kind {
                 StmtKind::Expr { scope, expr } => {
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
@@ -88,10 +93,9 @@ fn ast_block_stmts(
                         block = this.in_opt_scope(
                             opt_destruction_scope.map(|de| (de, source_info)),
                             |this| {
-                                let si = (scope, source_info);
+                                let si = (*scope, source_info);
                                 this.in_scope(si, LintLevel::Inherited, |this| {
-                                    let expr = this.hir.mirror(expr);
-                                    this.stmt_expr(block, expr, Some(scope))
+                                    this.stmt_expr(block, &expr, Some(*scope))
                                 })
                             }
                         )
@@ -102,7 +106,7 @@ fn ast_block_stmts(
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result });
 
                     // Enter the remainder scope, i.e., the bindings' destruction scope.
-                    this.push_scope((remainder_scope, source_info));
+                    this.push_scope((*remainder_scope, source_info));
                     let_scope_stack.push(remainder_scope);
 
                     // Declare the bindings, which may create a source scope.
@@ -114,14 +118,14 @@ fn ast_block_stmts(
 
                     // Evaluate the initializer, if present.
                     if let Some(init) = initializer {
-                        let initializer_span = init.span();
+                        let initializer_span = init.span;
 
                         unpack!(
                             block = this.in_opt_scope(
                                 opt_destruction_scope.map(|de| (de, source_info)),
                                 |this| {
-                                    let scope = (init_scope, source_info);
-                                    this.in_scope(scope, lint_level, |this| {
+                                    let scope = (*init_scope, source_info);
+                                    this.in_scope(scope, *lint_level, |this| {
                                         this.declare_bindings(
                                             visibility_scope,
                                             remainder_span,
@@ -129,14 +133,14 @@ fn ast_block_stmts(
                                             ArmHasGuard(false),
                                             Some((None, initializer_span)),
                                         );
-                                        this.expr_into_pattern(block, patterninit)
+                                        this.expr_into_pattern(block, pattern.clone(), &init)
                                     })
                                 }
                             )
                         );
                     } else {
-                        let scope = (init_scope, source_info);
-                        unpack!(this.in_scope(scope, lint_level, |this| {
+                        let scope = (*init_scope, source_info);
+                        unpack!(this.in_scope(scope, *lint_level, |this| {
                             this.declare_bindings(
                                 visibility_scope,
                                 remainder_span,
@@ -176,13 +180,10 @@ fn ast_block_stmts(
         if let Some(expr) = expr {
             let tail_result_is_ignored =
                 destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
-            let span = match expr {
-                ExprRef::Thir(expr) => expr.span,
-                ExprRef::Mirror(ref expr) => expr.span,
-            };
-            this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored, span });
+            this.block_context
+                .push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });
 
-            unpack!(block = this.into(destination, block, expr));
+            unpack!(block = this.expr_into_dest(destination, block, expr));
             let popped = this.block_context.pop();
 
             assert!(popped.map_or(false, |bf| bf.is_tail_expr()));
@@ -200,7 +201,7 @@ fn ast_block_stmts(
         // Finally, we pop all the let scopes before exiting out from the scope of block
         // itself.
         for scope in let_scope_stack.into_iter().rev() {
-            unpack!(block = this.pop_scope((scope, source_info), block));
+            unpack!(block = this.pop_scope((*scope, source_info), block));
         }
         // Restore the original source scope.
         this.source_scope = outer_source_scope;
index 3a36ad590c506faa0842a51e55a2b2d3ced1645d..1096d2eedfe218bd6075410ed0477b04ea2b765c 100644 (file)
@@ -8,33 +8,27 @@
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
     /// `expr` is a valid compile-time constant!
-    crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
-        let expr = self.hir.mirror(expr);
-        self.expr_as_constant(expr)
-    }
-
-    fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
+    crate fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
         let this = self;
         let Expr { ty, temp_lifetime: _, span, kind } = expr;
         match kind {
-            ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
+            ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(&value),
             ExprKind::Literal { literal, user_ty, const_id: _ } => {
                 let user_ty = user_ty.map(|user_ty| {
                     this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
-                        span,
+                        span: *span,
                         user_ty,
                         inferred_ty: ty,
                     })
                 });
-                assert_eq!(literal.ty, ty);
-                Constant { span, user_ty, literal }
+                assert_eq!(literal.ty, *ty);
+                Constant { span: *span, user_ty, literal }
+            }
+            ExprKind::StaticRef { literal, .. } => Constant { span: *span, user_ty: None, literal },
+            ExprKind::ConstBlock { value } => {
+                Constant { span: *span, user_ty: None, literal: value }
             }
-            ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal },
-            ExprKind::ConstBlock { value } => Constant { span, user_ty: None, literal: value },
-            _ => span_bug!(span, "expression is not a valid constant {:?}", kind),
+            _ => span_bug!(*span, "expression is not a valid constant {:?}", kind),
         }
     }
 }
index 60f8d8c8a9f36fd1c1c104723cbf87d29261d7bd..faa8ea759d70970b39695d2c4b412b8412a59ba1 100644 (file)
@@ -14,10 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// after the current enclosing `ExprKind::Scope` has ended, so
     /// please do *not* return it from functions to avoid bad
     /// miscompiles.
-    crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
+    crate fn as_local_operand(
+        &mut self,
+        block: BasicBlock,
+        expr: &Expr<'tcx>,
+    ) -> BlockAnd<Operand<'tcx>> {
         let local_scope = self.local_scope();
         self.as_operand(block, Some(local_scope), expr)
     }
@@ -70,14 +71,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// value to the stack.
     ///
     /// See #68034 for more details.
-    crate fn as_local_call_operand<M>(
+    crate fn as_local_call_operand(
         &mut self,
         block: BasicBlock,
-        expr: M,
-    ) -> BlockAnd<Operand<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
+        expr: &Expr<'tcx>,
+    ) -> BlockAnd<Operand<'tcx>> {
         let local_scope = self.local_scope();
         self.as_call_operand(block, Some(local_scope), expr)
     }
@@ -88,52 +86,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// this time.
     ///
     /// The operand is known to be live until the end of `scope`.
-    crate fn as_operand<M>(
-        &mut self,
-        block: BasicBlock,
-        scope: Option<region::Scope>,
-        expr: M,
-    ) -> BlockAnd<Operand<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
-        let expr = self.hir.mirror(expr);
-        self.expr_as_operand(block, scope, expr)
-    }
-
+    ///
     /// Like `as_local_call_operand`, except that the argument will
     /// not be valid once `scope` ends.
-    fn as_call_operand<M>(
-        &mut self,
-        block: BasicBlock,
-        scope: Option<region::Scope>,
-        expr: M,
-    ) -> BlockAnd<Operand<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
-        let expr = self.hir.mirror(expr);
-        self.expr_as_call_operand(block, scope, expr)
-    }
-
-    fn expr_as_operand(
+    crate fn as_operand(
         &mut self,
         mut block: BasicBlock,
         scope: Option<region::Scope>,
-        expr: Expr<'tcx>,
+        expr: &Expr<'tcx>,
     ) -> BlockAnd<Operand<'tcx>> {
-        debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
+        debug!("as_operand(block={:?}, expr={:?})", block, expr);
         let this = self;
 
-        if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
+        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);
+            let region_scope = (*region_scope, source_info);
             return this
-                .in_scope(region_scope, lint_level, |this| this.as_operand(block, scope, value));
+                .in_scope(region_scope, *lint_level, |this| this.as_operand(block, scope, &value));
         }
 
         let category = Category::of(&expr.kind).unwrap();
-        debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind);
+        debug!("as_operand: category={:?} for={:?}", category, expr.kind);
         match category {
             Category::Constant => {
                 let constant = this.as_constant(expr);
@@ -146,20 +119,20 @@ fn expr_as_operand(
         }
     }
 
-    fn expr_as_call_operand(
+    crate fn as_call_operand(
         &mut self,
         mut block: BasicBlock,
         scope: Option<region::Scope>,
-        expr: Expr<'tcx>,
+        expr: &Expr<'tcx>,
     ) -> BlockAnd<Operand<'tcx>> {
-        debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr);
+        debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
         let this = self;
 
-        if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
+        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, value)
+            let region_scope = (*region_scope, source_info);
+            return this.in_scope(region_scope, *lint_level, |this| {
+                this.as_call_operand(block, scope, &value)
             });
         }
 
@@ -177,8 +150,6 @@ fn expr_as_call_operand(
                 // As described above, detect the case where we are passing a value of unsized
                 // type, and that value is coming from the deref of a box.
                 if let ExprKind::Deref { ref arg } = expr.kind {
-                    let arg = this.hir.mirror(arg.clone());
-
                     // Generate let tmp0 = arg0
                     let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut));
 
@@ -193,6 +164,6 @@ fn expr_as_call_operand(
             }
         }
 
-        this.expr_as_operand(block, scope, expr)
+        this.as_operand(block, scope, expr)
     }
 }
index 89143e244478f8b44bb031f75744563d97d0e9f1..156f8d2e7045c754e45c950b2b82e2b3266f4dce 100644 (file)
@@ -347,25 +347,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Extra care is needed if any user code is allowed to run between calling
     /// this method and using it, as is the case for `match` and index
     /// expressions.
-    crate fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
+    crate fn as_place(
+        &mut self,
+        mut block: BasicBlock,
+        expr: &Expr<'tcx>,
+    ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_place_builder(block, expr));
         block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results()))
     }
 
     /// This is used when constructing a compound `Place`, so that we can avoid creating
     /// intermediate `Place` values until we know the full set of projections.
-    crate fn as_place_builder<M>(
+    crate fn as_place_builder(
         &mut self,
         block: BasicBlock,
-        expr: M,
-    ) -> BlockAnd<PlaceBuilder<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
-        let expr = self.hir.mirror(expr);
+        expr: &Expr<'tcx>,
+    ) -> BlockAnd<PlaceBuilder<'tcx>> {
         self.expr_as_place(block, expr, Mutability::Mut, None)
     }
 
@@ -374,14 +371,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// place. The place itself may or may not be mutable:
     /// * If this expr is a place expr like a.b, then we will return that place.
     /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
-    crate fn as_read_only_place<M>(
+    crate fn as_read_only_place(
         &mut self,
         mut block: BasicBlock,
-        expr: M,
-    ) -> BlockAnd<Place<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
+        expr: &Expr<'tcx>,
+    ) -> BlockAnd<Place<'tcx>> {
         let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
         block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results()))
     }
@@ -392,22 +386,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// place. The place itself may or may not be mutable:
     /// * If this expr is a place expr like a.b, then we will return that place.
     /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
-    fn as_read_only_place_builder<M>(
+    fn as_read_only_place_builder(
         &mut self,
         block: BasicBlock,
-        expr: M,
-    ) -> BlockAnd<PlaceBuilder<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
-        let expr = self.hir.mirror(expr);
+        expr: &Expr<'tcx>,
+    ) -> BlockAnd<PlaceBuilder<'tcx>> {
         self.expr_as_place(block, expr, Mutability::Not, None)
     }
 
     fn expr_as_place(
         &mut self,
         mut block: BasicBlock,
-        expr: Expr<'tcx>,
+        expr: &Expr<'tcx>,
         mutability: Mutability,
         fake_borrow_temps: Option<&mut Vec<Local>>,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
@@ -416,29 +406,28 @@ fn expr_as_place(
         let this = self;
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
-        match expr.kind {
+        match &expr.kind {
             ExprKind::Scope { region_scope, lint_level, value } => {
-                this.in_scope((region_scope, source_info), lint_level, |this| {
-                    let value = this.hir.mirror(value);
-                    this.expr_as_place(block, value, mutability, fake_borrow_temps)
+                this.in_scope((*region_scope, source_info), *lint_level, |this| {
+                    this.expr_as_place(block, &value, mutability, fake_borrow_temps)
                 })
             }
             ExprKind::Field { lhs, name } => {
-                let lhs = this.hir.mirror(lhs);
-                let place_builder =
-                    unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,));
-                block.and(place_builder.field(name, expr.ty))
+                let place_builder = unpack!(
+                    block = this.expr_as_place(block, &lhs, mutability, fake_borrow_temps,)
+                );
+                block.and(place_builder.field(*name, expr.ty))
             }
             ExprKind::Deref { arg } => {
-                let arg = this.hir.mirror(arg);
-                let place_builder =
-                    unpack!(block = this.expr_as_place(block, 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,
-                lhs,
-                index,
+                &lhs,
+                &index,
                 mutability,
                 fake_borrow_temps,
                 expr.temp_lifetime,
@@ -446,31 +435,30 @@ fn expr_as_place(
                 source_info,
             ),
             ExprKind::UpvarRef { closure_def_id, var_hir_id } => {
-                let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id.expect_local());
+                let upvar_id = ty::UpvarId::new(*var_hir_id, closure_def_id.expect_local());
                 this.lower_captured_upvar(block, upvar_id)
             }
 
             ExprKind::VarRef { id } => {
-                let place_builder = if this.is_bound_var_in_guard(id) {
-                    let index = this.var_local_id(id, RefWithinGuard);
+                let place_builder = if this.is_bound_var_in_guard(*id) {
+                    let index = this.var_local_id(*id, RefWithinGuard);
                     PlaceBuilder::from(index).deref()
                 } else {
-                    let index = this.var_local_id(id, OutsideGuard);
+                    let index = this.var_local_id(*id, OutsideGuard);
                     PlaceBuilder::from(index)
                 };
                 block.and(place_builder)
             }
 
             ExprKind::PlaceTypeAscription { source, user_ty } => {
-                let source = this.hir.mirror(source);
                 let place_builder = unpack!(
-                    block = this.expr_as_place(block, 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 =
                         this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                             span: source_info.span,
-                            user_ty,
+                            user_ty: *user_ty,
                             inferred_ty: expr.ty,
                         });
 
@@ -493,14 +481,13 @@ fn expr_as_place(
                 block.and(place_builder)
             }
             ExprKind::ValueTypeAscription { source, user_ty } => {
-                let source = this.hir.mirror(source);
                 let temp =
-                    unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
+                    unpack!(block = this.as_temp(block, source.temp_lifetime, &source, mutability));
                 if let Some(user_ty) = user_ty {
                     let annotation_index =
                         this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
                             span: source_info.span,
-                            user_ty,
+                            user_ty: *user_ty,
                             inferred_ty: expr.ty,
                         });
                     this.cfg.push(
@@ -599,22 +586,20 @@ fn lower_captured_upvar(
     fn lower_index_expression(
         &mut self,
         mut block: BasicBlock,
-        base: ExprRef<'tcx>,
-        index: ExprRef<'tcx>,
+        base: &Expr<'tcx>,
+        index: &Expr<'tcx>,
         mutability: Mutability,
         fake_borrow_temps: Option<&mut Vec<Local>>,
         temp_lifetime: Option<region::Scope>,
         expr_span: Span,
         source_info: SourceInfo,
     ) -> BlockAnd<PlaceBuilder<'tcx>> {
-        let lhs = self.hir.mirror(base);
-
         let base_fake_borrow_temps = &mut Vec::new();
         let is_outermost_index = fake_borrow_temps.is_none();
         let fake_borrow_temps = fake_borrow_temps.unwrap_or(base_fake_borrow_temps);
 
         let mut base_place =
-            unpack!(block = self.expr_as_place(block, lhs, mutability, Some(fake_borrow_temps),));
+            unpack!(block = self.expr_as_place(block, base, mutability, Some(fake_borrow_temps),));
 
         // Making this a *fresh* temporary means we do not have to worry about
         // the index changing later: Nothing will ever change this temporary.
index fd696f997065c7815550801c83548cebb3cbd7e9..8082315408c6fc7c8825f970b9e7846bf6c16f27 100644 (file)
@@ -19,33 +19,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// The operand returned from this function will *not be valid* after
     /// an ExprKind::Scope is passed, so please do *not* return it from
     /// functions to avoid bad miscompiles.
-    crate fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
+    crate fn as_local_rvalue(
+        &mut self,
+        block: BasicBlock,
+        expr: &Expr<'tcx>,
+    ) -> BlockAnd<Rvalue<'tcx>> {
         let local_scope = self.local_scope();
         self.as_rvalue(block, Some(local_scope), expr)
     }
 
     /// Compile `expr`, yielding an rvalue.
-    fn as_rvalue<M>(
-        &mut self,
-        block: BasicBlock,
-        scope: Option<region::Scope>,
-        expr: M,
-    ) -> BlockAnd<Rvalue<'tcx>>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
-        let expr = self.hir.mirror(expr);
-        self.expr_as_rvalue(block, scope, expr)
-    }
-
-    fn expr_as_rvalue(
+    crate fn as_rvalue(
         &mut self,
         mut block: BasicBlock,
         scope: Option<region::Scope>,
-        expr: Expr<'tcx>,
+        expr: &Expr<'tcx>,
     ) -> BlockAnd<Rvalue<'tcx>> {
         debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
 
@@ -53,25 +41,27 @@ fn expr_as_rvalue(
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
 
-        match expr.kind {
-            ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)),
+        match &expr.kind {
+            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, value))
+                let region_scope = (*region_scope, source_info);
+                this.in_scope(region_scope, *lint_level, |this| {
+                    this.as_rvalue(block, scope, &value)
+                })
             }
             ExprKind::Repeat { value, count } => {
-                let value_operand = unpack!(block = this.as_operand(block, scope, value));
+                let value_operand = unpack!(block = this.as_operand(block, scope, &value));
                 block.and(Rvalue::Repeat(value_operand, count))
             }
             ExprKind::Binary { op, lhs, rhs } => {
-                let lhs = unpack!(block = this.as_operand(block, scope, lhs));
-                let rhs = unpack!(block = this.as_operand(block, scope, rhs));
-                this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
+                let lhs = unpack!(block = this.as_operand(block, scope, &lhs));
+                let rhs = unpack!(block = this.as_operand(block, scope, &rhs));
+                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, arg));
+                let arg = unpack!(block = this.as_operand(block, scope, &arg));
                 // Check for -MIN on signed integers
-                if this.hir.check_overflow() && op == UnOp::Neg && expr.ty.is_signed() {
+                if this.hir.check_overflow() && *op == UnOp::Neg && expr.ty.is_signed() {
                     let bool_ty = this.hir.bool_ty();
 
                     let minval = this.minval_literal(expr_span, expr.ty);
@@ -92,10 +82,9 @@ fn expr_as_rvalue(
                         expr_span,
                     );
                 }
-                block.and(Rvalue::UnaryOp(op, arg))
+                block.and(Rvalue::UnaryOp(*op, arg))
             }
             ExprKind::Box { value } => {
-                let value = this.hir.mirror(value);
                 // The `Box<T>` temporary created here is not a part of the HIR,
                 // and therefore is not considered during generator auto-trait
                 // determination. See the comment about `box` at `yield_in_scope`.
@@ -115,18 +104,21 @@ fn expr_as_rvalue(
 
                 // initialize the box contents:
                 unpack!(
-                    block =
-                        this.into(this.hir.tcx().mk_place_deref(Place::from(result)), block, value)
+                    block = this.expr_into_dest(
+                        this.hir.tcx().mk_place_deref(Place::from(result)),
+                        block,
+                        &value
+                    )
                 );
                 block.and(Rvalue::Use(Operand::Move(Place::from(result))))
             }
             ExprKind::Cast { source } => {
-                let source = unpack!(block = this.as_operand(block, scope, source));
+                let source = unpack!(block = this.as_operand(block, scope, &source));
                 block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
             }
             ExprKind::Pointer { cast, source } => {
-                let source = unpack!(block = this.as_operand(block, scope, source));
-                block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
+                let source = unpack!(block = this.as_operand(block, scope, &source));
+                block.and(Rvalue::Cast(CastKind::Pointer(*cast), source, expr.ty))
             }
             ExprKind::Array { fields } => {
                 // (*) We would (maybe) be closer to codegen if we
@@ -159,7 +151,7 @@ fn expr_as_rvalue(
                 let el_ty = expr.ty.sequence_element_type(this.hir.tcx());
                 let fields: Vec<_> = fields
                     .into_iter()
-                    .map(|f| unpack!(block = this.as_operand(block, scope, f)))
+                    .map(|f| unpack!(block = this.as_operand(block, scope, &f)))
                     .collect();
 
                 block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields))
@@ -169,7 +161,7 @@ fn expr_as_rvalue(
                 // first process the set of fields
                 let fields: Vec<_> = fields
                     .into_iter()
-                    .map(|f| unpack!(block = this.as_operand(block, scope, f)))
+                    .map(|f| unpack!(block = this.as_operand(block, scope, &f)))
                     .collect();
 
                 block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
@@ -179,7 +171,6 @@ fn expr_as_rvalue(
                 let operands: Vec<_> = upvars
                     .into_iter()
                     .map(|upvar| {
-                        let upvar = this.hir.mirror(upvar);
                         match Category::of(&upvar.kind) {
                             // Use as_place to avoid creating a temporary when
                             // moving a variable into a closure, so that
@@ -190,7 +181,7 @@ fn expr_as_rvalue(
                             // This occurs when capturing by copy/move, while
                             // by reference captures use as_operand
                             Some(Category::Place) => {
-                                let place = unpack!(block = this.as_place(block, upvar));
+                                let place = unpack!(block = this.as_place(block, &upvar));
                                 this.consume_by_copy_or_move(place)
                             }
                             _ => {
@@ -198,17 +189,17 @@ fn expr_as_rvalue(
                                 // 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.kind {
                                     ExprKind::Borrow {
                                         borrow_kind:
                                             BorrowKind::Mut { allow_two_phase_borrow: false },
                                         arg,
                                     } => unpack!(
                                         block = this.limit_capture_mutability(
-                                            upvar.span, upvar.ty, scope, block, arg,
+                                            upvar.span, upvar.ty, scope, block, &arg,
                                         )
                                     ),
-                                    _ => unpack!(block = this.as_operand(block, scope, upvar)),
+                                    _ => unpack!(block = this.as_operand(block, scope, &upvar)),
                                 }
                             }
                         }
@@ -219,9 +210,9 @@ fn expr_as_rvalue(
                         // We implicitly set the discriminant to 0. See
                         // librustc_mir/transform/deaggregator.rs for details.
                         let movability = movability.unwrap();
-                        box AggregateKind::Generator(closure_id, substs, movability)
+                        box AggregateKind::Generator(*closure_id, substs, movability)
                     }
-                    UpvarSubsts::Closure(substs) => box AggregateKind::Closure(closure_id, substs),
+                    UpvarSubsts::Closure(substs) => box AggregateKind::Closure(*closure_id, substs),
                 };
                 block.and(Rvalue::Aggregate(result, operands))
             }
@@ -377,7 +368,7 @@ fn limit_capture_mutability(
         upvar_ty: Ty<'tcx>,
         temp_lifetime: Option<region::Scope>,
         mut block: BasicBlock,
-        arg: ExprRef<'tcx>,
+        arg: &Expr<'tcx>,
     ) -> BlockAnd<Operand<'tcx>> {
         let this = self;
 
index 9984b527ffdb4c00611c8e0b843f6ab5b25c072a..0f4d05fc03ab96974739380a5b1a81ecde52579c 100644 (file)
@@ -4,48 +4,42 @@
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::thir::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_hir as hir;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr` into a fresh temporary. This is used when building
     /// up rvalues so as to freeze the value that will be consumed.
-    crate fn as_temp<M>(
+    crate fn as_temp(
         &mut self,
         block: BasicBlock,
         temp_lifetime: Option<region::Scope>,
-        expr: M,
+        expr: &Expr<'tcx>,
         mutability: Mutability,
-    ) -> BlockAnd<Local>
-    where
-        M: Mirror<'tcx, Output = Expr<'tcx>>,
-    {
-        let expr = self.hir.mirror(expr);
-        //
+    ) -> 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.expr_as_temp(block, temp_lifetime, expr, mutability))
+        ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
     }
 
-    fn expr_as_temp(
+    fn as_temp_inner(
         &mut self,
         mut block: BasicBlock,
         temp_lifetime: Option<region::Scope>,
-        expr: Expr<'tcx>,
+        expr: &Expr<'tcx>,
         mutability: Mutability,
     ) -> BlockAnd<Local> {
         debug!(
-            "expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
+            "as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
             block, temp_lifetime, expr, mutability
         );
         let this = self;
 
         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| {
+        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, value, mutability)
             });
         }
@@ -89,7 +83,7 @@ fn expr_as_temp(
             // Don't bother with StorageLive and Dead for these temporaries,
             // they are never assigned.
             ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (),
-            ExprKind::Block { body: hir::Block { expr: None, targeted_by_break: false, .. } }
+            ExprKind::Block { body: Block { expr: None, targeted_by_break: false, .. } }
                 if expr_ty.is_never() => {}
             _ => {
                 this.cfg
@@ -114,7 +108,7 @@ fn expr_as_temp(
             }
         }
 
-        unpack!(block = this.into(temp_place, block, expr));
+        unpack!(block = this.expr_into_dest(temp_place, block, expr));
 
         if let Some(temp_lifetime) = temp_lifetime {
             this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value);
index 235fe14cbf9fdd3ed395c65d7fa0a12242828242..9c719e36551c41973f2c3b1324672fef415d8eaf 100644 (file)
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
-    crate fn into_expr(
+    crate fn expr_into_dest(
         &mut self,
         destination: Place<'tcx>,
         mut block: BasicBlock,
-        expr: Expr<'tcx>,
+        expr: &Expr<'tcx>,
     ) -> BlockAnd<()> {
-        debug!("into_expr(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
+        debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
 
         // since we frequently have to reference `self` from within a
         // closure, where `self` would be shadowed, it's easier to
@@ -35,24 +35,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             this.block_context.push(BlockFrame::SubExpr);
         }
 
-        let block_and = match expr.kind {
+        let block_and = match &expr.kind {
             ExprKind::Scope { region_scope, lint_level, value } => {
-                let region_scope = (region_scope, source_info);
+                let region_scope = (*region_scope, source_info);
                 ensure_sufficient_stack(|| {
-                    this.in_scope(region_scope, lint_level, |this| {
-                        this.into(destination, block, value)
+                    this.in_scope(region_scope, *lint_level, |this| {
+                        this.expr_into_dest(destination, block, &value)
                     })
                 })
             }
             ExprKind::Block { body: ast_block } => {
-                this.ast_block(destination, block, ast_block, source_info)
+                this.ast_block(destination, block, &ast_block, source_info)
             }
             ExprKind::Match { scrutinee, arms } => {
-                this.match_expr(destination, expr_span, block, scrutinee, arms)
+                this.match_expr(destination, expr_span, block, &scrutinee, &arms)
             }
             ExprKind::If { cond, then, else_opt } => {
                 let place = unpack!(
-                    block = this.as_temp(block, Some(this.local_scope()), cond, Mutability::Mut)
+                    block = this.as_temp(block, Some(this.local_scope()), &cond, Mutability::Mut)
                 );
                 let operand = Operand::Move(Place::from(place));
 
@@ -61,9 +61,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block);
                 this.cfg.terminate(block, source_info, term);
 
-                unpack!(then_block = this.into(destination, then_block, then));
+                unpack!(then_block = this.expr_into_dest(destination, then_block, &then));
                 else_block = if let Some(else_opt) = else_opt {
-                    unpack!(this.into(destination, else_block, else_opt))
+                    unpack!(this.expr_into_dest(destination, else_block, &else_opt))
                 } else {
                     // Body of the `if` expression without an `else` clause must return `()`, thus
                     // we implicitly generate a `else {}` if it is not specified.
@@ -87,14 +87,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 join_block.unit()
             }
             ExprKind::NeverToAny { source } => {
-                let source = this.hir.mirror(source);
                 let is_call =
                     matches!(source.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
@@ -127,7 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.cfg.start_new_block(),
                 );
 
-                let lhs = unpack!(block = this.as_local_operand(block, lhs));
+                let lhs = unpack!(block = this.as_local_operand(block, &lhs));
                 let blocks = match op {
                     LogicalOp::And => (else_block, false_block),
                     LogicalOp::Or => (true_block, else_block),
@@ -135,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1);
                 this.cfg.terminate(block, source_info, term);
 
-                let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs));
+                let rhs = unpack!(else_block = this.as_local_operand(else_block, &rhs));
                 let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block);
                 this.cfg.terminate(else_block, source_info, term);
 
@@ -188,7 +188,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.into(tmp, body_block, 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.
@@ -196,17 +196,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 })
             }
             ExprKind::Call { ty: _, fun, args, from_hir_call, fn_span } => {
-                let fun = unpack!(block = this.as_local_operand(block, fun));
+                let fun = unpack!(block = this.as_local_operand(block, &fun));
                 let args: Vec<_> = args
                     .into_iter()
-                    .map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
+                    .map(|arg| unpack!(block = this.as_local_call_operand(block, &arg)))
                     .collect();
 
                 let success = this.cfg.start_new_block();
 
                 this.record_operands_moved(&args);
 
-                debug!("into_expr: fn_span={:?}", fn_span);
+                debug!("expr_into_dest: fn_span={:?}", fn_span);
 
                 this.cfg.terminate(
                     block,
@@ -223,14 +223,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         } else {
                             Some((destination, success))
                         },
-                        from_hir_call,
-                        fn_span,
+                        from_hir_call: *from_hir_call,
+                        fn_span: *fn_span,
                     },
                 );
                 this.diverge_from(block);
                 success.unit()
             }
-            ExprKind::Use { source } => this.into(destination, block, source),
+            ExprKind::Use { source } => this.expr_into_dest(destination, block, &source),
             ExprKind::Borrow { arg, borrow_kind } => {
                 // We don't do this in `as_rvalue` because we use `as_place`
                 // for borrow expressions, so we cannot create an `RValue` that
@@ -238,20 +238,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // 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)),
-                    _ => unpack!(block = this.as_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.hir.tcx().lifetimes.re_erased, borrow_kind, arg_place);
+                    Rvalue::Ref(this.hir.tcx().lifetimes.re_erased, *borrow_kind, arg_place);
                 this.cfg.push_assign(block, source_info, destination, borrow);
                 block.unit()
             }
             ExprKind::AddressOf { mutability, arg } => {
                 let place = match mutability {
-                    hir::Mutability::Not => this.as_read_only_place(block, arg),
-                    hir::Mutability::Mut => this.as_place(block, arg),
+                    hir::Mutability::Not => this.as_read_only_place(block, &arg),
+                    hir::Mutability::Mut => this.as_place(block, &arg),
                 };
-                let address_of = Rvalue::AddressOf(mutability, unpack!(block = place));
+                let address_of = Rvalue::AddressOf(*mutability, unpack!(block = place));
                 this.cfg.push_assign(block, source_info, destination, address_of);
                 block.unit()
             }
@@ -267,13 +267,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // (evaluating them in order given by user)
                 let fields_map: FxHashMap<_, _> = fields
                     .into_iter()
-                    .map(|f| (f.name, unpack!(block = this.as_operand(block, Some(scope), f.expr))))
+                    .map(|f| {
+                        (f.name, unpack!(block = this.as_operand(block, Some(scope), &f.expr)))
+                    })
                     .collect();
 
-                let field_names = this.hir.all_fields(adt_def, variant_index);
+                let field_names = this.hir.all_fields(adt_def, *variant_index);
 
                 let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
-                    let place_builder = unpack!(block = this.as_place_builder(block, 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
@@ -307,7 +309,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 });
                 let adt = box AggregateKind::Adt(
                     adt_def,
-                    variant_index,
+                    *variant_index,
                     substs,
                     user_ty,
                     active_field_index,
@@ -327,21 +329,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .into_iter()
                     .map(|op| match op {
                         thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In {
-                            reg,
-                            value: unpack!(block = this.as_local_operand(block, expr)),
+                            reg: *reg,
+                            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, expr))),
+                                reg: *reg,
+                                late: *late,
+                                place: expr
+                                    .as_ref()
+                                    .map(|expr| unpack!(block = this.as_place(block, expr))),
                             }
                         }
                         thir::InlineAsmOperand::InOut { reg, late, expr } => {
-                            let place = unpack!(block = this.as_place(block, expr));
+                            let place = unpack!(block = this.as_place(block, &expr));
                             mir::InlineAsmOperand::InOut {
-                                reg,
-                                late,
+                                reg: *reg,
+                                late: *late,
                                 // This works because asm operands must be Copy
                                 in_value: Operand::Copy(place),
                                 out_place: Some(place),
@@ -349,22 +353,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         }
                         thir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
                             mir::InlineAsmOperand::InOut {
-                                reg,
-                                late,
-                                in_value: unpack!(block = this.as_local_operand(block, in_expr)),
-                                out_place: out_expr.map(|out_expr| {
+                                reg: *reg,
+                                late: *late,
+                                in_value: unpack!(block = this.as_local_operand(block, &in_expr)),
+                                out_place: out_expr.as_ref().map(|out_expr| {
                                     unpack!(block = this.as_place(block, out_expr))
                                 }),
                             }
                         }
                         thir::InlineAsmOperand::Const { expr } => mir::InlineAsmOperand::Const {
-                            value: unpack!(block = this.as_local_operand(block, expr)),
+                            value: unpack!(block = this.as_local_operand(block, &expr)),
                         },
                         thir::InlineAsmOperand::SymFn { expr } => {
-                            mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) }
+                            mir::InlineAsmOperand::SymFn { value: box this.as_constant(&expr) }
                         }
                         thir::InlineAsmOperand::SymStatic { def_id } => {
-                            mir::InlineAsmOperand::SymStatic { def_id }
+                            mir::InlineAsmOperand::SymStatic { def_id: *def_id }
                         }
                     })
                     .collect();
@@ -377,7 +381,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     TerminatorKind::InlineAsm {
                         template,
                         operands,
-                        options,
+                        options: *options,
                         line_spans,
                         destination: if options.contains(InlineAsmOptions::NORETURN) {
                             None
@@ -436,7 +440,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             ExprKind::Yield { value } => {
                 let scope = this.local_scope();
-                let value = unpack!(block = this.as_operand(block, Some(scope), value));
+                let value = unpack!(block = this.as_operand(block, Some(scope), &value));
                 let resume = this.cfg.start_new_block();
                 this.cfg.terminate(
                     block,
index ac8c7e725e1b4190a1a075935422993e013cc9bc..07338928eb8efa777ae72103a4f640f461d05848 100644 (file)
@@ -9,7 +9,7 @@
 //! a type that is not `Copy`, then using any of these functions will
 //! "move" the value out of its current home (if any).
 //!
-//! - `into` -- writes the value into a specific location, which
+//! - `expr_into_dest` -- writes the value into a specific location, which
 //!   should be uninitialized
 //! - `as_operand` -- evaluates the value and yields an `Operand`,
 //!   suitable for use as an argument to an `Rvalue`
index f117689d940fd7a210183b1d0a526c8032912d46..0d2d99a8b5e87915013b39ecf6e70e16f7185468 100644 (file)
@@ -13,7 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     crate fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
-        expr: Expr<'tcx>,
+        expr: &Expr<'tcx>,
         statement_scope: Option<region::Scope>,
     ) -> BlockAnd<()> {
         let this = self;
@@ -22,16 +22,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Handle a number of expressions that don't need a destination at all. This
         // avoids needing a mountain of temporary `()` variables.
         let expr2 = expr.clone();
-        match expr.kind {
+        match &expr.kind {
             ExprKind::Scope { region_scope, lint_level, value } => {
-                let value = this.hir.mirror(value);
-                this.in_scope((region_scope, source_info), lint_level, |this| {
-                    this.stmt_expr(block, value, statement_scope)
+                this.in_scope((*region_scope, source_info), *lint_level, |this| {
+                    this.stmt_expr(block, &value, statement_scope)
                 })
             }
             ExprKind::Assign { lhs, rhs } => {
-                let lhs = this.hir.mirror(lhs);
-                let rhs = this.hir.mirror(rhs);
                 let lhs_span = lhs.span;
 
                 // Note: we evaluate assignments right-to-left. This
@@ -44,12 +41,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // Generate better code for things that don't need to be
                 // dropped.
                 if this.hir.needs_drop(lhs.ty) {
-                    let rhs = unpack!(block = this.as_local_operand(block, rhs));
-                    let lhs = unpack!(block = this.as_place(block, lhs));
+                    let rhs = unpack!(block = this.as_local_operand(block, &rhs));
+                    let lhs = unpack!(block = this.as_place(block, &lhs));
                     unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
                 } else {
-                    let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
-                    let lhs = unpack!(block = this.as_place(block, lhs));
+                    let rhs = unpack!(block = this.as_local_rvalue(block, &rhs));
+                    let lhs = unpack!(block = this.as_place(block, &lhs));
                     this.cfg.push_assign(block, source_info, lhs, rhs);
                 }
 
@@ -65,22 +62,27 @@ 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.hir.mirror(lhs);
                 let lhs_ty = lhs.ty;
 
                 debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr2);
                 this.block_context.push(BlockFrame::SubExpr);
 
                 // As above, RTL.
-                let rhs = unpack!(block = this.as_local_operand(block, rhs));
-                let lhs = unpack!(block = this.as_place(block, lhs));
+                let rhs = unpack!(block = this.as_local_operand(block, &rhs));
+                let lhs = unpack!(block = this.as_place(block, &lhs));
 
                 // we don't have to drop prior contents or anything
                 // because AssignOp is only legal for Copy types
                 // (overloaded ops should be desugared into a call).
                 let result = unpack!(
-                    block =
-                        this.build_binary_op(block, op, expr_span, lhs_ty, Operand::Copy(lhs), rhs)
+                    block = this.build_binary_op(
+                        block,
+                        *op,
+                        expr_span,
+                        lhs_ty,
+                        Operand::Copy(lhs),
+                        rhs
+                    )
                 );
                 this.cfg.push_assign(block, source_info, lhs, result);
 
@@ -88,26 +90,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.unit()
             }
             ExprKind::Continue { label } => {
-                this.break_scope(block, None, BreakableTarget::Continue(label), source_info)
-            }
-            ExprKind::Break { label, value } => {
-                this.break_scope(block, value, BreakableTarget::Break(label), source_info)
+                this.break_scope(block, None, BreakableTarget::Continue(*label), source_info)
             }
+            ExprKind::Break { label, value } => this.break_scope(
+                block,
+                value.as_deref(),
+                BreakableTarget::Break(*label),
+                source_info,
+            ),
             ExprKind::Return { value } => {
-                this.break_scope(block, value, BreakableTarget::Return, source_info)
+                this.break_scope(block, value.as_deref(), BreakableTarget::Return, source_info)
             }
             ExprKind::LlvmInlineAsm { asm, outputs, inputs } => {
                 debug!("stmt_expr LlvmInlineAsm block_context.push(SubExpr) : {:?}", expr2);
                 this.block_context.push(BlockFrame::SubExpr);
                 let outputs = outputs
                     .into_iter()
-                    .map(|output| unpack!(block = this.as_place(block, output)))
+                    .map(|output| unpack!(block = this.as_place(block, &output)))
                     .collect::<Vec<_>>()
                     .into_boxed_slice();
                 let inputs = inputs
                     .into_iter()
                     .map(|input| {
-                        (input.span(), unpack!(block = this.as_local_operand(block, input)))
+                        (input.span, unpack!(block = this.as_local_operand(block, &input)))
                     })
                     .collect::<Vec<_>>()
                     .into_boxed_slice();
@@ -116,7 +121,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Statement {
                         source_info,
                         kind: StatementKind::LlvmInlineAsm(box LlvmInlineAsm {
-                            asm: asm.clone(),
+                            asm: (*asm).clone(),
                             outputs,
                             inputs,
                         }),
@@ -140,10 +145,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // it is usually better to focus on `the_value` rather
                 // than the entirety of block(s) surrounding it.
                 let adjusted_span = (|| {
-                    if let ExprKind::Block { body } = expr.kind {
+                    if let ExprKind::Block { body } = &expr.kind {
                         if let Some(tail_expr) = &body.expr {
-                            let mut expr = tail_expr;
-                            while let rustc_hir::ExprKind::Block(subblock, _label) = &expr.kind {
+                            let mut expr = &*tail_expr;
+                            while let ExprKind::Block { body: subblock } = &expr.kind {
                                 if let Some(subtail_expr) = &subblock.expr {
                                     expr = subtail_expr
                                 } else {
diff --git a/compiler/rustc_mir_build/src/build/into.rs b/compiler/rustc_mir_build/src/build/into.rs
deleted file mode 100644 (file)
index 7264e49..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-//! In general, there are a number of things for which it's convenient
-//! to just call `builder.into` and have it emit its result into a
-//! given location. This is basically for expressions or things that can be
-//! wrapped up as expressions (e.g., blocks). To make this ergonomic, we use this
-//! latter `EvalInto` trait.
-
-use crate::build::{BlockAnd, Builder};
-use crate::thir::*;
-use rustc_middle::mir::*;
-
-pub(in crate::build) trait EvalInto<'tcx> {
-    fn eval_into(
-        self,
-        builder: &mut Builder<'_, 'tcx>,
-        destination: Place<'tcx>,
-        block: BasicBlock,
-    ) -> BlockAnd<()>;
-}
-
-impl<'a, 'tcx> Builder<'a, 'tcx> {
-    crate fn into<E>(
-        &mut self,
-        destination: Place<'tcx>,
-        block: BasicBlock,
-        expr: E,
-    ) -> BlockAnd<()>
-    where
-        E: EvalInto<'tcx>,
-    {
-        expr.eval_into(self, destination, block)
-    }
-}
-
-impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
-    fn eval_into(
-        self,
-        builder: &mut Builder<'_, 'tcx>,
-        destination: Place<'tcx>,
-        block: BasicBlock,
-    ) -> BlockAnd<()> {
-        let expr = builder.hir.mirror(self);
-        builder.into_expr(destination, block, expr)
-    }
-}
-
-impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
-    fn eval_into(
-        self,
-        builder: &mut Builder<'_, 'tcx>,
-        destination: Place<'tcx>,
-        block: BasicBlock,
-    ) -> BlockAnd<()> {
-        builder.into_expr(destination, block, self)
-    }
-}
index fde007ec011bae21348890a40dd259b8c1cd88ba..6a828c1864fc9aad7a770681518b97a64dbe13ac 100644 (file)
@@ -89,10 +89,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         destination: Place<'tcx>,
         span: Span,
         mut block: BasicBlock,
-        scrutinee: ExprRef<'tcx>,
-        arms: Vec<Arm<'tcx>>,
+        scrutinee: &Expr<'tcx>,
+        arms: &[Arm<'tcx>],
     ) -> BlockAnd<()> {
-        let scrutinee_span = scrutinee.span();
+        let scrutinee_span = scrutinee.span;
         let scrutinee_place =
             unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
 
@@ -119,7 +119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn lower_scrutinee(
         &mut self,
         mut block: BasicBlock,
-        scrutinee: ExprRef<'tcx>,
+        scrutinee: &Expr<'tcx>,
         scrutinee_span: Span,
     ) -> BlockAnd<Place<'tcx>> {
         let scrutinee_place = unpack!(block = self.as_place(block, scrutinee));
@@ -236,7 +236,6 @@ fn lower_match_arms(
                 let arm_source_info = self.source_info(arm.span);
                 let arm_scope = (arm.scope, arm_source_info);
                 self.in_scope(arm_scope, arm.lint_level, |this| {
-                    let body = this.hir.mirror(arm.body.clone());
                     let scope = this.declare_bindings(
                         None,
                         arm.span,
@@ -259,7 +258,7 @@ fn lower_match_arms(
                         this.source_scope = source_scope;
                     }
 
-                    this.into(destination, arm_block, body)
+                    this.expr_into_dest(destination, arm_block, &arm.body)
                 })
             })
             .collect();
@@ -362,14 +361,14 @@ pub(super) fn expr_into_pattern(
         &mut self,
         mut block: BasicBlock,
         irrefutable_pat: Pat<'tcx>,
-        initializer: ExprRef<'tcx>,
+        initializer: &Expr<'tcx>,
     ) -> 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.into(place, block, initializer));
+                unpack!(block = self.expr_into_dest(place, block, initializer));
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let source_info = self.source_info(irrefutable_pat.span);
@@ -404,7 +403,7 @@ pub(super) fn expr_into_pattern(
             } => {
                 let place =
                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true);
-                unpack!(block = self.into(place, block, initializer));
+                unpack!(block = self.expr_into_dest(place, block, initializer));
 
                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
                 let pattern_source_info = self.source_info(irrefutable_pat.span);
@@ -1749,15 +1748,13 @@ fn bind_and_guard_matched_candidate<'pat>(
 
             let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match guard {
                 Guard::If(e) => {
-                    let e = self.hir.mirror(e.clone());
                     let source_info = self.source_info(e.span);
                     (e.span, self.test_bool(block, e, source_info))
                 }
                 Guard::IfLet(pat, scrutinee) => {
-                    let scrutinee_span = scrutinee.span();
-                    let scrutinee_place = unpack!(
-                        block = self.lower_scrutinee(block, scrutinee.clone(), scrutinee_span)
-                    );
+                    let scrutinee_span = scrutinee.span;
+                    let scrutinee_place =
+                        unpack!(block = self.lower_scrutinee(block, &scrutinee, scrutinee_span));
                     let mut guard_candidate = Candidate::new(scrutinee_place, &pat, false);
                     let wildcard = Pat::wildcard_from_ty(pat.ty);
                     let mut otherwise_candidate = Candidate::new(scrutinee_place, &wildcard, false);
@@ -1772,14 +1769,14 @@ fn bind_and_guard_matched_candidate<'pat>(
                         pat.span.to(arm_span.unwrap()),
                         pat,
                         ArmHasGuard(false),
-                        Some((Some(&scrutinee_place), scrutinee.span())),
+                        Some((Some(&scrutinee_place), scrutinee.span)),
                     );
                     let post_guard_block = self.bind_pattern(
                         self.source_info(pat.span),
                         guard_candidate,
                         None,
                         &fake_borrow_temps,
-                        scrutinee.span(),
+                        scrutinee.span,
                         None,
                         None,
                     );
index b928458df8ee41c809e2dc42fa997c1b72ae78e1..f9bed4454f2ede28c59417a2cb5168fcf8b04d02 100644 (file)
@@ -667,8 +667,8 @@ fn construct_const<'a, 'tcx>(
 
     let mut block = START_BLOCK;
     let ast_expr = &tcx.hir().body(body_id).value;
-    let expr = builder.hir.mirror(ast_expr);
-    unpack!(block = builder.into_expr(Place::return_place(), block, expr));
+    let expr = builder.hir.mirror_expr(ast_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);
@@ -953,8 +953,8 @@ fn args_and_body(
             self.source_scope = source_scope;
         }
 
-        let body = self.hir.mirror(ast_body);
-        self.into(Place::return_place(), block, body)
+        let body = self.hir.mirror_expr(ast_body);
+        self.expr_into_dest(Place::return_place(), block, &body)
     }
 
     fn set_correct_source_scope_for_arg(
@@ -1001,7 +1001,6 @@ fn get_unit_temp(&mut self) -> Place<'tcx> {
 mod block;
 mod cfg;
 mod expr;
-mod into;
 mod matches;
 mod misc;
 mod scope;
index 5e9d780d1797752d17fd8e4ea671bff61435746c..fccff023d0872a6e0d11443f69cc4865bdf9b709 100644 (file)
@@ -82,7 +82,7 @@
 */
 
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
-use crate::thir::{Expr, ExprRef, LintLevel};
+use crate::thir::{Expr, LintLevel};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::vec::IndexVec;
 use rustc_middle::middle::region;
@@ -575,7 +575,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     crate fn break_scope(
         &mut self,
         mut block: BasicBlock,
-        value: Option<ExprRef<'tcx>>,
+        value: Option<&Expr<'tcx>>,
         target: BreakableTarget,
         source_info: SourceInfo,
     ) -> BlockAnd<()> {
@@ -612,7 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             if let Some(value) = value {
                 debug!("stmt_expr Break val block_context.push(SubExpr)");
                 self.block_context.push(BlockFrame::SubExpr);
-                unpack!(block = self.into(destination, block, value));
+                unpack!(block = self.expr_into_dest(destination, block, value));
                 self.block_context.pop();
             } else {
                 self.cfg.push_assign_unit(block, source_info, destination, self.hir.tcx())
@@ -920,7 +920,7 @@ fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
     crate fn test_bool(
         &mut self,
         mut block: BasicBlock,
-        condition: Expr<'tcx>,
+        condition: &Expr<'tcx>,
         source_info: SourceInfo,
     ) -> (BasicBlock, BasicBlock) {
         let cond = unpack!(block = self.as_local_operand(block, condition));
index 980888df7fee41242285ca1224f14dcfa26d814b..9c1440aba4204487a448a92a7bd0ffbc06f8693b 100644 (file)
@@ -1,4 +1,3 @@
-use crate::thir::cx::to_ref::ToRef;
 use crate::thir::cx::Cx;
 use crate::thir::{self, *};
 
 
 use rustc_index::vec::Idx;
 
-impl<'tcx> Mirror<'tcx> for &'tcx hir::Block<'tcx> {
-    type Output = Block<'tcx>;
-
-    fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Block<'tcx> {
+impl<'a, 'tcx> Cx<'a, 'tcx> {
+    crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'tcx> {
         // We have to eagerly lower the "spine" of the statements
         // in order to get the lexical scoping correctly.
-        let stmts = mirror_stmts(cx, self.hir_id.local_id, &*self.stmts);
+        let stmts = self.mirror_stmts(block.hir_id.local_id, &*block.stmts);
         let opt_destruction_scope =
-            cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id);
+            self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id);
         Block {
-            targeted_by_break: self.targeted_by_break,
-            region_scope: region::Scope { id: self.hir_id.local_id, data: region::ScopeData::Node },
+            targeted_by_break: block.targeted_by_break,
+            region_scope: region::Scope {
+                id: block.hir_id.local_id,
+                data: region::ScopeData::Node,
+            },
             opt_destruction_scope,
-            span: self.span,
+            span: block.span,
             stmts,
-            expr: self.expr.to_ref(),
-            safety_mode: match self.rules {
+            expr: block.expr.as_ref().map(|expr| self.mirror_expr_boxed(expr)),
+            safety_mode: match block.rules {
                 hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
-                hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(self.hir_id),
+                hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id),
                 hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe,
                 hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe,
             },
         }
     }
-}
 
-fn mirror_stmts<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    block_id: hir::ItemLocalId,
-    stmts: &'tcx [hir::Stmt<'tcx>],
-) -> Vec<StmtRef<'tcx>> {
-    let mut result = vec![];
-    for (index, stmt) in stmts.iter().enumerate() {
-        let hir_id = stmt.hir_id;
-        let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
-        match stmt.kind {
-            hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
-                result.push(StmtRef::Mirror(Box::new(Stmt {
-                    kind: StmtKind::Expr {
-                        scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node },
-                        expr: expr.to_ref(),
-                    },
-                    opt_destruction_scope: opt_dxn_ext,
-                })))
-            }
-            hir::StmtKind::Item(..) => {
-                // ignore for purposes of the MIR
-            }
-            hir::StmtKind::Local(ref local) => {
-                let remainder_scope = region::Scope {
-                    id: block_id,
-                    data: region::ScopeData::Remainder(region::FirstStatementIndex::new(index)),
-                };
+    fn mirror_stmts(
+        &mut self,
+        block_id: hir::ItemLocalId,
+        stmts: &'tcx [hir::Stmt<'tcx>],
+    ) -> Vec<Stmt<'tcx>> {
+        let mut result = vec![];
+        for (index, stmt) in stmts.iter().enumerate() {
+            let hir_id = stmt.hir_id;
+            let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id);
+            match stmt.kind {
+                hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
+                    result.push(Stmt {
+                        kind: StmtKind::Expr {
+                            scope: region::Scope {
+                                id: hir_id.local_id,
+                                data: region::ScopeData::Node,
+                            },
+                            expr: self.mirror_expr_boxed(expr),
+                        },
+                        opt_destruction_scope: opt_dxn_ext,
+                    })
+                }
+                hir::StmtKind::Item(..) => {
+                    // ignore for purposes of the MIR
+                }
+                hir::StmtKind::Local(ref local) => {
+                    let remainder_scope = region::Scope {
+                        id: block_id,
+                        data: region::ScopeData::Remainder(region::FirstStatementIndex::new(index)),
+                    };
 
-                let mut pattern = cx.pattern_from_hir(&local.pat);
+                    let mut pattern = self.pattern_from_hir(&local.pat);
 
-                if let Some(ty) = &local.ty {
-                    if let Some(&user_ty) = cx.typeck_results.user_provided_types().get(ty.hir_id) {
-                        debug!("mirror_stmts: user_ty={:?}", user_ty);
-                        pattern = Pat {
-                            ty: pattern.ty,
-                            span: pattern.span,
-                            kind: Box::new(PatKind::AscribeUserType {
-                                ascription: thir::pattern::Ascription {
-                                    user_ty: PatTyProj::from_user_type(user_ty),
-                                    user_ty_span: ty.span,
-                                    variance: ty::Variance::Covariant,
-                                },
-                                subpattern: pattern,
-                            }),
-                        };
+                    if let Some(ty) = &local.ty {
+                        if let Some(&user_ty) =
+                            self.typeck_results.user_provided_types().get(ty.hir_id)
+                        {
+                            debug!("mirror_stmts: user_ty={:?}", user_ty);
+                            pattern = Pat {
+                                ty: pattern.ty,
+                                span: pattern.span,
+                                kind: Box::new(PatKind::AscribeUserType {
+                                    ascription: thir::pattern::Ascription {
+                                        user_ty: PatTyProj::from_user_type(user_ty),
+                                        user_ty_span: ty.span,
+                                        variance: ty::Variance::Covariant,
+                                    },
+                                    subpattern: pattern,
+                                }),
+                            };
+                        }
                     }
-                }
 
-                result.push(StmtRef::Mirror(Box::new(Stmt {
-                    kind: StmtKind::Let {
-                        remainder_scope,
-                        init_scope: region::Scope {
-                            id: hir_id.local_id,
-                            data: region::ScopeData::Node,
+                    result.push(Stmt {
+                        kind: StmtKind::Let {
+                            remainder_scope,
+                            init_scope: region::Scope {
+                                id: hir_id.local_id,
+                                data: region::ScopeData::Node,
+                            },
+                            pattern,
+                            initializer: local.init.map(|init| self.mirror_expr_boxed(init)),
+                            lint_level: LintLevel::Explicit(local.hir_id),
                         },
-                        pattern,
-                        initializer: local.init.to_ref(),
-                        lint_level: LintLevel::Explicit(local.hir_id),
-                    },
-                    opt_destruction_scope: opt_dxn_ext,
-                })));
+                        opt_destruction_scope: opt_dxn_ext,
+                    });
+                }
             }
         }
+        result
     }
-    result
-}
-
-crate fn to_expr_ref<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    block: &'tcx hir::Block<'tcx>,
-) -> ExprRef<'tcx> {
-    let block_ty = cx.typeck_results().node_type(block.hir_id);
-    let temp_lifetime = cx.region_scope_tree.temporary_scope(block.hir_id.local_id);
-    let expr = Expr {
-        ty: block_ty,
-        temp_lifetime,
-        span: block.span,
-        kind: ExprKind::Block { body: block },
-    };
-    expr.to_ref()
 }
index 620ce360e7d9122d8a64bc08257f8b0ad12952f2..cd5e73a45cd59bb2d2390b0e739e82c5b14fa7cf 100644 (file)
@@ -1,5 +1,3 @@
-use crate::thir::cx::block;
-use crate::thir::cx::to_ref::ToRef;
 use crate::thir::cx::Cx;
 use crate::thir::util::UserAnnotatedTyHelpers;
 use crate::thir::*;
 use rustc_middle::ty::{self, AdtKind, Ty};
 use rustc_span::Span;
 
-impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr<'tcx> {
-    type Output = Expr<'tcx>;
+impl<'a, 'tcx> Cx<'a, 'tcx> {
+    crate fn mirror_expr(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
+        let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id);
+        let expr_scope =
+            region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
 
-    fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
-        let temp_lifetime = cx.region_scope_tree.temporary_scope(self.hir_id.local_id);
-        let expr_scope = region::Scope { id: self.hir_id.local_id, data: region::ScopeData::Node };
+        debug!("Expr::make_mirror(): id={}, span={:?}", hir_expr.hir_id, hir_expr.span);
 
-        debug!("Expr::make_mirror(): id={}, span={:?}", self.hir_id, self.span);
-
-        let mut expr = make_mirror_unadjusted(cx, self);
+        let mut expr = self.make_mirror_unadjusted(hir_expr);
 
         // Now apply adjustments, if any.
-        for adjustment in cx.typeck_results().expr_adjustments(self) {
+        for adjustment in self.typeck_results().expr_adjustments(hir_expr) {
             debug!("make_mirror: expr={:?} applying adjustment={:?}", expr, adjustment);
-            expr = apply_adjustment(cx, self, expr, adjustment);
+            expr = self.apply_adjustment(hir_expr, expr, adjustment);
         }
 
         // Next, wrap this up in the expr's scope.
         expr = Expr {
             temp_lifetime,
             ty: expr.ty,
-            span: self.span,
+            span: hir_expr.span,
             kind: ExprKind::Scope {
                 region_scope: expr_scope,
-                value: expr.to_ref(),
-                lint_level: LintLevel::Explicit(self.hir_id),
+                value: Box::new(expr),
+                lint_level: LintLevel::Explicit(hir_expr.hir_id),
             },
         };
 
         // Finally, create a destruction scope, if any.
-        if let Some(region_scope) = cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id)
+        if let Some(region_scope) =
+            self.region_scope_tree.opt_destruction_scope(hir_expr.hir_id.local_id)
         {
             expr = Expr {
                 temp_lifetime,
                 ty: expr.ty,
-                span: self.span,
+                span: hir_expr.span,
                 kind: ExprKind::Scope {
                     region_scope,
-                    value: expr.to_ref(),
+                    value: Box::new(expr),
                     lint_level: LintLevel::Inherited,
                 },
             };
@@ -64,687 +62,997 @@ fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
         // OK, all done!
         expr
     }
-}
-
-fn apply_adjustment<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    hir_expr: &'tcx hir::Expr<'tcx>,
-    mut expr: Expr<'tcx>,
-    adjustment: &Adjustment<'tcx>,
-) -> Expr<'tcx> {
-    let Expr { temp_lifetime, mut span, .. } = expr;
-
-    // Adjust the span from the block, to the last expression of the
-    // block. This is a better span when returning a mutable reference
-    // with too short a lifetime. The error message will use the span
-    // from the assignment to the return place, which should only point
-    // at the returned value, not the entire function body.
-    //
-    // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
-    //      x
-    //   // ^ error message points at this expression.
-    // }
-    let mut adjust_span = |expr: &mut Expr<'tcx>| {
-        if let ExprKind::Block { body } = expr.kind {
-            if let Some(ref last_expr) = body.expr {
-                span = last_expr.span;
-                expr.span = span;
-            }
-        }
-    };
 
-    let kind = match adjustment.kind {
-        Adjust::Pointer(PointerCast::Unsize) => {
-            adjust_span(&mut expr);
-            ExprKind::Pointer { cast: PointerCast::Unsize, source: expr.to_ref() }
-        }
-        Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: expr.to_ref() },
-        Adjust::NeverToAny => ExprKind::NeverToAny { source: expr.to_ref() },
-        Adjust::Deref(None) => {
-            adjust_span(&mut expr);
-            ExprKind::Deref { arg: expr.to_ref() }
-        }
-        Adjust::Deref(Some(deref)) => {
-            // We don't need to do call adjust_span here since
-            // deref coercions always start with a built-in deref.
-            let call = deref.method_call(cx.tcx(), expr.ty);
-
-            expr = Expr {
-                temp_lifetime,
-                ty: cx.tcx.mk_ref(deref.region, ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }),
-                span,
-                kind: ExprKind::Borrow {
-                    borrow_kind: deref.mutbl.to_borrow_kind(),
-                    arg: expr.to_ref(),
-                },
-            };
+    crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Vec<Expr<'tcx>> {
+        exprs.iter().map(|expr| self.mirror_expr(expr)).collect()
+    }
 
-            overloaded_place(
-                cx,
-                hir_expr,
-                adjustment.target,
-                Some(call),
-                vec![expr.to_ref()],
-                deref.span,
-            )
-        }
-        Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
-            ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: expr.to_ref() }
-        }
-        Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
-            ExprKind::AddressOf { mutability, arg: expr.to_ref() }
-        }
-    };
+    crate fn mirror_expr_boxed(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Box<Expr<'tcx>> {
+        Box::new(self.mirror_expr(expr))
+    }
 
-    Expr { temp_lifetime, ty: adjustment.target, span, kind }
-}
+    fn apply_adjustment(
+        &mut self,
+        hir_expr: &'tcx hir::Expr<'tcx>,
+        mut expr: Expr<'tcx>,
+        adjustment: &Adjustment<'tcx>,
+    ) -> Expr<'tcx> {
+        let Expr { temp_lifetime, mut span, .. } = expr;
+
+        // Adjust the span from the block, to the last expression of the
+        // block. This is a better span when returning a mutable reference
+        // with too short a lifetime. The error message will use the span
+        // from the assignment to the return place, which should only point
+        // at the returned value, not the entire function body.
+        //
+        // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 {
+        //      x
+        //   // ^ error message points at this expression.
+        // }
+        let mut adjust_span = |expr: &mut Expr<'tcx>| {
+            if let ExprKind::Block { body } = &expr.kind {
+                if let Some(ref last_expr) = body.expr {
+                    span = last_expr.span;
+                    expr.span = span;
+                }
+            }
+        };
 
-fn make_mirror_unadjusted<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    expr: &'tcx hir::Expr<'tcx>,
-) -> Expr<'tcx> {
-    let expr_ty = cx.typeck_results().expr_ty(expr);
-    let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-
-    let kind = match expr.kind {
-        // Here comes the interesting stuff:
-        hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => {
-            // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
-            let expr = method_callee(cx, expr, method_span, None);
-            let args = args.iter().map(|e| e.to_ref()).collect();
-            ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true, fn_span }
-        }
+        let kind = match adjustment.kind {
+            Adjust::Pointer(PointerCast::Unsize) => {
+                adjust_span(&mut expr);
+                ExprKind::Pointer { cast: PointerCast::Unsize, source: Box::new(expr) }
+            }
+            Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: Box::new(expr) },
+            Adjust::NeverToAny => ExprKind::NeverToAny { source: Box::new(expr) },
+            Adjust::Deref(None) => {
+                adjust_span(&mut expr);
+                ExprKind::Deref { arg: Box::new(expr) }
+            }
+            Adjust::Deref(Some(deref)) => {
+                // We don't need to do call adjust_span here since
+                // deref coercions always start with a built-in deref.
+                let call = deref.method_call(self.tcx(), expr.ty);
 
-        hir::ExprKind::Call(ref fun, ref args) => {
-            if cx.typeck_results().is_method_call(expr) {
-                // The callee is something implementing Fn, FnMut, or FnOnce.
-                // Find the actual method implementation being called and
-                // build the appropriate UFCS call expression with the
-                // callee-object as expr parameter.
+                expr = Expr {
+                    temp_lifetime,
+                    ty: self
+                        .tcx
+                        .mk_ref(deref.region, ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }),
+                    span,
+                    kind: ExprKind::Borrow {
+                        borrow_kind: deref.mutbl.to_borrow_kind(),
+                        arg: Box::new(expr),
+                    },
+                };
 
-                // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
+                self.overloaded_place(
+                    hir_expr,
+                    adjustment.target,
+                    Some(call),
+                    vec![expr],
+                    deref.span,
+                )
+            }
+            Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
+                ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: Box::new(expr) }
+            }
+            Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
+                ExprKind::AddressOf { mutability, arg: Box::new(expr) }
+            }
+        };
 
-                let method = method_callee(cx, expr, fun.span, None);
+        Expr { temp_lifetime, ty: adjustment.target, span, kind }
+    }
 
-                let arg_tys = args.iter().map(|e| cx.typeck_results().expr_ty_adjusted(e));
-                let tupled_args = Expr {
-                    ty: cx.tcx.mk_tup(arg_tys),
-                    temp_lifetime,
-                    span: expr.span,
-                    kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() },
-                };
+    fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
+        let expr_ty = self.typeck_results().expr_ty(expr);
+        let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
 
+        let kind = match expr.kind {
+            // Here comes the interesting stuff:
+            hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => {
+                // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
+                let expr = self.method_callee(expr, method_span, None);
+                let args = self.mirror_exprs(args);
                 ExprKind::Call {
-                    ty: method.ty,
-                    fun: method.to_ref(),
-                    args: vec![fun.to_ref(), tupled_args.to_ref()],
+                    ty: expr.ty,
+                    fun: Box::new(expr),
+                    args,
                     from_hir_call: true,
-                    fn_span: expr.span,
+                    fn_span,
                 }
-            } else {
-                let adt_data =
-                    if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
-                        // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
-                        expr_ty.ty_adt_def().and_then(|adt_def| match path.res {
-                            Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => {
-                                Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
-                            }
-                            Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
-                            _ => None,
-                        })
-                    } else {
-                        None
+            }
+
+            hir::ExprKind::Call(ref fun, ref args) => {
+                if self.typeck_results().is_method_call(expr) {
+                    // The callee is something implementing Fn, FnMut, or FnOnce.
+                    // Find the actual method implementation being called and
+                    // build the appropriate UFCS call expression with the
+                    // callee-object as expr parameter.
+
+                    // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
+
+                    let method = self.method_callee(expr, fun.span, None);
+
+                    let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e));
+                    let tupled_args = Expr {
+                        ty: self.tcx.mk_tup(arg_tys),
+                        temp_lifetime,
+                        span: expr.span,
+                        kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
                     };
-                if let Some((adt_def, index)) = adt_data {
-                    let substs = cx.typeck_results().node_substs(fun.hir_id);
-                    let user_provided_types = cx.typeck_results().user_provided_types();
-                    let user_ty = user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
-                        if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
-                            *did = adt_def.did;
-                        }
-                        u_ty
-                    });
-                    debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
-
-                    let field_refs = args
-                        .iter()
-                        .enumerate()
-                        .map(|(idx, e)| FieldExprRef { name: Field::new(idx), expr: e.to_ref() })
-                        .collect();
-                    ExprKind::Adt {
-                        adt_def,
-                        substs,
-                        variant_index: index,
-                        fields: field_refs,
-                        user_ty,
-                        base: None,
-                    }
-                } else {
+
                     ExprKind::Call {
-                        ty: cx.typeck_results().node_type(fun.hir_id),
-                        fun: fun.to_ref(),
-                        args: args.to_ref(),
+                        ty: method.ty,
+                        fun: Box::new(method),
+                        args: vec![self.mirror_expr(fun), tupled_args],
                         from_hir_call: true,
                         fn_span: expr.span,
                     }
+                } else {
+                    let adt_data =
+                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
+                            // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
+                            expr_ty.ty_adt_def().and_then(|adt_def| match path.res {
+                                Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => {
+                                    Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id)))
+                                }
+                                Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
+                                _ => None,
+                            })
+                        } else {
+                            None
+                        };
+                    if let Some((adt_def, index)) = adt_data {
+                        let substs = self.typeck_results().node_substs(fun.hir_id);
+                        let user_provided_types = self.typeck_results().user_provided_types();
+                        let user_ty =
+                            user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| {
+                                if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value {
+                                    *did = adt_def.did;
+                                }
+                                u_ty
+                            });
+                        debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
+
+                        let field_refs = args
+                            .iter()
+                            .enumerate()
+                            .map(|(idx, e)| FieldExpr {
+                                name: Field::new(idx),
+                                expr: self.mirror_expr(e),
+                            })
+                            .collect();
+                        ExprKind::Adt {
+                            adt_def,
+                            substs,
+                            variant_index: index,
+                            fields: field_refs,
+                            user_ty,
+                            base: None,
+                        }
+                    } else {
+                        ExprKind::Call {
+                            ty: self.typeck_results().node_type(fun.hir_id),
+                            fun: self.mirror_expr_boxed(fun),
+                            args: self.mirror_exprs(args),
+                            from_hir_call: true,
+                            fn_span: expr.span,
+                        }
+                    }
                 }
             }
-        }
 
-        hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => {
-            ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: arg.to_ref() }
-        }
+            hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => ExprKind::Borrow {
+                borrow_kind: mutbl.to_borrow_kind(),
+                arg: self.mirror_expr_boxed(arg),
+            },
 
-        hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
-            ExprKind::AddressOf { mutability, arg: arg.to_ref() }
-        }
+            hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
+                ExprKind::AddressOf { mutability, arg: self.mirror_expr_boxed(arg) }
+            }
 
-        hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk },
+            hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) },
 
-        hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
-            ExprKind::Assign { lhs: lhs.to_ref(), rhs: rhs.to_ref() }
-        }
+            hir::ExprKind::Assign(ref lhs, ref rhs, _) => ExprKind::Assign {
+                lhs: self.mirror_expr_boxed(lhs),
+                rhs: self.mirror_expr_boxed(rhs),
+            },
 
-        hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
-            if cx.typeck_results().is_method_call(expr) {
-                overloaded_operator(cx, expr, vec![lhs.to_ref(), rhs.to_ref()])
-            } else {
-                ExprKind::AssignOp { op: bin_op(op.node), lhs: lhs.to_ref(), rhs: rhs.to_ref() }
+            hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
+                if self.typeck_results().is_method_call(expr) {
+                    let lhs = self.mirror_expr(lhs);
+                    let rhs = self.mirror_expr(rhs);
+                    self.overloaded_operator(expr, vec![lhs, rhs])
+                } else {
+                    ExprKind::AssignOp {
+                        op: bin_op(op.node),
+                        lhs: self.mirror_expr_boxed(lhs),
+                        rhs: self.mirror_expr_boxed(rhs),
+                    }
+                }
             }
-        }
 
-        hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
-            literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false),
-            user_ty: None,
-            const_id: None,
-        },
-
-        hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
-            if cx.typeck_results().is_method_call(expr) {
-                overloaded_operator(cx, expr, vec![lhs.to_ref(), rhs.to_ref()])
-            } else {
-                // FIXME overflow
-                match (op.node, cx.constness) {
-                    (hir::BinOpKind::And, _) => ExprKind::LogicalOp {
-                        op: LogicalOp::And,
-                        lhs: lhs.to_ref(),
-                        rhs: rhs.to_ref(),
-                    },
-                    (hir::BinOpKind::Or, _) => ExprKind::LogicalOp {
-                        op: LogicalOp::Or,
-                        lhs: lhs.to_ref(),
-                        rhs: rhs.to_ref(),
-                    },
+            hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
+                literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, false),
+                user_ty: None,
+                const_id: None,
+            },
 
-                    _ => {
-                        let op = bin_op(op.node);
-                        ExprKind::Binary { op, lhs: lhs.to_ref(), rhs: rhs.to_ref() }
+            hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
+                if self.typeck_results().is_method_call(expr) {
+                    let lhs = self.mirror_expr(lhs);
+                    let rhs = self.mirror_expr(rhs);
+                    self.overloaded_operator(expr, vec![lhs, rhs])
+                } else {
+                    // FIXME overflow
+                    match (op.node, self.constness) {
+                        (hir::BinOpKind::And, _) => ExprKind::LogicalOp {
+                            op: LogicalOp::And,
+                            lhs: self.mirror_expr_boxed(lhs),
+                            rhs: self.mirror_expr_boxed(rhs),
+                        },
+                        (hir::BinOpKind::Or, _) => ExprKind::LogicalOp {
+                            op: LogicalOp::Or,
+                            lhs: self.mirror_expr_boxed(lhs),
+                            rhs: self.mirror_expr_boxed(rhs),
+                        },
+
+                        _ => {
+                            let op = bin_op(op.node);
+                            ExprKind::Binary {
+                                op,
+                                lhs: self.mirror_expr_boxed(lhs),
+                                rhs: self.mirror_expr_boxed(rhs),
+                            }
+                        }
                     }
                 }
             }
-        }
 
-        hir::ExprKind::Index(ref lhs, ref index) => {
-            if cx.typeck_results().is_method_call(expr) {
-                overloaded_place(
-                    cx,
-                    expr,
-                    expr_ty,
-                    None,
-                    vec![lhs.to_ref(), index.to_ref()],
-                    expr.span,
-                )
-            } else {
-                ExprKind::Index { lhs: lhs.to_ref(), index: index.to_ref() }
+            hir::ExprKind::Index(ref lhs, ref index) => {
+                if self.typeck_results().is_method_call(expr) {
+                    let lhs = self.mirror_expr(lhs);
+                    let index = self.mirror_expr(index);
+                    self.overloaded_place(expr, expr_ty, None, vec![lhs, index], expr.span)
+                } else {
+                    ExprKind::Index {
+                        lhs: self.mirror_expr_boxed(lhs),
+                        index: self.mirror_expr_boxed(index),
+                    }
+                }
             }
-        }
 
-        hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => {
-            if cx.typeck_results().is_method_call(expr) {
-                overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()], expr.span)
-            } else {
-                ExprKind::Deref { arg: arg.to_ref() }
+            hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => {
+                if self.typeck_results().is_method_call(expr) {
+                    let arg = self.mirror_expr(arg);
+                    self.overloaded_place(expr, expr_ty, None, vec![arg], expr.span)
+                } else {
+                    ExprKind::Deref { arg: self.mirror_expr_boxed(arg) }
+                }
             }
-        }
 
-        hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => {
-            if cx.typeck_results().is_method_call(expr) {
-                overloaded_operator(cx, expr, vec![arg.to_ref()])
-            } else {
-                ExprKind::Unary { op: UnOp::Not, arg: arg.to_ref() }
+            hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => {
+                if self.typeck_results().is_method_call(expr) {
+                    let arg = self.mirror_expr(arg);
+                    self.overloaded_operator(expr, vec![arg])
+                } else {
+                    ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr_boxed(arg) }
+                }
             }
-        }
 
-        hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => {
-            if cx.typeck_results().is_method_call(expr) {
-                overloaded_operator(cx, expr, vec![arg.to_ref()])
-            } else if let hir::ExprKind::Lit(ref lit) = arg.kind {
-                ExprKind::Literal {
-                    literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true),
-                    user_ty: None,
-                    const_id: None,
+            hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => {
+                if self.typeck_results().is_method_call(expr) {
+                    let arg = self.mirror_expr(arg);
+                    self.overloaded_operator(expr, vec![arg])
+                } else if let hir::ExprKind::Lit(ref lit) = arg.kind {
+                    ExprKind::Literal {
+                        literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true),
+                        user_ty: None,
+                        const_id: None,
+                    }
+                } else {
+                    ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr_boxed(arg) }
                 }
-            } else {
-                ExprKind::Unary { op: UnOp::Neg, arg: arg.to_ref() }
             }
-        }
 
-        hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() {
-            ty::Adt(adt, substs) => match adt.adt_kind() {
-                AdtKind::Struct | AdtKind::Union => {
-                    let user_provided_types = cx.typeck_results().user_provided_types();
-                    let user_ty = user_provided_types.get(expr.hir_id).copied();
-                    debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
-                    ExprKind::Adt {
-                        adt_def: adt,
-                        variant_index: VariantIdx::new(0),
-                        substs,
-                        user_ty,
-                        fields: field_refs(cx, fields),
-                        base: base.as_ref().map(|base| FruInfo {
-                            base: base.to_ref(),
-                            field_types: cx.typeck_results().fru_field_types()[expr.hir_id].clone(),
-                        }),
+            hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() {
+                ty::Adt(adt, substs) => match adt.adt_kind() {
+                    AdtKind::Struct | AdtKind::Union => {
+                        let user_provided_types = self.typeck_results().user_provided_types();
+                        let user_ty = user_provided_types.get(expr.hir_id).copied();
+                        debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
+                        ExprKind::Adt {
+                            adt_def: adt,
+                            variant_index: VariantIdx::new(0),
+                            substs,
+                            user_ty,
+                            fields: self.field_refs(fields),
+                            base: base.as_ref().map(|base| FruInfo {
+                                base: self.mirror_expr_boxed(base),
+                                field_types: self.typeck_results().fru_field_types()[expr.hir_id]
+                                    .clone(),
+                            }),
+                        }
                     }
-                }
-                AdtKind::Enum => {
-                    let res = cx.typeck_results().qpath_res(qpath, expr.hir_id);
-                    match res {
-                        Res::Def(DefKind::Variant, variant_id) => {
-                            assert!(base.is_none());
-
-                            let index = adt.variant_index_with_id(variant_id);
-                            let user_provided_types = cx.typeck_results().user_provided_types();
-                            let user_ty = user_provided_types.get(expr.hir_id).copied();
-                            debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
-                            ExprKind::Adt {
-                                adt_def: adt,
-                                variant_index: index,
-                                substs,
-                                user_ty,
-                                fields: field_refs(cx, fields),
-                                base: None,
+                    AdtKind::Enum => {
+                        let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
+                        match res {
+                            Res::Def(DefKind::Variant, variant_id) => {
+                                assert!(base.is_none());
+
+                                let index = adt.variant_index_with_id(variant_id);
+                                let user_provided_types =
+                                    self.typeck_results().user_provided_types();
+                                let user_ty = user_provided_types.get(expr.hir_id).copied();
+                                debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
+                                ExprKind::Adt {
+                                    adt_def: adt,
+                                    variant_index: index,
+                                    substs,
+                                    user_ty,
+                                    fields: self.field_refs(fields),
+                                    base: None,
+                                }
+                            }
+                            _ => {
+                                span_bug!(expr.span, "unexpected res: {:?}", res);
                             }
-                        }
-                        _ => {
-                            span_bug!(expr.span, "unexpected res: {:?}", res);
                         }
                     }
-                }
-            },
-            _ => {
-                span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty);
-            }
-        },
-
-        hir::ExprKind::Closure(..) => {
-            let closure_ty = cx.typeck_results().expr_ty(expr);
-            let (def_id, substs, movability) = match *closure_ty.kind() {
-                ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
-                ty::Generator(def_id, substs, movability) => {
-                    (def_id, UpvarSubsts::Generator(substs), Some(movability))
-                }
+                },
                 _ => {
-                    span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
+                    span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty);
                 }
-            };
+            },
 
-            let upvars = cx
-                .typeck_results()
-                .closure_min_captures_flattened(def_id)
-                .zip(substs.upvar_tys())
-                .map(|(captured_place, ty)| capture_upvar(cx, expr, captured_place, ty))
-                .collect();
-            ExprKind::Closure { closure_id: def_id, substs, upvars, movability }
-        }
+            hir::ExprKind::Closure(..) => {
+                let closure_ty = self.typeck_results().expr_ty(expr);
+                let (def_id, substs, movability) = match *closure_ty.kind() {
+                    ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
+                    ty::Generator(def_id, substs, movability) => {
+                        (def_id, UpvarSubsts::Generator(substs), Some(movability))
+                    }
+                    _ => {
+                        span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
+                    }
+                };
 
-        hir::ExprKind::Path(ref qpath) => {
-            let res = cx.typeck_results().qpath_res(qpath, expr.hir_id);
-            convert_path_expr(cx, expr, res)
-        }
+                let upvars = self
+                    .typeck_results()
+                    .closure_min_captures_flattened(def_id)
+                    .zip(substs.upvar_tys())
+                    .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty))
+                    .collect();
+                ExprKind::Closure { closure_id: def_id, substs, upvars, movability }
+            }
 
-        hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm {
-            template: asm.template,
-            operands: asm
-                .operands
-                .iter()
-                .map(|(op, _op_sp)| {
-                    match *op {
-                        hir::InlineAsmOperand::In { reg, ref expr } => {
-                            InlineAsmOperand::In { reg, expr: expr.to_ref() }
-                        }
-                        hir::InlineAsmOperand::Out { reg, late, ref expr } => {
-                            InlineAsmOperand::Out {
+            hir::ExprKind::Path(ref qpath) => {
+                let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
+                self.convert_path_expr(expr, res)
+            }
+
+            hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm {
+                template: asm.template,
+                operands: asm
+                    .operands
+                    .iter()
+                    .map(|(op, _op_sp)| {
+                        match *op {
+                            hir::InlineAsmOperand::In { reg, ref expr } => {
+                                InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
+                            }
+                            hir::InlineAsmOperand::Out { reg, late, ref expr } => {
+                                InlineAsmOperand::Out {
+                                    reg,
+                                    late,
+                                    expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
+                                }
+                            }
+                            hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
+                                InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
+                            }
+                            hir::InlineAsmOperand::SplitInOut {
                                 reg,
                                 late,
-                                expr: expr.as_ref().map(|expr| expr.to_ref()),
+                                ref in_expr,
+                                ref out_expr,
+                            } => InlineAsmOperand::SplitInOut {
+                                reg,
+                                late,
+                                in_expr: self.mirror_expr(in_expr),
+                                out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
+                            },
+                            hir::InlineAsmOperand::Const { ref expr } => {
+                                InlineAsmOperand::Const { expr: self.mirror_expr(expr) }
                             }
-                        }
-                        hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
-                            InlineAsmOperand::InOut { reg, late, expr: expr.to_ref() }
-                        }
-                        hir::InlineAsmOperand::SplitInOut {
-                            reg,
-                            late,
-                            ref in_expr,
-                            ref out_expr,
-                        } => InlineAsmOperand::SplitInOut {
-                            reg,
-                            late,
-                            in_expr: in_expr.to_ref(),
-                            out_expr: out_expr.as_ref().map(|expr| expr.to_ref()),
-                        },
-                        hir::InlineAsmOperand::Const { ref expr } => {
-                            InlineAsmOperand::Const { expr: expr.to_ref() }
-                        }
-                        hir::InlineAsmOperand::Sym { ref expr } => {
-                            let qpath = match expr.kind {
-                                hir::ExprKind::Path(ref qpath) => qpath,
-                                _ => span_bug!(
-                                    expr.span,
-                                    "asm `sym` operand should be a path, found {:?}",
-                                    expr.kind
-                                ),
-                            };
-                            let temp_lifetime =
-                                cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-                            let res = cx.typeck_results().qpath_res(qpath, expr.hir_id);
-                            let ty;
-                            match res {
-                                Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => {
-                                    ty = cx.typeck_results().node_type(expr.hir_id);
-                                    let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
-                                    InlineAsmOperand::SymFn {
-                                        expr: Expr {
-                                            ty,
-                                            temp_lifetime,
-                                            span: expr.span,
-                                            kind: ExprKind::Literal {
-                                                literal: ty::Const::zero_sized(cx.tcx, ty),
-                                                user_ty,
-                                                const_id: None,
+                            hir::InlineAsmOperand::Sym { ref expr } => {
+                                let qpath = match expr.kind {
+                                    hir::ExprKind::Path(ref qpath) => qpath,
+                                    _ => span_bug!(
+                                        expr.span,
+                                        "asm `sym` operand should be a path, found {:?}",
+                                        expr.kind
+                                    ),
+                                };
+                                let temp_lifetime =
+                                    self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
+                                let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
+                                let ty;
+                                match res {
+                                    Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => {
+                                        ty = self.typeck_results().node_type(expr.hir_id);
+                                        let user_ty =
+                                            self.user_substs_applied_to_res(expr.hir_id, res);
+                                        InlineAsmOperand::SymFn {
+                                            expr: Expr {
+                                                ty,
+                                                temp_lifetime,
+                                                span: expr.span,
+                                                kind: ExprKind::Literal {
+                                                    literal: ty::Const::zero_sized(self.tcx, ty),
+                                                    user_ty,
+                                                    const_id: None,
+                                                },
                                             },
                                         }
-                                        .to_ref(),
                                     }
-                                }
 
-                                Res::Def(DefKind::Static, def_id) => {
-                                    InlineAsmOperand::SymStatic { def_id }
-                                }
+                                    Res::Def(DefKind::Static, def_id) => {
+                                        InlineAsmOperand::SymStatic { def_id }
+                                    }
 
-                                _ => {
-                                    cx.tcx.sess.span_err(
-                                        expr.span,
-                                        "asm `sym` operand must point to a fn or static",
-                                    );
-
-                                    // Not a real fn, but we're not reaching codegen anyways...
-                                    ty = cx.tcx.ty_error();
-                                    InlineAsmOperand::SymFn {
-                                        expr: Expr {
-                                            ty,
-                                            temp_lifetime,
-                                            span: expr.span,
-                                            kind: ExprKind::Literal {
-                                                literal: ty::Const::zero_sized(cx.tcx, ty),
-                                                user_ty: None,
-                                                const_id: None,
+                                    _ => {
+                                        self.tcx.sess.span_err(
+                                            expr.span,
+                                            "asm `sym` operand must point to a fn or static",
+                                        );
+
+                                        // Not a real fn, but we're not reaching codegen anyways...
+                                        ty = self.tcx.ty_error();
+                                        InlineAsmOperand::SymFn {
+                                            expr: Expr {
+                                                ty,
+                                                temp_lifetime,
+                                                span: expr.span,
+                                                kind: ExprKind::Literal {
+                                                    literal: ty::Const::zero_sized(self.tcx, ty),
+                                                    user_ty: None,
+                                                    const_id: None,
+                                                },
                                             },
                                         }
-                                        .to_ref(),
                                     }
                                 }
                             }
                         }
-                    }
-                })
-                .collect(),
-            options: asm.options,
-            line_spans: asm.line_spans,
-        },
-
-        hir::ExprKind::LlvmInlineAsm(ref asm) => ExprKind::LlvmInlineAsm {
-            asm: &asm.inner,
-            outputs: asm.outputs_exprs.to_ref(),
-            inputs: asm.inputs_exprs.to_ref(),
-        },
-
-        hir::ExprKind::ConstBlock(ref anon_const) => {
-            let anon_const_def_id = cx.tcx.hir().local_def_id(anon_const.hir_id);
-            let value = ty::Const::from_anon_const(cx.tcx, anon_const_def_id);
-
-            ExprKind::ConstBlock { value }
-        }
-        // Now comes the rote stuff:
-        hir::ExprKind::Repeat(ref v, ref count) => {
-            let count_def_id = cx.tcx.hir().local_def_id(count.hir_id);
-            let count = ty::Const::from_anon_const(cx.tcx, count_def_id);
+                    })
+                    .collect(),
+                options: asm.options,
+                line_spans: asm.line_spans,
+            },
 
-            ExprKind::Repeat { value: v.to_ref(), count }
-        }
-        hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.to_ref() },
-        hir::ExprKind::Break(dest, ref value) => match dest.target_id {
-            Ok(target_id) => ExprKind::Break {
-                label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
-                value: value.to_ref(),
+            hir::ExprKind::LlvmInlineAsm(ref asm) => ExprKind::LlvmInlineAsm {
+                asm: &asm.inner,
+                outputs: self.mirror_exprs(asm.outputs_exprs),
+                inputs: self.mirror_exprs(asm.inputs_exprs),
+            },
+
+            hir::ExprKind::ConstBlock(ref anon_const) => {
+                let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
+                let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+
+                ExprKind::ConstBlock { value }
+            }
+            // Now comes the rote stuff:
+            hir::ExprKind::Repeat(ref v, ref count) => {
+                let count_def_id = self.tcx.hir().local_def_id(count.hir_id);
+                let count = ty::Const::from_anon_const(self.tcx, count_def_id);
+
+                ExprKind::Repeat { value: self.mirror_expr_boxed(v), count }
+            }
+            hir::ExprKind::Ret(ref v) => {
+                ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr_boxed(v)) }
+            }
+            hir::ExprKind::Break(dest, ref value) => match dest.target_id {
+                Ok(target_id) => ExprKind::Break {
+                    label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
+                    value: value.as_ref().map(|value| self.mirror_expr_boxed(value)),
+                },
+                Err(err) => bug!("invalid loop id for break: {}", err),
+            },
+            hir::ExprKind::Continue(dest) => match dest.target_id {
+                Ok(loop_id) => ExprKind::Continue {
+                    label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node },
+                },
+                Err(err) => bug!("invalid loop id for continue: {}", err),
             },
-            Err(err) => bug!("invalid loop id for break: {}", err),
-        },
-        hir::ExprKind::Continue(dest) => match dest.target_id {
-            Ok(loop_id) => ExprKind::Continue {
-                label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node },
+            hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
+                cond: self.mirror_expr_boxed(cond),
+                then: self.mirror_expr_boxed(then),
+                else_opt: else_opt.map(|el| self.mirror_expr_boxed(el)),
             },
-            Err(err) => bug!("invalid loop id for continue: {}", err),
-        },
-        hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
-            cond: cond.to_ref(),
-            then: then.to_ref(),
-            else_opt: else_opt.map(|el| el.to_ref()),
-        },
-        hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
-            scrutinee: discr.to_ref(),
-            arms: arms.iter().map(|a| convert_arm(cx, a)).collect(),
-        },
-        hir::ExprKind::Loop(ref body, ..) => ExprKind::Loop { body: block::to_expr_ref(cx, body) },
-        hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
-            lhs: source.to_ref(),
-            name: Field::new(cx.tcx.field_index(expr.hir_id, cx.typeck_results)),
-        },
-        hir::ExprKind::Cast(ref source, ref cast_ty) => {
-            // Check for a user-given type annotation on this `cast`
-            let user_provided_types = cx.typeck_results.user_provided_types();
-            let user_ty = user_provided_types.get(cast_ty.hir_id);
-
-            debug!(
-                "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
-                expr, cast_ty.hir_id, user_ty,
-            );
-
-            // Check to see if this cast is a "coercion cast", where the cast is actually done
-            // using a coercion (or is a no-op).
-            let cast = if cx.typeck_results().is_coercion_cast(source.hir_id) {
-                // Convert the lexpr to a vexpr.
-                ExprKind::Use { source: source.to_ref() }
-            } else if cx.typeck_results().expr_ty(source).is_region_ptr() {
-                // Special cased so that we can type check that the element
-                // type of the source matches the pointed to type of the
-                // destination.
-                ExprKind::Pointer { source: source.to_ref(), cast: PointerCast::ArrayToPointer }
-            } else {
-                // check whether this is casting an enum variant discriminant
-                // to prevent cycles, we refer to the discriminant initializer
-                // which is always an integer and thus doesn't need to know the
-                // enum's layout (or its tag type) to compute it during const eval
-                // Example:
-                // enum Foo {
-                //     A,
-                //     B = A as isize + 4,
-                // }
-                // The correct solution would be to add symbolic computations to miri,
-                // so we wouldn't have to compute and store the actual value
-                let var = if let hir::ExprKind::Path(ref qpath) = source.kind {
-                    let res = cx.typeck_results().qpath_res(qpath, source.hir_id);
-                    cx.typeck_results().node_type(source.hir_id).ty_adt_def().and_then(|adt_def| {
-                        match res {
-                            Res::Def(
-                                DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
-                                variant_ctor_id,
-                            ) => {
-                                let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
-                                let (d, o) = adt_def.discriminant_def_for_variant(idx);
-                                use rustc_middle::ty::util::IntTypeExt;
-                                let ty = adt_def.repr.discr_type();
-                                let ty = ty.to_ty(cx.tcx());
-                                Some((d, o, ty))
-                            }
-                            _ => None,
-                        }
-                    })
+            hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
+                scrutinee: self.mirror_expr_boxed(discr),
+                arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
+            },
+            hir::ExprKind::Loop(ref body, ..) => {
+                let block_ty = self.typeck_results().node_type(body.hir_id);
+                let temp_lifetime = self.region_scope_tree.temporary_scope(body.hir_id.local_id);
+                let block = self.mirror_block(body);
+                let body = Box::new(Expr {
+                    ty: block_ty,
+                    temp_lifetime,
+                    span: block.span,
+                    kind: ExprKind::Block { body: block },
+                });
+                ExprKind::Loop { body }
+            }
+            hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
+                lhs: self.mirror_expr_boxed(source),
+                name: Field::new(self.tcx.field_index(expr.hir_id, self.typeck_results)),
+            },
+            hir::ExprKind::Cast(ref source, ref cast_ty) => {
+                // Check for a user-given type annotation on this `cast`
+                let user_provided_types = self.typeck_results.user_provided_types();
+                let user_ty = user_provided_types.get(cast_ty.hir_id);
+
+                debug!(
+                    "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}",
+                    expr, cast_ty.hir_id, user_ty,
+                );
+
+                // Check to see if this cast is a "coercion cast", where the cast is actually done
+                // using a coercion (or is a no-op).
+                let cast = if self.typeck_results().is_coercion_cast(source.hir_id) {
+                    // Convert the lexpr to a vexpr.
+                    ExprKind::Use { source: self.mirror_expr_boxed(source) }
+                } else if self.typeck_results().expr_ty(source).is_region_ptr() {
+                    // Special cased so that we can type check that the element
+                    // type of the source matches the pointed to type of the
+                    // destination.
+                    ExprKind::Pointer {
+                        source: self.mirror_expr_boxed(source),
+                        cast: PointerCast::ArrayToPointer,
+                    }
                 } else {
-                    None
-                };
+                    // check whether this is casting an enum variant discriminant
+                    // to prevent cycles, we refer to the discriminant initializer
+                    // which is always an integer and thus doesn't need to know the
+                    // enum's layout (or its tag type) to compute it during const eval
+                    // Example:
+                    // enum Foo {
+                    //     A,
+                    //     B = A as isize + 4,
+                    // }
+                    // The correct solution would be to add symbolic computations to miri,
+                    // so we wouldn't have to compute and store the actual value
+                    let var = if let hir::ExprKind::Path(ref qpath) = source.kind {
+                        let res = self.typeck_results().qpath_res(qpath, source.hir_id);
+                        self.typeck_results().node_type(source.hir_id).ty_adt_def().and_then(
+                            |adt_def| match res {
+                                Res::Def(
+                                    DefKind::Ctor(CtorOf::Variant, CtorKind::Const),
+                                    variant_ctor_id,
+                                ) => {
+                                    let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
+                                    let (d, o) = adt_def.discriminant_def_for_variant(idx);
+                                    use rustc_middle::ty::util::IntTypeExt;
+                                    let ty = adt_def.repr.discr_type();
+                                    let ty = ty.to_ty(self.tcx());
+                                    Some((d, o, ty))
+                                }
+                                _ => None,
+                            },
+                        )
+                    } else {
+                        None
+                    };
 
-                let source = if let Some((did, offset, var_ty)) = var {
-                    let mk_const = |literal| {
-                        Expr {
+                    let source = if let Some((did, offset, var_ty)) = var {
+                        let mk_const = |literal| Expr {
                             temp_lifetime,
                             ty: var_ty,
                             span: expr.span,
                             kind: ExprKind::Literal { literal, user_ty: None, const_id: None },
+                        };
+                        let offset = mk_const(ty::Const::from_bits(
+                            self.tcx,
+                            offset as u128,
+                            self.param_env.and(var_ty),
+                        ));
+                        match did {
+                            Some(did) => {
+                                // in case we are offsetting from a computed discriminant
+                                // and not the beginning of discriminants (which is always `0`)
+                                let substs = InternalSubsts::identity_for_item(self.tcx(), did);
+                                let lhs = mk_const(self.tcx().mk_const(ty::Const {
+                                    val: ty::ConstKind::Unevaluated(
+                                        ty::WithOptConstParam::unknown(did),
+                                        substs,
+                                        None,
+                                    ),
+                                    ty: var_ty,
+                                }));
+                                let bin = ExprKind::Binary {
+                                    op: BinOp::Add,
+                                    lhs: Box::new(lhs),
+                                    rhs: Box::new(offset),
+                                };
+                                Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin }
+                            }
+                            None => offset,
                         }
-                        .to_ref()
+                    } else {
+                        self.mirror_expr(source)
                     };
-                    let offset = mk_const(ty::Const::from_bits(
-                        cx.tcx,
-                        offset as u128,
-                        cx.param_env.and(var_ty),
-                    ));
-                    match did {
-                        Some(did) => {
-                            // in case we are offsetting from a computed discriminant
-                            // and not the beginning of discriminants (which is always `0`)
-                            let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
-                            let lhs = mk_const(cx.tcx().mk_const(ty::Const {
-                                val: ty::ConstKind::Unevaluated(
-                                    ty::WithOptConstParam::unknown(did),
-                                    substs,
-                                    None,
-                                ),
-                                ty: var_ty,
-                            }));
-                            let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset };
-                            Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin }.to_ref()
-                        }
-                        None => offset,
-                    }
-                } else {
-                    source.to_ref()
-                };
 
-                ExprKind::Cast { source }
-            };
+                    ExprKind::Cast { source: Box::new(source) }
+                };
 
-            if let Some(user_ty) = user_ty {
-                // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
-                //       inefficient, revisit this when performance becomes an issue.
-                let cast_expr = Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast };
-                debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
+                if let Some(user_ty) = user_ty {
+                    // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
+                    //       inefficient, revisit this when performance becomes an issue.
+                    let cast_expr =
+                        Box::new(Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast });
+                    debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
 
-                ExprKind::ValueTypeAscription {
-                    source: cast_expr.to_ref(),
-                    user_ty: Some(*user_ty),
+                    ExprKind::ValueTypeAscription { source: cast_expr, user_ty: Some(*user_ty) }
+                } else {
+                    cast
                 }
-            } else {
-                cast
             }
-        }
-        hir::ExprKind::Type(ref source, ref ty) => {
-            let user_provided_types = cx.typeck_results.user_provided_types();
-            let user_ty = user_provided_types.get(ty.hir_id).copied();
-            debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
-            if source.is_syntactic_place_expr() {
-                ExprKind::PlaceTypeAscription { source: source.to_ref(), user_ty }
-            } else {
-                ExprKind::ValueTypeAscription { source: source.to_ref(), user_ty }
+            hir::ExprKind::Type(ref source, ref ty) => {
+                let user_provided_types = self.typeck_results.user_provided_types();
+                let user_ty = user_provided_types.get(ty.hir_id).copied();
+                debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
+                let mirrored = self.mirror_expr_boxed(source);
+                if source.is_syntactic_place_expr() {
+                    ExprKind::PlaceTypeAscription { source: mirrored, user_ty }
+                } else {
+                    ExprKind::ValueTypeAscription { source: mirrored, user_ty }
+                }
+            }
+            hir::ExprKind::DropTemps(ref source) => {
+                ExprKind::Use { source: self.mirror_expr_boxed(source) }
+            }
+            hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr_boxed(value) },
+            hir::ExprKind::Array(ref fields) => ExprKind::Array {
+                fields: fields.iter().map(|field| self.mirror_expr(field)).collect(),
+            },
+            hir::ExprKind::Tup(ref fields) => ExprKind::Tuple {
+                fields: fields.iter().map(|field| self.mirror_expr(field)).collect(),
+            },
+
+            hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr_boxed(v) },
+            hir::ExprKind::Err => unreachable!(),
+        };
+
+        Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
+    }
+
+    fn user_substs_applied_to_res(
+        &mut self,
+        hir_id: hir::HirId,
+        res: Res,
+    ) -> Option<ty::CanonicalUserType<'tcx>> {
+        debug!("user_substs_applied_to_res: res={:?}", res);
+        let user_provided_type = match res {
+            // A reference to something callable -- e.g., a fn, method, or
+            // a tuple-struct or tuple-variant. This has the type of a
+            // `Fn` but with the user-given substitutions.
+            Res::Def(DefKind::Fn, _)
+            | Res::Def(DefKind::AssocFn, _)
+            | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
+            | Res::Def(DefKind::Const, _)
+            | Res::Def(DefKind::AssocConst, _) => {
+                self.typeck_results().user_provided_types().get(hir_id).copied()
+            }
+
+            // A unit struct/variant which is used as a value (e.g.,
+            // `None`). This has the type of the enum/struct that defines
+            // this variant -- but with the substitutions given by the
+            // user.
+            Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
+                self.user_substs_applied_to_ty_of_hir_id(hir_id)
+            }
+
+            // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
+            Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id),
+
+            _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
+        };
+        debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type);
+        user_provided_type
+    }
+
+    fn method_callee(
+        &mut self,
+        expr: &hir::Expr<'_>,
+        span: Span,
+        overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
+    ) -> Expr<'tcx> {
+        let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
+        let (def_id, substs, user_ty) = match overloaded_callee {
+            Some((def_id, substs)) => (def_id, substs, None),
+            None => {
+                let (kind, def_id) =
+                    self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| {
+                        span_bug!(expr.span, "no type-dependent def for method callee")
+                    });
+                let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id));
+                debug!("method_callee: user_ty={:?}", user_ty);
+                (def_id, self.typeck_results().node_substs(expr.hir_id), user_ty)
             }
+        };
+        let ty = self.tcx().mk_fn_def(def_id, substs);
+        Expr {
+            temp_lifetime,
+            ty,
+            span,
+            kind: ExprKind::Literal {
+                literal: ty::Const::zero_sized(self.tcx(), ty),
+                user_ty,
+                const_id: None,
+            },
+        }
+    }
+
+    fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> {
+        Arm {
+            pattern: self.pattern_from_hir(&arm.pat),
+            guard: arm.guard.as_ref().map(|g| match g {
+                hir::Guard::If(ref e) => Guard::If(self.mirror_expr_boxed(e)),
+                hir::Guard::IfLet(ref pat, ref e) => {
+                    Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr_boxed(e))
+                }
+            }),
+            body: self.mirror_expr(arm.body),
+            lint_level: LintLevel::Explicit(arm.hir_id),
+            scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
+            span: arm.span,
         }
-        hir::ExprKind::DropTemps(ref source) => ExprKind::Use { source: source.to_ref() },
-        hir::ExprKind::Box(ref value) => ExprKind::Box { value: value.to_ref() },
-        hir::ExprKind::Array(ref fields) => ExprKind::Array { fields: fields.to_ref() },
-        hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() },
+    }
 
-        hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: v.to_ref() },
-        hir::ExprKind::Err => unreachable!(),
-    };
+    fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
+        let substs = self.typeck_results().node_substs(expr.hir_id);
+        match res {
+            // A regular function, constructor function or a constant.
+            Res::Def(DefKind::Fn, _)
+            | Res::Def(DefKind::AssocFn, _)
+            | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
+            | Res::SelfCtor(..) => {
+                let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
+                debug!("convert_path_expr: user_ty={:?}", user_ty);
+                ExprKind::Literal {
+                    literal: ty::Const::zero_sized(
+                        self.tcx,
+                        self.typeck_results().node_type(expr.hir_id),
+                    ),
+                    user_ty,
+                    const_id: None,
+                }
+            }
 
-    Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
-}
+            Res::Def(DefKind::ConstParam, def_id) => {
+                let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+                let item_id = self.tcx.hir().get_parent_node(hir_id);
+                let item_def_id = self.tcx.hir().local_def_id(item_id);
+                let generics = self.tcx.generics_of(item_def_id);
+                let index = generics.param_def_id_to_index[&def_id];
+                let name = self.tcx.hir().name(hir_id);
+                let val = ty::ConstKind::Param(ty::ParamConst::new(index, name));
+                ExprKind::Literal {
+                    literal: self.tcx.mk_const(ty::Const {
+                        val,
+                        ty: self.typeck_results().node_type(expr.hir_id),
+                    }),
+                    user_ty: None,
+                    const_id: Some(def_id),
+                }
+            }
+
+            Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
+                let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
+                debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
+                ExprKind::Literal {
+                    literal: self.tcx.mk_const(ty::Const {
+                        val: ty::ConstKind::Unevaluated(
+                            ty::WithOptConstParam::unknown(def_id),
+                            substs,
+                            None,
+                        ),
+                        ty: self.typeck_results().node_type(expr.hir_id),
+                    }),
+                    user_ty,
+                    const_id: Some(def_id),
+                }
+            }
+
+            Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
+                let user_provided_types = self.typeck_results.user_provided_types();
+                let user_provided_type = user_provided_types.get(expr.hir_id).copied();
+                debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
+                let ty = self.typeck_results().node_type(expr.hir_id);
+                match ty.kind() {
+                    // A unit struct/variant which is used as a value.
+                    // We return a completely different ExprKind here to account for this special case.
+                    ty::Adt(adt_def, substs) => ExprKind::Adt {
+                        adt_def,
+                        variant_index: adt_def.variant_index_with_ctor_id(def_id),
+                        substs,
+                        user_ty: user_provided_type,
+                        fields: vec![],
+                        base: None,
+                    },
+                    _ => bug!("unexpected ty: {:?}", ty),
+                }
+            }
+
+            // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
+            // a constant reference (or constant raw pointer for `static mut`) in MIR
+            Res::Def(DefKind::Static, id) => {
+                let ty = self.tcx.static_ptr_ty(id);
+                let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
+                let kind = if self.tcx.is_thread_local_static(id) {
+                    ExprKind::ThreadLocalRef(id)
+                } else {
+                    let ptr = self.tcx.create_static_alloc(id);
+                    ExprKind::StaticRef {
+                        literal: ty::Const::from_scalar(self.tcx, Scalar::Ptr(ptr.into()), ty),
+                        def_id: id,
+                    }
+                };
+                ExprKind::Deref { arg: Box::new(Expr { ty, temp_lifetime, span: expr.span, kind }) }
+            }
+
+            Res::Local(var_hir_id) => self.convert_var(var_hir_id),
 
-fn user_substs_applied_to_res<'tcx>(
-    cx: &mut Cx<'_, 'tcx>,
-    hir_id: hir::HirId,
-    res: Res,
-) -> Option<ty::CanonicalUserType<'tcx>> {
-    debug!("user_substs_applied_to_res: res={:?}", res);
-    let user_provided_type = match res {
-        // A reference to something callable -- e.g., a fn, method, or
-        // a tuple-struct or tuple-variant. This has the type of a
-        // `Fn` but with the user-given substitutions.
-        Res::Def(DefKind::Fn, _)
-        | Res::Def(DefKind::AssocFn, _)
-        | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
-        | Res::Def(DefKind::Const, _)
-        | Res::Def(DefKind::AssocConst, _) => {
-            cx.typeck_results().user_provided_types().get(hir_id).copied()
+            _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
         }
+    }
 
-        // A unit struct/variant which is used as a value (e.g.,
-        // `None`). This has the type of the enum/struct that defines
-        // this variant -- but with the substitutions given by the
-        // user.
-        Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => {
-            cx.user_substs_applied_to_ty_of_hir_id(hir_id)
+    fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
+        // We want upvars here not captures.
+        // Captures will be handled in MIR.
+        let is_upvar = self
+            .tcx
+            .upvars_mentioned(self.body_owner)
+            .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
+
+        debug!(
+            "convert_var({:?}): is_upvar={}, body_owner={:?}",
+            var_hir_id, is_upvar, self.body_owner
+        );
+
+        if is_upvar {
+            ExprKind::UpvarRef { closure_def_id: self.body_owner, var_hir_id }
+        } else {
+            ExprKind::VarRef { id: var_hir_id }
         }
+    }
 
-        // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
-        Res::SelfCtor(_) => cx.user_substs_applied_to_ty_of_hir_id(hir_id),
+    fn overloaded_operator(
+        &mut self,
+        expr: &'tcx hir::Expr<'tcx>,
+        args: Vec<Expr<'tcx>>,
+    ) -> ExprKind<'tcx> {
+        let fun = Box::new(self.method_callee(expr, expr.span, None));
+        ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span }
+    }
 
-        _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
-    };
-    debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type);
-    user_provided_type
-}
+    fn overloaded_place(
+        &mut self,
+        expr: &'tcx hir::Expr<'tcx>,
+        place_ty: Ty<'tcx>,
+        overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
+        args: Vec<Expr<'tcx>>,
+        span: Span,
+    ) -> ExprKind<'tcx> {
+        // For an overloaded *x or x[y] expression of type T, the method
+        // call returns an &T and we must add the deref so that the types
+        // line up (this is because `*x` and `x[y]` represent places):
+
+        // Reconstruct the output assuming it's a reference with the
+        // same region and mutability as the receiver. This holds for
+        // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
+        let (region, mutbl) = match *args[0].ty.kind() {
+            ty::Ref(region, _, mutbl) => (region, mutbl),
+            _ => span_bug!(span, "overloaded_place: receiver is not a reference"),
+        };
+        let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl });
+
+        // construct the complete expression `foo()` for the overloaded call,
+        // which will yield the &T type
+        let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
+        let fun = Box::new(self.method_callee(expr, span, overloaded_callee));
+        let ref_expr = Box::new(Expr {
+            temp_lifetime,
+            ty: ref_ty,
+            span,
+            kind: ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: span },
+        });
+
+        // construct and return a deref wrapper `*foo()`
+        ExprKind::Deref { arg: ref_expr }
+    }
+
+    fn capture_upvar(
+        &mut self,
+        closure_expr: &'tcx hir::Expr<'tcx>,
+        captured_place: &'a ty::CapturedPlace<'tcx>,
+        upvar_ty: Ty<'tcx>,
+    ) -> Expr<'tcx> {
+        let upvar_capture = captured_place.info.capture_kind;
+        let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
+        let var_ty = captured_place.place.base_ty;
+
+        // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path
+        // as it's seen for use within the closure and not at the time of closure creation.
+        //
+        // That is we see expect to see it start from a captured upvar and not something that is local
+        // to the closure's parent.
+        let var_hir_id = match captured_place.place.base {
+            HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
+            base => bug!("Expected an upvar, found {:?}", base),
+        };
+
+        let mut captured_place_expr = Expr {
+            temp_lifetime,
+            ty: var_ty,
+            span: closure_expr.span,
+            kind: self.convert_var(var_hir_id),
+        };
+
+        for proj in captured_place.place.projections.iter() {
+            let kind = match proj.kind {
+                HirProjectionKind::Deref => ExprKind::Deref { arg: Box::new(captured_place_expr) },
+                HirProjectionKind::Field(field, ..) => {
+                    // Variant index will always be 0, because for multi-variant
+                    // enums, we capture the enum entirely.
+                    ExprKind::Field {
+                        lhs: Box::new(captured_place_expr),
+                        name: Field::new(field as usize),
+                    }
+                }
+                HirProjectionKind::Index | HirProjectionKind::Subslice => {
+                    // We don't capture these projections, so we can ignore them here
+                    continue;
+                }
+            };
 
-fn method_callee<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    expr: &hir::Expr<'_>,
-    span: Span,
-    overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
-) -> Expr<'tcx> {
-    let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-    let (def_id, substs, user_ty) = match overloaded_callee {
-        Some((def_id, substs)) => (def_id, substs, None),
-        None => {
-            let (kind, def_id) = cx
-                .typeck_results()
-                .type_dependent_def(expr.hir_id)
-                .unwrap_or_else(|| span_bug!(expr.span, "no type-dependent def for method callee"));
-            let user_ty = user_substs_applied_to_res(cx, expr.hir_id, Res::Def(kind, def_id));
-            debug!("method_callee: user_ty={:?}", user_ty);
-            (def_id, cx.typeck_results().node_substs(expr.hir_id), user_ty)
+            captured_place_expr =
+                Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind };
+        }
+
+        match upvar_capture {
+            ty::UpvarCapture::ByValue(_) => captured_place_expr,
+            ty::UpvarCapture::ByRef(upvar_borrow) => {
+                let borrow_kind = match upvar_borrow.kind {
+                    ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
+                    ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
+                    ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
+                };
+                Expr {
+                    temp_lifetime,
+                    ty: upvar_ty,
+                    span: closure_expr.span,
+                    kind: ExprKind::Borrow { borrow_kind, arg: Box::new(captured_place_expr) },
+                }
+            }
         }
-    };
-    let ty = cx.tcx().mk_fn_def(def_id, substs);
-    Expr {
-        temp_lifetime,
-        ty,
-        span,
-        kind: ExprKind::Literal {
-            literal: ty::Const::zero_sized(cx.tcx(), ty),
-            user_ty,
-            const_id: None,
-        },
+    }
+
+    /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
+    fn field_refs(&mut self, fields: &'tcx [hir::Field<'tcx>]) -> Vec<FieldExpr<'tcx>> {
+        fields
+            .iter()
+            .map(|field| FieldExpr {
+                name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
+                expr: self.mirror_expr(field.expr),
+            })
+            .collect()
     }
 }
 
@@ -776,135 +1084,6 @@ fn to_borrow_kind(&self) -> BorrowKind {
     }
 }
 
-fn convert_arm<'tcx>(cx: &mut Cx<'_, 'tcx>, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> {
-    Arm {
-        pattern: cx.pattern_from_hir(&arm.pat),
-        guard: arm.guard.as_ref().map(|g| match g {
-            hir::Guard::If(ref e) => Guard::If(e.to_ref()),
-            hir::Guard::IfLet(ref pat, ref e) => Guard::IfLet(cx.pattern_from_hir(pat), e.to_ref()),
-        }),
-        body: arm.body.to_ref(),
-        lint_level: LintLevel::Explicit(arm.hir_id),
-        scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
-        span: arm.span,
-    }
-}
-
-fn convert_path_expr<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    expr: &'tcx hir::Expr<'tcx>,
-    res: Res,
-) -> ExprKind<'tcx> {
-    let substs = cx.typeck_results().node_substs(expr.hir_id);
-    match res {
-        // A regular function, constructor function or a constant.
-        Res::Def(DefKind::Fn, _)
-        | Res::Def(DefKind::AssocFn, _)
-        | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _)
-        | Res::SelfCtor(..) => {
-            let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
-            debug!("convert_path_expr: user_ty={:?}", user_ty);
-            ExprKind::Literal {
-                literal: ty::Const::zero_sized(cx.tcx, cx.typeck_results().node_type(expr.hir_id)),
-                user_ty,
-                const_id: None,
-            }
-        }
-
-        Res::Def(DefKind::ConstParam, def_id) => {
-            let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-            let item_id = cx.tcx.hir().get_parent_node(hir_id);
-            let item_def_id = cx.tcx.hir().local_def_id(item_id);
-            let generics = cx.tcx.generics_of(item_def_id);
-            let index = generics.param_def_id_to_index[&def_id];
-            let name = cx.tcx.hir().name(hir_id);
-            let val = ty::ConstKind::Param(ty::ParamConst::new(index, name));
-            ExprKind::Literal {
-                literal: cx
-                    .tcx
-                    .mk_const(ty::Const { val, ty: cx.typeck_results().node_type(expr.hir_id) }),
-                user_ty: None,
-                const_id: Some(def_id),
-            }
-        }
-
-        Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
-            let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res);
-            debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
-            ExprKind::Literal {
-                literal: cx.tcx.mk_const(ty::Const {
-                    val: ty::ConstKind::Unevaluated(
-                        ty::WithOptConstParam::unknown(def_id),
-                        substs,
-                        None,
-                    ),
-                    ty: cx.typeck_results().node_type(expr.hir_id),
-                }),
-                user_ty,
-                const_id: Some(def_id),
-            }
-        }
-
-        Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => {
-            let user_provided_types = cx.typeck_results.user_provided_types();
-            let user_provided_type = user_provided_types.get(expr.hir_id).copied();
-            debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
-            let ty = cx.typeck_results().node_type(expr.hir_id);
-            match ty.kind() {
-                // A unit struct/variant which is used as a value.
-                // We return a completely different ExprKind here to account for this special case.
-                ty::Adt(adt_def, substs) => ExprKind::Adt {
-                    adt_def,
-                    variant_index: adt_def.variant_index_with_ctor_id(def_id),
-                    substs,
-                    user_ty: user_provided_type,
-                    fields: vec![],
-                    base: None,
-                },
-                _ => bug!("unexpected ty: {:?}", ty),
-            }
-        }
-
-        // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
-        // a constant reference (or constant raw pointer for `static mut`) in MIR
-        Res::Def(DefKind::Static, id) => {
-            let ty = cx.tcx.static_ptr_ty(id);
-            let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-            let kind = if cx.tcx.is_thread_local_static(id) {
-                ExprKind::ThreadLocalRef(id)
-            } else {
-                let ptr = cx.tcx.create_static_alloc(id);
-                ExprKind::StaticRef {
-                    literal: ty::Const::from_scalar(cx.tcx, Scalar::Ptr(ptr.into()), ty),
-                    def_id: id,
-                }
-            };
-            ExprKind::Deref { arg: Expr { ty, temp_lifetime, span: expr.span, kind }.to_ref() }
-        }
-
-        Res::Local(var_hir_id) => convert_var(cx, var_hir_id),
-
-        _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
-    }
-}
-
-fn convert_var<'tcx>(cx: &mut Cx<'_, 'tcx>, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
-    // We want upvars here not captures.
-    // Captures will be handled in MIR.
-    let is_upvar = cx
-        .tcx
-        .upvars_mentioned(cx.body_owner)
-        .map_or(false, |upvars| upvars.contains_key(&var_hir_id));
-
-    debug!("convert_var({:?}): is_upvar={}, body_owner={:?}", var_hir_id, is_upvar, cx.body_owner);
-
-    if is_upvar {
-        ExprKind::UpvarRef { closure_def_id: cx.body_owner, var_hir_id }
-    } else {
-        ExprKind::VarRef { id: var_hir_id }
-    }
-}
-
 fn bin_op(op: hir::BinOpKind) -> BinOp {
     match op {
         hir::BinOpKind::Add => BinOp::Add,
@@ -926,139 +1105,3 @@ fn bin_op(op: hir::BinOpKind) -> BinOp {
         _ => bug!("no equivalent for ast binop {:?}", op),
     }
 }
-
-fn overloaded_operator<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    expr: &'tcx hir::Expr<'tcx>,
-    args: Vec<ExprRef<'tcx>>,
-) -> ExprKind<'tcx> {
-    let fun = method_callee(cx, expr, expr.span, None);
-    ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false, fn_span: expr.span }
-}
-
-fn overloaded_place<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    expr: &'tcx hir::Expr<'tcx>,
-    place_ty: Ty<'tcx>,
-    overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
-    args: Vec<ExprRef<'tcx>>,
-    span: Span,
-) -> ExprKind<'tcx> {
-    // For an overloaded *x or x[y] expression of type T, the method
-    // call returns an &T and we must add the deref so that the types
-    // line up (this is because `*x` and `x[y]` represent places):
-
-    let recv_ty = match args[0] {
-        ExprRef::Thir(e) => cx.typeck_results().expr_ty_adjusted(e),
-        ExprRef::Mirror(ref e) => e.ty,
-    };
-
-    // Reconstruct the output assuming it's a reference with the
-    // same region and mutability as the receiver. This holds for
-    // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
-    let (region, mutbl) = match *recv_ty.kind() {
-        ty::Ref(region, _, mutbl) => (region, mutbl),
-        _ => span_bug!(span, "overloaded_place: receiver is not a reference"),
-    };
-    let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl });
-
-    // construct the complete expression `foo()` for the overloaded call,
-    // which will yield the &T type
-    let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-    let fun = method_callee(cx, expr, span, overloaded_callee);
-    let ref_expr = Expr {
-        temp_lifetime,
-        ty: ref_ty,
-        span,
-        kind: ExprKind::Call {
-            ty: fun.ty,
-            fun: fun.to_ref(),
-            args,
-            from_hir_call: false,
-            fn_span: span,
-        },
-    };
-
-    // construct and return a deref wrapper `*foo()`
-    ExprKind::Deref { arg: ref_expr.to_ref() }
-}
-
-fn capture_upvar<'a, 'tcx>(
-    cx: &mut Cx<'_, 'tcx>,
-    closure_expr: &'tcx hir::Expr<'tcx>,
-    captured_place: &'a ty::CapturedPlace<'tcx>,
-    upvar_ty: Ty<'tcx>,
-) -> ExprRef<'tcx> {
-    let upvar_capture = captured_place.info.capture_kind;
-    let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
-    let var_ty = captured_place.place.base_ty;
-
-    // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path
-    // as it's seen for use within the closure and not at the time of closure creation.
-    //
-    // That is we see expect to see it start from a captured upvar and not something that is local
-    // to the closure's parent.
-    let var_hir_id = match captured_place.place.base {
-        HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
-        base => bug!("Expected an upvar, found {:?}", base),
-    };
-
-    let mut captured_place_expr = Expr {
-        temp_lifetime,
-        ty: var_ty,
-        span: closure_expr.span,
-        kind: convert_var(cx, var_hir_id),
-    };
-
-    for proj in captured_place.place.projections.iter() {
-        let kind = match proj.kind {
-            HirProjectionKind::Deref => ExprKind::Deref { arg: captured_place_expr.to_ref() },
-            HirProjectionKind::Field(field, ..) => {
-                // Variant index will always be 0, because for multi-variant
-                // enums, we capture the enum entirely.
-                ExprKind::Field {
-                    lhs: captured_place_expr.to_ref(),
-                    name: Field::new(field as usize),
-                }
-            }
-            HirProjectionKind::Index | HirProjectionKind::Subslice => {
-                // We don't capture these projections, so we can ignore them here
-                continue;
-            }
-        };
-
-        captured_place_expr = Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind };
-    }
-
-    match upvar_capture {
-        ty::UpvarCapture::ByValue(_) => captured_place_expr.to_ref(),
-        ty::UpvarCapture::ByRef(upvar_borrow) => {
-            let borrow_kind = match upvar_borrow.kind {
-                ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
-                ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique,
-                ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false },
-            };
-            Expr {
-                temp_lifetime,
-                ty: upvar_ty,
-                span: closure_expr.span,
-                kind: ExprKind::Borrow { borrow_kind, arg: captured_place_expr.to_ref() },
-            }
-            .to_ref()
-        }
-    }
-}
-
-/// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExprRef.
-fn field_refs<'a, 'tcx>(
-    cx: &mut Cx<'a, 'tcx>,
-    fields: &'tcx [hir::Field<'tcx>],
-) -> Vec<FieldExprRef<'tcx>> {
-    fields
-        .iter()
-        .map(|field| FieldExprRef {
-            name: Field::new(cx.tcx.field_index(field.hir_id, cx.typeck_results)),
-            expr: field.expr.to_ref(),
-        })
-        .collect()
-}
index 465808cea9dd50cc9c1e03d9e99f2dcfb71e85bd..6b3b3be514c039d1558ae306f8b87af96c0c8c99 100644 (file)
@@ -93,11 +93,6 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
-    /// Normalizes `ast` into the appropriate "mirror" type.
-    crate fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
-        ast.make_mirror(self)
-    }
-
     crate fn usize_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.usize
     }
@@ -219,4 +214,3 @@ fn typeck_results(&self) -> &ty::TypeckResults<'tcx> {
 
 mod block;
 mod expr;
-mod to_ref;
diff --git a/compiler/rustc_mir_build/src/thir/cx/to_ref.rs b/compiler/rustc_mir_build/src/thir/cx/to_ref.rs
deleted file mode 100644 (file)
index 53a988e..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-use crate::thir::*;
-
-use rustc_hir as hir;
-
-crate trait ToRef {
-    type Output;
-    fn to_ref(self) -> Self::Output;
-}
-
-impl<'tcx> ToRef for &'tcx hir::Expr<'tcx> {
-    type Output = ExprRef<'tcx>;
-
-    fn to_ref(self) -> ExprRef<'tcx> {
-        ExprRef::Thir(self)
-    }
-}
-
-impl<'tcx> ToRef for &'tcx &'tcx hir::Expr<'tcx> {
-    type Output = ExprRef<'tcx>;
-
-    fn to_ref(self) -> ExprRef<'tcx> {
-        ExprRef::Thir(&**self)
-    }
-}
-
-impl<'tcx> ToRef for Expr<'tcx> {
-    type Output = ExprRef<'tcx>;
-
-    fn to_ref(self) -> ExprRef<'tcx> {
-        ExprRef::Mirror(Box::new(self))
-    }
-}
-
-impl<'tcx, T, U> ToRef for &'tcx Option<T>
-where
-    &'tcx T: ToRef<Output = U>,
-{
-    type Output = Option<U>;
-
-    fn to_ref(self) -> Option<U> {
-        self.as_ref().map(|expr| expr.to_ref())
-    }
-}
-
-impl<'tcx, T, U> ToRef for &'tcx Vec<T>
-where
-    &'tcx T: ToRef<Output = U>,
-{
-    type Output = Vec<U>;
-
-    fn to_ref(self) -> Vec<U> {
-        self.iter().map(|expr| expr.to_ref()).collect()
-    }
-}
-
-impl<'tcx, T, U> ToRef for &'tcx [T]
-where
-    &'tcx T: ToRef<Output = U>,
-{
-    type Output = Vec<U>;
-
-    fn to_ref(self) -> Vec<U> {
-        self.iter().map(|expr| expr.to_ref()).collect()
-    }
-}
index ce0098fdf860bc2e93679b75d4cde20dae41c5c8..f934dd32c53812611e7ff2ed242e81a33984e544 100644 (file)
@@ -4,7 +4,6 @@
 //! unit-tested and separated from the Rust source and compiler data
 //! structures.
 
-use self::cx::Cx;
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -39,8 +38,8 @@
     crate region_scope: region::Scope,
     crate opt_destruction_scope: Option<region::Scope>,
     crate span: Span,
-    crate stmts: Vec<StmtRef<'tcx>>,
-    crate expr: Option<ExprRef<'tcx>>,
+    crate stmts: Vec<Stmt<'tcx>>,
+    crate expr: Option<Box<Expr<'tcx>>>,
     crate safety_mode: BlockSafety,
 }
 
     PopUnsafe,
 }
 
-#[derive(Clone, Debug)]
-crate enum StmtRef<'tcx> {
-    Mirror(Box<Stmt<'tcx>>),
-}
-
 #[derive(Clone, Debug)]
 crate struct Stmt<'tcx> {
     crate kind: StmtKind<'tcx>,
@@ -70,7 +64,7 @@
         scope: region::Scope,
 
         /// expression being evaluated in this statement
-        expr: ExprRef<'tcx>,
+        expr: Box<Expr<'tcx>>,
     },
 
     Let {
@@ -88,7 +82,7 @@
         pattern: Pat<'tcx>,
 
         /// let pat: ty = <INIT> ...
-        initializer: Option<ExprRef<'tcx>>,
+        initializer: Option<Box<Expr<'tcx>>>,
 
         /// the lint level for this let-statement
         lint_level: LintLevel,
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Expr<'_>, 168);
+rustc_data_structures::static_assert_size!(Expr<'_>, 160);
 
 /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
 /// into instances of this `Expr` enum. This lowering can be done
 /// basically as lazily or as eagerly as desired: every recursive
-/// reference to an expression in this enum is an `ExprRef<'tcx>`, which
+/// reference to an expression in this enum is an `Box<Expr<'tcx>>`, which
 /// may in turn be another instance of this enum (boxed), or else an
 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
 /// short-lived. They are created by `Thir::to_expr`, analyzed and
     Scope {
         region_scope: region::Scope,
         lint_level: LintLevel,
-        value: ExprRef<'tcx>,
+        value: Box<Expr<'tcx>>,
     },
     Box {
-        value: ExprRef<'tcx>,
+        value: Box<Expr<'tcx>>,
     },
     If {
-        cond: ExprRef<'tcx>,
-        then: ExprRef<'tcx>,
-        else_opt: Option<ExprRef<'tcx>>,
+        cond: Box<Expr<'tcx>>,
+        then: Box<Expr<'tcx>>,
+        else_opt: Option<Box<Expr<'tcx>>>,
     },
     Call {
         ty: Ty<'tcx>,
-        fun: ExprRef<'tcx>,
-        args: Vec<ExprRef<'tcx>>,
-        // Whether this is from a call in HIR, rather than from an overloaded
-        // operator. True for overloaded function call.
+        fun: Box<Expr<'tcx>>,
+        args: Vec<Expr<'tcx>>,
+        /// Whether this is from a call in HIR, rather than from an overloaded
+        /// operator. `true` for overloaded function call.
         from_hir_call: bool,
         /// This `Span` is the span of the function, without the dot and receiver
         /// (e.g. `foo(a, b)` in `x.foo(a, b)`
         fn_span: Span,
     },
     Deref {
-        arg: ExprRef<'tcx>,
+        arg: Box<Expr<'tcx>>,
     }, // NOT overloaded!
     Binary {
         op: BinOp,
-        lhs: ExprRef<'tcx>,
-        rhs: ExprRef<'tcx>,
+        lhs: Box<Expr<'tcx>>,
+        rhs: Box<Expr<'tcx>>,
     }, // NOT overloaded!
     LogicalOp {
         op: LogicalOp,
-        lhs: ExprRef<'tcx>,
-        rhs: ExprRef<'tcx>,
+        lhs: Box<Expr<'tcx>>,
+        rhs: Box<Expr<'tcx>>,
     }, // NOT overloaded!
     // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
     Unary {
         op: UnOp,
-        arg: ExprRef<'tcx>,
+        arg: Box<Expr<'tcx>>,
     }, // NOT overloaded!
     Cast {
-        source: ExprRef<'tcx>,
+        source: Box<Expr<'tcx>>,
     },
     Use {
-        source: ExprRef<'tcx>,
+        source: Box<Expr<'tcx>>,
     }, // Use a lexpr to get a vexpr.
     NeverToAny {
-        source: ExprRef<'tcx>,
+        source: Box<Expr<'tcx>>,
     },
     Pointer {
         cast: PointerCast,
-        source: ExprRef<'tcx>,
+        source: Box<Expr<'tcx>>,
     },
     Loop {
-        body: ExprRef<'tcx>,
+        body: Box<Expr<'tcx>>,
     },
     Match {
-        scrutinee: ExprRef<'tcx>,
+        scrutinee: Box<Expr<'tcx>>,
         arms: Vec<Arm<'tcx>>,
     },
     Block {
-        body: &'tcx hir::Block<'tcx>,
+        body: Block<'tcx>,
     },
     Assign {
-        lhs: ExprRef<'tcx>,
-        rhs: ExprRef<'tcx>,
+        lhs: Box<Expr<'tcx>>,
+        rhs: Box<Expr<'tcx>>,
     },
     AssignOp {
         op: BinOp,
-        lhs: ExprRef<'tcx>,
-        rhs: ExprRef<'tcx>,
+        lhs: Box<Expr<'tcx>>,
+        rhs: Box<Expr<'tcx>>,
     },
     Field {
-        lhs: ExprRef<'tcx>,
+        lhs: Box<Expr<'tcx>>,
         name: Field,
     },
     Index {
-        lhs: ExprRef<'tcx>,
-        index: ExprRef<'tcx>,
+        lhs: Box<Expr<'tcx>>,
+        index: Box<Expr<'tcx>>,
     },
     VarRef {
         id: hir::HirId,
     },
     Borrow {
         borrow_kind: BorrowKind,
-        arg: ExprRef<'tcx>,
+        arg: Box<Expr<'tcx>>,
     },
     /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
     AddressOf {
         mutability: hir::Mutability,
-        arg: ExprRef<'tcx>,
+        arg: Box<Expr<'tcx>>,
     },
     Break {
         label: region::Scope,
-        value: Option<ExprRef<'tcx>>,
+        value: Option<Box<Expr<'tcx>>>,
     },
     Continue {
         label: region::Scope,
     },
     Return {
-        value: Option<ExprRef<'tcx>>,
+        value: Option<Box<Expr<'tcx>>>,
     },
     ConstBlock {
         value: &'tcx Const<'tcx>,
     },
     Repeat {
-        value: ExprRef<'tcx>,
+        value: Box<Expr<'tcx>>,
         count: &'tcx Const<'tcx>,
     },
     Array {
-        fields: Vec<ExprRef<'tcx>>,
+        fields: Vec<Expr<'tcx>>,
     },
     Tuple {
-        fields: Vec<ExprRef<'tcx>>,
+        fields: Vec<Expr<'tcx>>,
     },
     Adt {
         adt_def: &'tcx AdtDef,
         /// Bar::<T> { ... }`.
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
 
-        fields: Vec<FieldExprRef<'tcx>>,
+        fields: Vec<FieldExpr<'tcx>>,
         base: Option<FruInfo<'tcx>>,
     },
     PlaceTypeAscription {
-        source: ExprRef<'tcx>,
+        source: Box<Expr<'tcx>>,
         /// Type that the user gave to this expression
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
     ValueTypeAscription {
-        source: ExprRef<'tcx>,
+        source: Box<Expr<'tcx>>,
         /// Type that the user gave to this expression
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
     Closure {
         closure_id: DefId,
         substs: UpvarSubsts<'tcx>,
-        upvars: Vec<ExprRef<'tcx>>,
+        upvars: Vec<Expr<'tcx>>,
         movability: Option<hir::Movability>,
     },
     Literal {
     ThreadLocalRef(DefId),
     LlvmInlineAsm {
         asm: &'tcx hir::LlvmInlineAsmInner,
-        outputs: Vec<ExprRef<'tcx>>,
-        inputs: Vec<ExprRef<'tcx>>,
+        outputs: Vec<Expr<'tcx>>,
+        inputs: Vec<Expr<'tcx>>,
     },
     Yield {
-        value: ExprRef<'tcx>,
+        value: Box<Expr<'tcx>>,
     },
 }
 
 #[derive(Clone, Debug)]
-crate enum ExprRef<'tcx> {
-    Thir(&'tcx hir::Expr<'tcx>),
-    Mirror(Box<Expr<'tcx>>),
-}
-
-#[derive(Clone, Debug)]
-crate struct FieldExprRef<'tcx> {
+crate struct FieldExpr<'tcx> {
     crate name: Field,
-    crate expr: ExprRef<'tcx>,
+    crate expr: Expr<'tcx>,
 }
 
 #[derive(Clone, Debug)]
 crate struct FruInfo<'tcx> {
-    crate base: ExprRef<'tcx>,
+    crate base: Box<Expr<'tcx>>,
     crate field_types: Vec<Ty<'tcx>>,
 }
 
 crate struct Arm<'tcx> {
     crate pattern: Pat<'tcx>,
     crate guard: Option<Guard<'tcx>>,
-    crate body: ExprRef<'tcx>,
+    crate body: Expr<'tcx>,
     crate lint_level: LintLevel,
     crate scope: region::Scope,
     crate span: Span,
 
 #[derive(Clone, Debug)]
 crate enum Guard<'tcx> {
-    If(ExprRef<'tcx>),
-    IfLet(Pat<'tcx>, ExprRef<'tcx>),
+    If(Box<Expr<'tcx>>),
+    IfLet(Pat<'tcx>, Box<Expr<'tcx>>),
 }
 
 #[derive(Copy, Clone, Debug)]
     Or,
 }
 
-impl<'tcx> ExprRef<'tcx> {
-    crate fn span(&self) -> Span {
-        match self {
-            ExprRef::Thir(expr) => expr.span,
-            ExprRef::Mirror(expr) => expr.span,
-        }
-    }
-}
-
 #[derive(Clone, Debug)]
 crate enum InlineAsmOperand<'tcx> {
     In {
         reg: InlineAsmRegOrRegClass,
-        expr: ExprRef<'tcx>,
+        expr: Expr<'tcx>,
     },
     Out {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        expr: Option<ExprRef<'tcx>>,
+        expr: Option<Expr<'tcx>>,
     },
     InOut {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        expr: ExprRef<'tcx>,
+        expr: Expr<'tcx>,
     },
     SplitInOut {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        in_expr: ExprRef<'tcx>,
-        out_expr: Option<ExprRef<'tcx>>,
+        in_expr: Expr<'tcx>,
+        out_expr: Option<Expr<'tcx>>,
     },
     Const {
-        expr: ExprRef<'tcx>,
+        expr: Expr<'tcx>,
     },
     SymFn {
-        expr: ExprRef<'tcx>,
+        expr: Expr<'tcx>,
     },
     SymStatic {
         def_id: DefId,
     },
 }
-
-///////////////////////////////////////////////////////////////////////////
-// The Mirror trait
-
-/// "Mirroring" is the process of converting from a HIR type into one
-/// of the THIR types defined in this file. This is basically a "on
-/// the fly" desugaring step that hides a lot of the messiness in the
-/// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
-/// `Expr<'tcx>`.
-///
-/// Mirroring is gradual: when you mirror an outer expression like `e1
-/// + e2`, the references to the inner expressions `e1` and `e2` are
-/// `ExprRef<'tcx>` instances, and they may or may not be eagerly
-/// mirrored. This allows a single AST node from the compiler to
-/// expand into one or more Thir nodes, which lets the Thir nodes be
-/// simpler.
-crate trait Mirror<'tcx> {
-    type Output;
-
-    fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
-}
-
-impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
-    type Output = Expr<'tcx>;
-
-    fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
-        self
-    }
-}
-
-impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
-    type Output = Expr<'tcx>;
-
-    fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
-        match self {
-            ExprRef::Thir(h) => h.make_mirror(hir),
-            ExprRef::Mirror(m) => *m,
-        }
-    }
-}
-
-impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
-    type Output = Stmt<'tcx>;
-
-    fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
-        self
-    }
-}
-
-impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
-    type Output = Stmt<'tcx>;
-
-    fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
-        match self {
-            StmtRef::Mirror(m) => *m,
-        }
-    }
-}
-
-impl<'tcx> Mirror<'tcx> for Block<'tcx> {
-    type Output = Block<'tcx>;
-
-    fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> {
-        self
-    }
-}