about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2019-10-20 16:09:36 -0400
committerSantiago Pastorino <spastorino@gmail.com>2019-10-22 10:33:30 -0300
commit190802cfca41df76fd7ef45d2915c89938a5904a (patch)
tree1c3348f5c02bf974be99a51a8b2c7a9f48b15a46
parent270541221f25b761d6aeb0e1900d807755857774 (diff)
downloadrust-190802cfca41df76fd7ef45d2915c89938a5904a.tar.gz
rust-190802cfca41df76fd7ef45d2915c89938a5904a.zip
Pattern match over PlaceRef rather than Place
This prepares the code base for when projection is interned. Place's
projection field is going to be `&List<PlaceElem<'tcx>>` so we won't be
able to pattern match against it.
-rw-r--r--src/librustc/mir/mod.rs16
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs5
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs84
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs5
-rw-r--r--src/librustc_codegen_ssa/mir/statement.rs11
-rw-r--r--src/librustc_mir/borrow_check/borrow_set.rs5
-rw-r--r--src/librustc_mir/borrow_check/conflict_errors.rs313
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs13
-rw-r--r--src/librustc_mir/borrow_check/mod.rs113
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs70
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs13
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs32
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs156
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs34
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs10
-rw-r--r--src/librustc_mir/borrow_check/used_muts.rs9
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs22
-rw-r--r--src/librustc_mir/build/matches/mod.rs2
-rw-r--r--src/librustc_mir/build/scope.rs71
-rw-r--r--src/librustc_mir/dataflow/impls/storage_liveness.rs6
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs2
-rw-r--r--src/librustc_mir/transform/check_consts/qualifs.rs4
-rw-r--r--src/librustc_mir/transform/check_consts/resolver.rs17
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs20
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs4
-rw-r--r--src/librustc_mir/transform/const_prop.rs37
-rw-r--r--src/librustc_mir/transform/copy_prop.rs115
-rw-r--r--src/librustc_mir/transform/generator.rs23
-rw-r--r--src/librustc_mir/transform/inline.rs40
-rw-r--r--src/librustc_mir/transform/instcombine.rs43
-rw-r--r--src/librustc_mir/transform/promote_consts.rs47
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs55
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs4
-rw-r--r--src/librustc_mir/transform/remove_noop_landing_pads.rs15
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs38
-rw-r--r--src/librustc_mir/transform/uniform_array_move_out.rs69
-rw-r--r--src/librustc_mir/util/alignment.rs4
37 files changed, 707 insertions, 820 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index ecda524db9a..6e509f51754 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1908,15 +1908,15 @@ impl<'tcx> Place<'tcx> {
     //
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local_or_deref_local(&self) -> Option<Local> {
-        match self {
-            Place {
-                base: PlaceBase::Local(local),
-                projection: box [],
+        match self.as_ref() {
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: &[],
             } |
-            Place {
-                base: PlaceBase::Local(local),
-                projection: box [ProjectionElem::Deref],
-            } => Some(*local),
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: &[ProjectionElem::Deref],
+            } => Some(local),
             _ => None,
         }
     }
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index ea1cf926fcc..604deffcf94 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -191,10 +191,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                     location: Location) {
         debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue);
 
-        if let mir::Place {
-            base: mir::PlaceBase::Local(index),
-            projection: box [],
-        } = *place {
+        if let Some(index) = place.as_local() {
             self.assign(index, location);
             let decl_span = self.fx.mir.local_decls[index].source_info.span;
             if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index dc77d025c00..28441cae26e 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -2,7 +2,7 @@ use rustc_index::vec::Idx;
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable, Instance};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
-use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
+use rustc::mir::{self, PlaceBase, Static, StaticKind};
 use rustc::mir::interpret::PanicInfo;
 use rustc_target::abi::call::{ArgType, FnType, PassMode};
 use rustc_target::spec::abi::Abi;
@@ -630,53 +630,43 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // checked by const-qualification, which also
                 // promotes any complex rvalues to constants.
                 if i == 2 && intrinsic.unwrap().starts_with("simd_shuffle") {
-                    match *arg {
+                    match arg {
                         // The shuffle array argument is usually not an explicit constant,
                         // but specified directly in the code. This means it gets promoted
                         // and we can then extract the value by evaluating the promoted.
-                        mir::Operand::Copy(
-                            Place {
-                                base: PlaceBase::Static(box Static {
-                                    kind: StaticKind::Promoted(promoted, _),
+                        mir::Operand::Copy(place) | mir::Operand::Move(place) => {
+                            if let mir::PlaceRef {
+                                base:
+                                    &PlaceBase::Static(box Static {
+                                        kind: StaticKind::Promoted(promoted, _),
+                                        ty,
+                                        def_id: _,
+                                    }),
+                                projection: &[],
+                            } = place.as_ref()
+                            {
+                                let param_env = ty::ParamEnv::reveal_all();
+                                let cid = mir::interpret::GlobalId {
+                                    instance: self.instance,
+                                    promoted: Some(promoted),
+                                };
+                                let c = bx.tcx().const_eval(param_env.and(cid));
+                                let (llval, ty) = self.simd_shuffle_indices(
+                                    &bx,
+                                    terminator.source_info.span,
                                     ty,
-                                    def_id: _,
-                                }),
-                                projection: box [],
+                                    c,
+                                );
+                                return OperandRef {
+                                    val: Immediate(llval),
+                                    layout: bx.layout_of(ty),
+                                };
+                            } else {
+                                span_bug!(span, "shuffle indices must be constant");
                             }
-                        ) |
-                        mir::Operand::Move(
-                            Place {
-                                base: PlaceBase::Static(box Static {
-                                    kind: StaticKind::Promoted(promoted, _),
-                                    ty,
-                                    def_id: _,
-                                }),
-                                projection: box [],
-                            }
-                        ) => {
-                            let param_env = ty::ParamEnv::reveal_all();
-                            let cid = mir::interpret::GlobalId {
-                                instance: self.instance,
-                                promoted: Some(promoted),
-                            };
-                            let c = bx.tcx().const_eval(param_env.and(cid));
-                            let (llval, ty) = self.simd_shuffle_indices(
-                                &bx,
-                                terminator.source_info.span,
-                                ty,
-                                c,
-                            );
-                            return OperandRef {
-                                val: Immediate(llval),
-                                layout: bx.layout_of(ty),
-                            };
-
-                        }
-                        mir::Operand::Copy(_) |
-                        mir::Operand::Move(_) => {
-                            span_bug!(span, "shuffle indices must be constant");
                         }
-                        mir::Operand::Constant(ref constant) => {
+
+                        mir::Operand::Constant(constant) => {
                             let c = self.eval_mir_constant(constant);
                             let (llval, ty) = self.simd_shuffle_indices(
                                 &bx,
@@ -1117,10 +1107,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         if fn_ret.is_ignore() {
             return ReturnDest::Nothing;
         }
-        let dest = if let mir::Place {
-            base: mir::PlaceBase::Local(index),
-            projection: box [],
-        } = *dest {
+        let dest = if let Some(index) = dest.as_local() {
             match self.locals[index] {
                 LocalRef::Place(dest) => dest,
                 LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
@@ -1178,10 +1165,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         src: &mir::Operand<'tcx>,
         dst: &mir::Place<'tcx>
     ) {
-        if let mir::Place {
-            base: mir::PlaceBase::Local(index),
-            projection: box [],
-        } = *dst {
+        if let Some(index) = dst.as_local() {
             match self.locals[index] {
                 LocalRef::Place(place) => self.codegen_transmute_into(bx, src, place),
                 LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 7e662ea37db..1608f222bc6 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -530,10 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ) -> Bx::Value {
         // ZST are passed as operands and require special handling
         // because codegen_place() panics if Local is operand.
-        if let mir::Place {
-            base: mir::PlaceBase::Local(index),
-            projection: box [],
-        } = *place {
+        if let Some(index) = place.as_local() {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if let ty::Array(_, n) = op.layout.ty.kind {
                     let n = n.eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index dab7dfc0417..43d5c2570b7 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -17,11 +17,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         self.set_debug_loc(&mut bx, statement.source_info);
         match statement.kind {
             mir::StatementKind::Assign(box(ref place, ref rvalue)) => {
-                if let mir::Place {
-                    base: mir::PlaceBase::Local(index),
-                    projection: box [],
-                } = place {
-                    match self.locals[*index] {
+                if let Some(index) = place.as_local() {
+                    match self.locals[index] {
                         LocalRef::Place(cg_dest) => {
                             self.codegen_rvalue(bx, cg_dest, rvalue)
                         }
@@ -30,7 +27,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         }
                         LocalRef::Operand(None) => {
                             let (mut bx, operand) = self.codegen_rvalue_operand(bx, rvalue);
-                            if let Some(name) = self.mir.local_decls[*index].name {
+                            if let Some(name) = self.mir.local_decls[index].name {
                                 match operand.val {
                                     OperandValue::Ref(x, ..) |
                                     OperandValue::Immediate(x) => {
@@ -44,7 +41,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     }
                                 }
                             }
-                            self.locals[*index] = LocalRef::Operand(Some(operand));
+                            self.locals[index] = LocalRef::Operand(Some(operand));
                             bx
                         }
                         LocalRef::Operand(Some(op)) => {
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index 7dd1db3b7bd..98641031c17 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -315,10 +315,7 @@ impl<'a, 'tcx> GatherBorrows<'a, 'tcx> {
         //    TEMP = &foo
         //
         // so extract `temp`.
-        let temp = if let &mir::Place {
-            base: mir::PlaceBase::Local(temp),
-            projection: box [],
-        } = assigned_place {
+        let temp = if let Some(temp) = assigned_place.as_local() {
             temp
         } else {
             span_bug!(
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index 4c469a82ac3..9b7a5caa6d9 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -239,11 +239,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
                     }
                 }
-                let span = if let Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                } = place {
-                    let decl = &self.body.local_decls[*local];
+                let span = if let Some(local) = place.as_local() {
+                    let decl = &self.body.local_decls[local];
                     Some(decl.source_info.span)
                 } else {
                     None
@@ -611,7 +608,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     projection,
                 } = first_borrowed_place;
 
-                let mut cursor = &**projection;
+                let mut cursor = projection.as_ref();
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
@@ -635,7 +632,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     projection,
                 } = second_borrowed_place;
 
-                let mut cursor = &**projection;
+                let mut cursor = projection.as_ref();
                 while let [proj_base @ .., elem] = cursor {
                     cursor = proj_base;
 
@@ -1124,26 +1121,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         };
 
         let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
-            let local_kind = match borrow.borrowed_place {
-                Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                } => {
-                    match self.body.local_kind(local) {
-                        LocalKind::ReturnPointer
-                        | LocalKind::Temp => bug!("temporary or return pointer with a name"),
-                        LocalKind::Var => "local variable ",
-                        LocalKind::Arg
-                        if !self.upvars.is_empty()
-                            && local == Local::new(1) => {
-                            "variable captured by `move` "
-                        }
-                        LocalKind::Arg => {
-                            "function parameter "
-                        }
+            let local_kind = if let Some(local) = borrow.borrowed_place.as_local() {
+                match self.body.local_kind(local) {
+                    LocalKind::ReturnPointer
+                    | LocalKind::Temp => bug!("temporary or return pointer with a name"),
+                    LocalKind::Var => "local variable ",
+                    LocalKind::Arg
+                    if !self.upvars.is_empty()
+                        && local == Local::new(1) => {
+                        "variable captured by `move` "
+                    }
+                    LocalKind::Arg => {
+                        "function parameter "
                     }
                 }
-                _ => "local data ",
+            } else {
+                "local data "
             };
             (
                 format!("{}`{}`", local_kind, place_desc),
@@ -1480,10 +1473,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         assigned_span: Span,
         err_place: &Place<'tcx>,
     ) {
-        let (from_arg, local_decl) = if let Place {
-            base: PlaceBase::Local(local),
-            projection: box [],
-        } = *err_place {
+        let (from_arg, local_decl) = if let Some(local) = err_place.as_local() {
             if let LocalKind::Arg = self.body.local_kind(local) {
                 (true, Some(&self.body.local_decls[local]))
             } else {
@@ -1643,11 +1633,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 reservation
             );
             // Check that the initial assignment of the reserve location is into a temporary.
-            let mut target = *match reservation {
-                Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                } if self.body.local_kind(*local) == LocalKind::Temp => local,
+            let mut target = match reservation.as_local() {
+                Some(local) if self.body.local_kind(local) == LocalKind::Temp => local,
                 _ => return None,
             };
 
@@ -1659,127 +1646,122 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
                     target, stmt
                 );
-                if let StatementKind::Assign(
-                    box(
-                        Place {
-                            base: PlaceBase::Local(assigned_to),
-                            projection: box [],
-                        },
-                        rvalue
-                    )
-                ) = &stmt.kind {
-                    debug!(
-                        "annotate_argument_and_return_for_borrow: assigned_to={:?} \
-                         rvalue={:?}",
-                        assigned_to, rvalue
-                    );
-                    // Check if our `target` was captured by a closure.
-                    if let Rvalue::Aggregate(
-                        box AggregateKind::Closure(def_id, substs),
-                        operands,
-                    ) = rvalue
-                    {
-                        for operand in operands {
-                            let assigned_from = match operand {
-                                Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
+                if let StatementKind::Assign(box(place, rvalue)) = &stmt.kind {
+                    if let Some(assigned_to) = place.as_local() {
+                        debug!(
+                            "annotate_argument_and_return_for_borrow: assigned_to={:?} \
+                             rvalue={:?}",
+                            assigned_to, rvalue
+                        );
+                        // Check if our `target` was captured by a closure.
+                        if let Rvalue::Aggregate(
+                            box AggregateKind::Closure(def_id, substs),
+                            operands,
+                        ) = rvalue
+                        {
+                            for operand in operands {
+                                let assigned_from = match operand {
+                                    Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
+                                        assigned_from
+                                    }
+                                    _ => continue,
+                                };
+                                debug!(
+                                    "annotate_argument_and_return_for_borrow: assigned_from={:?}",
                                     assigned_from
-                                }
-                                _ => continue,
-                            };
-                            debug!(
-                                "annotate_argument_and_return_for_borrow: assigned_from={:?}",
-                                assigned_from
-                            );
-
-                            // Find the local from the operand.
-                            let assigned_from_local = match assigned_from.local_or_deref_local() {
-                                Some(local) => local,
-                                None => continue,
-                            };
+                                );
 
-                            if assigned_from_local != target {
-                                continue;
-                            }
+                                // Find the local from the operand.
+                                let assigned_from_local = match assigned_from.local_or_deref_local()
+                                {
+                                    Some(local) => local,
+                                    None => continue,
+                                };
 
-                            // If a closure captured our `target` and then assigned
-                            // into a place then we should annotate the closure in
-                            // case it ends up being assigned into the return place.
-                            annotated_closure = self.annotate_fn_sig(
-                                *def_id,
-                                self.infcx.closure_sig(*def_id, *substs),
-                            );
-                            debug!(
-                                "annotate_argument_and_return_for_borrow: \
-                                 annotated_closure={:?} assigned_from_local={:?} \
-                                 assigned_to={:?}",
-                                annotated_closure, assigned_from_local, assigned_to
-                            );
+                                if assigned_from_local != target {
+                                    continue;
+                                }
 
-                            if *assigned_to == mir::RETURN_PLACE {
-                                // If it was assigned directly into the return place, then
-                                // return now.
-                                return annotated_closure;
-                            } else {
-                                // Otherwise, update the target.
-                                target = *assigned_to;
+                                // If a closure captured our `target` and then assigned
+                                // into a place then we should annotate the closure in
+                                // case it ends up being assigned into the return place.
+                                annotated_closure = self.annotate_fn_sig(
+                                    *def_id,
+                                    self.infcx.closure_sig(*def_id, *substs),
+                                );
+                                debug!(
+                                    "annotate_argument_and_return_for_borrow: \
+                                     annotated_closure={:?} assigned_from_local={:?} \
+                                     assigned_to={:?}",
+                                    annotated_closure, assigned_from_local, assigned_to
+                                );
+
+                                if assigned_to == mir::RETURN_PLACE {
+                                    // If it was assigned directly into the return place, then
+                                    // return now.
+                                    return annotated_closure;
+                                } else {
+                                    // Otherwise, update the target.
+                                    target = assigned_to;
+                                }
                             }
-                        }
 
-                        // If none of our closure's operands matched, then skip to the next
-                        // statement.
-                        continue;
-                    }
+                            // If none of our closure's operands matched, then skip to the next
+                            // statement.
+                            continue;
+                        }
 
-                    // Otherwise, look at other types of assignment.
-                    let assigned_from = match rvalue {
-                        Rvalue::Ref(_, _, assigned_from) => assigned_from,
-                        Rvalue::Use(operand) => match operand {
-                            Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
-                                assigned_from
-                            }
+                        // Otherwise, look at other types of assignment.
+                        let assigned_from = match rvalue {
+                            Rvalue::Ref(_, _, assigned_from) => assigned_from,
+                            Rvalue::Use(operand) => match operand {
+                                Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
+                                    assigned_from
+                                }
+                                _ => continue,
+                            },
                             _ => continue,
-                        },
-                        _ => continue,
-                    };
-                    debug!(
-                        "annotate_argument_and_return_for_borrow: \
-                         assigned_from={:?}",
-                        assigned_from,
-                    );
+                        };
+                        debug!(
+                            "annotate_argument_and_return_for_borrow: \
+                             assigned_from={:?}",
+                            assigned_from,
+                        );
 
-                    // Find the local from the rvalue.
-                    let assigned_from_local = match assigned_from.local_or_deref_local() {
-                        Some(local) => local,
-                        None => continue,
-                    };
-                    debug!(
-                        "annotate_argument_and_return_for_borrow: \
-                         assigned_from_local={:?}",
-                        assigned_from_local,
-                    );
+                        // Find the local from the rvalue.
+                        let assigned_from_local = match assigned_from.local_or_deref_local() {
+                            Some(local) => local,
+                            None => continue,
+                        };
+                        debug!(
+                            "annotate_argument_and_return_for_borrow: \
+                             assigned_from_local={:?}",
+                            assigned_from_local,
+                        );
 
-                    // Check if our local matches the target - if so, we've assigned our
-                    // borrow to a new place.
-                    if assigned_from_local != target {
-                        continue;
-                    }
+                        // Check if our local matches the target - if so, we've assigned our
+                        // borrow to a new place.
+                        if assigned_from_local != target {
+                            continue;
+                        }
 
-                    // If we assigned our `target` into a new place, then we should
-                    // check if it was the return place.
-                    debug!(
-                        "annotate_argument_and_return_for_borrow: \
-                         assigned_from_local={:?} assigned_to={:?}",
-                        assigned_from_local, assigned_to
-                    );
-                    if *assigned_to == mir::RETURN_PLACE {
-                        // If it was then return the annotated closure if there was one,
-                        // else, annotate this function.
-                        return annotated_closure.or_else(fallback);
-                    }
+                        // If we assigned our `target` into a new place, then we should
+                        // check if it was the return place.
+                        debug!(
+                            "annotate_argument_and_return_for_borrow: \
+                             assigned_from_local={:?} assigned_to={:?}",
+                            assigned_from_local, assigned_to
+                        );
+                        if assigned_to == mir::RETURN_PLACE {
+                            // If it was then return the annotated closure if there was one,
+                            // else, annotate this function.
+                            return annotated_closure.or_else(fallback);
+                        }
 
-                    // If we didn't assign into the return place, then we just update
-                    // the target.
-                    target = *assigned_to;
+                        // If we didn't assign into the return place, then we just update
+                        // the target.
+                        target = assigned_to;
+                    }
                 }
             }
 
@@ -1790,38 +1772,37 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 target, terminator
             );
             if let TerminatorKind::Call {
-                destination: Some((Place {
-                    base: PlaceBase::Local(assigned_to),
-                    projection: box [],
-                }, _)),
+                destination: Some((place, _)),
                 args,
                 ..
             } = &terminator.kind
             {
-                debug!(
-                    "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
-                    assigned_to, args
-                );
-                for operand in args {
-                    let assigned_from = match operand {
-                        Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
-                            assigned_from
-                        }
-                        _ => continue,
-                    };
+                if let Some(assigned_to) = place.as_local() {
                     debug!(
-                        "annotate_argument_and_return_for_borrow: assigned_from={:?}",
-                        assigned_from,
+                        "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
+                        assigned_to, args
                     );
-
-                    if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
+                    for operand in args {
+                        let assigned_from = match operand {
+                            Operand::Copy(assigned_from) | Operand::Move(assigned_from) => {
+                                assigned_from
+                            }
+                            _ => continue,
+                        };
                         debug!(
-                            "annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
-                            assigned_from_local,
+                            "annotate_argument_and_return_for_borrow: assigned_from={:?}",
+                            assigned_from,
                         );
 
-                        if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
-                            return annotated_closure.or_else(fallback);
+                        if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
+                            debug!(
+                                "annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
+                                assigned_from_local,
+                            );
+
+                            if assigned_to == mir::RETURN_PLACE && assigned_from_local == target {
+                                return annotated_closure.or_else(fallback);
+                            }
                         }
                     }
                 }
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 5e0727d5157..4036e9db33b 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -838,12 +838,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             .get(location.statement_index)
         {
             Some(&Statement {
-                kind: StatementKind::Assign(box(Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                }, _)),
+                kind: StatementKind::Assign(box(ref place, _)),
                 ..
-            }) => local,
+            }) => {
+                if let Some(local) = place.as_local() {
+                    local
+                } else {
+                    return OtherUse(use_span);
+                }
+            }
             _ => return OtherUse(use_span),
         };
 
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 75d4b56fdb7..c3369e87215 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1133,15 +1133,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // Special case: you can assign a immutable local variable
         // (e.g., `x = ...`) so long as it has never been initialized
         // before (at this point in the flow).
-        if let Place {
-            base: PlaceBase::Local(local),
-            projection: box [],
-        } = place_span.0 {
-            if let Mutability::Not = self.body.local_decls[*local].mutability {
+        if let Some(local) = place_span.0.as_local() {
+            if let Mutability::Not = self.body.local_decls[local].mutability {
                 // check for reassignments to immutable local variables
                 self.check_if_reassignment_to_immutable_state(
                     location,
-                    *local,
+                    local,
                     place_span,
                     flow_state,
                 );
@@ -1288,60 +1285,58 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // captures of a closure are copied/moved directly
         // when generating MIR.
         match *operand {
-            Operand::Move(Place {
-                base: PlaceBase::Local(local),
-                projection: box [],
-            }) |
-            Operand::Copy(Place {
-                base: PlaceBase::Local(local),
-                projection: box [],
-            }) if self.body.local_decls[local].is_user_variable.is_none() => {
-                if self.body.local_decls[local].ty.is_mutable_ptr() {
-                    // The variable will be marked as mutable by the borrow.
-                    return;
-                }
-                // This is an edge case where we have a `move` closure
-                // inside a non-move closure, and the inner closure
-                // contains a mutation:
-                //
-                // let mut i = 0;
-                // || { move || { i += 1; }; };
-                //
-                // In this case our usual strategy of assuming that the
-                // variable will be captured by mutable reference is
-                // wrong, since `i` can be copied into the inner
-                // closure from a shared reference.
-                //
-                // As such we have to search for the local that this
-                // capture comes from and mark it as being used as mut.
-
-                let temp_mpi = self.move_data.rev_lookup.find_local(local);
-                let init = if let [init_index] = *self.move_data.init_path_map[temp_mpi] {
-                    &self.move_data.inits[init_index]
-                } else {
-                    bug!("temporary should be initialized exactly once")
-                };
-
-                let loc = match init.location {
-                    InitLocation::Statement(stmt) => stmt,
-                    _ => bug!("temporary initialized in arguments"),
-                };
-
-                let bbd = &self.body[loc.block];
-                let stmt = &bbd.statements[loc.statement_index];
-                debug!("temporary assigned in: stmt={:?}", stmt);
-
-                if let StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref source))) = stmt.kind {
-                    propagate_closure_used_mut_place(self, source);
-                } else {
-                    bug!("closures should only capture user variables \
-                        or references to user variables");
+            Operand::Move(ref place) | Operand::Copy(ref place) => {
+                match place.as_local() {
+                    Some(local) if self.body.local_decls[local].is_user_variable.is_none() => {
+                        if self.body.local_decls[local].ty.is_mutable_ptr() {
+                            // The variable will be marked as mutable by the borrow.
+                            return;
+                        }
+                        // This is an edge case where we have a `move` closure
+                        // inside a non-move closure, and the inner closure
+                        // contains a mutation:
+                        //
+                        // let mut i = 0;
+                        // || { move || { i += 1; }; };
+                        //
+                        // In this case our usual strategy of assuming that the
+                        // variable will be captured by mutable reference is
+                        // wrong, since `i` can be copied into the inner
+                        // closure from a shared reference.
+                        //
+                        // As such we have to search for the local that this
+                        // capture comes from and mark it as being used as mut.
+
+                        let temp_mpi = self.move_data.rev_lookup.find_local(local);
+                        let init = if let [init_index] = *self.move_data.init_path_map[temp_mpi] {
+                            &self.move_data.inits[init_index]
+                        } else {
+                            bug!("temporary should be initialized exactly once")
+                        };
+
+                        let loc = match init.location {
+                            InitLocation::Statement(stmt) => stmt,
+                            _ => bug!("temporary initialized in arguments"),
+                        };
+
+                        let bbd = &self.body[loc.block];
+                        let stmt = &bbd.statements[loc.statement_index];
+                        debug!("temporary assigned in: stmt={:?}", stmt);
+
+                        if let StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref source))) =
+                            stmt.kind
+                        {
+                            propagate_closure_used_mut_place(self, source);
+                        } else {
+                            bug!(
+                                "closures should only capture user variables \
+                                 or references to user variables"
+                            );
+                        }
+                    }
+                    _ => propagate_closure_used_mut_place(self, place),
                 }
             }
-            Operand::Move(ref place)
-            | Operand::Copy(ref place) => {
-                propagate_closure_used_mut_place(self, place);
-            }
             Operand::Constant(..) => {}
         }
     }
@@ -1702,7 +1697,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
 
         // None case => assigning to `x` does not require `x` be initialized.
-        let mut cursor = &*place.projection;
+        let mut cursor = &*place.projection.as_ref();
         while let [proj_base @ .., elem] = cursor {
             cursor = proj_base;
 
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 431361fa5a8..d9e958d9450 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -89,45 +89,41 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 // If that ever stops being the case, then the ever initialized
                 // flow could be used.
                 if let Some(StatementKind::Assign(
-                    box(
-                        Place {
-                            base: PlaceBase::Local(local),
-                            projection: box [],
-                        },
-                        Rvalue::Use(Operand::Move(move_from))
-                    )
+                    box(place, Rvalue::Use(Operand::Move(move_from)))
                 )) = self.body.basic_blocks()[location.block]
                     .statements
                     .get(location.statement_index)
                     .map(|stmt| &stmt.kind)
                 {
-                    let local_decl = &self.body.local_decls[*local];
-                    // opt_match_place is the
-                    // match_span is the span of the expression being matched on
-                    // match *x.y { ... }        match_place is Some(*x.y)
-                    //       ^^^^                match_span is the span of *x.y
-                    //
-                    // opt_match_place is None for let [mut] x = ... statements,
-                    // whether or not the right-hand side is a place expression
-                    if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
-                        opt_match_place: Some((ref opt_match_place, match_span)),
-                        binding_mode: _,
-                        opt_ty_info: _,
-                        pat_span: _,
-                    }))) = local_decl.is_user_variable
-                    {
-                        let stmt_source_info = self.body.source_info(location);
-                        self.append_binding_error(
-                            grouped_errors,
-                            kind,
-                            original_path,
-                            move_from,
-                            *local,
-                            opt_match_place,
-                            match_span,
-                            stmt_source_info.span,
-                        );
-                        return;
+                    if let Some(local) = place.as_local() {
+                        let local_decl = &self.body.local_decls[local];
+                        // opt_match_place is the
+                        // match_span is the span of the expression being matched on
+                        // match *x.y { ... }        match_place is Some(*x.y)
+                        //       ^^^^                match_span is the span of *x.y
+                        //
+                        // opt_match_place is None for let [mut] x = ... statements,
+                        // whether or not the right-hand side is a place expression
+                        if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                            opt_match_place: Some((ref opt_match_place, match_span)),
+                            binding_mode: _,
+                            opt_ty_info: _,
+                            pat_span: _,
+                        }))) = local_decl.is_user_variable
+                        {
+                            let stmt_source_info = self.body.source_info(location);
+                            self.append_binding_error(
+                                grouped_errors,
+                                kind,
+                                original_path,
+                                move_from,
+                                local,
+                                opt_match_place,
+                                match_span,
+                                stmt_source_info.span,
+                            );
+                            return;
+                        }
                     }
                 }
 
@@ -307,11 +303,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All)
             .find_map(|p| self.is_upvar_field_projection(p));
 
-        let deref_base = match &deref_target_place.projection {
-            box [proj_base @ .., ProjectionElem::Deref] => {
+        let deref_base = match deref_target_place.projection.as_ref() {
+            &[ref proj_base @ .., ProjectionElem::Deref] => {
                 PlaceRef {
                     base: &deref_target_place.base,
-                    projection: proj_base,
+                    projection: &proj_base,
                 }
             }
             _ => bug!("deref_target_place is not a deref projection"),
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 8ab4020394f..68b33331a1f 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -49,10 +49,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 projection: [],
             } => {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if let Place {
-                    base: PlaceBase::Local(_),
-                    projection: box [],
-                } = access_place {
+                if access_place.as_local().is_some() {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
                     let name = self.body.local_decls[*local]
@@ -153,10 +150,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     }),
                 projection: [],
             } => {
-                if let Place {
-                    base: PlaceBase::Static(_),
-                    projection: box [],
-                } = access_place {
+                if let PlaceRef {
+                    base: &PlaceBase::Static(_),
+                    projection: &[],
+                } = access_place.as_ref() {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
                     reason = String::new();
                 } else {
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index b105664399a..cae303039a1 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -8,8 +8,8 @@ use rustc::infer::InferCtxt;
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
 use rustc::mir::{
-    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, ProjectionElem, Rvalue,
-    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
+    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, PlaceRef, ProjectionElem,
+    Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
 };
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, RegionVid, Ty};
@@ -211,14 +211,14 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
             // - if it's a deeper projection, we have to filter which
             //   of the borrows are killed: the ones whose `borrowed_place`
             //   conflicts with the `place`.
-            match place {
-                Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
+            match place.as_ref() {
+                PlaceRef {
+                    base: &PlaceBase::Local(local),
+                    projection: &[],
                 } |
-                Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [ProjectionElem::Deref],
+                PlaceRef {
+                    base: &PlaceBase::Local(local),
+                    projection: &[ProjectionElem::Deref],
                 } => {
                     debug!(
                         "Recording `killed` facts for borrows of local={:?} at location={:?}",
@@ -229,21 +229,21 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
                         all_facts,
                         self.borrow_set,
                         self.location_table,
-                        local,
+                        &local,
                         location,
                     );
                 }
 
-                Place {
-                    base: PlaceBase::Static(_),
+                PlaceRef {
+                    base: &PlaceBase::Static(_),
                     ..
                 } => {
                     // Ignore kills of static or static mut variables.
                 }
 
-                Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [.., _],
+                PlaceRef {
+                    base: &PlaceBase::Local(local),
+                    projection: &[.., _],
                 } => {
                     // Kill conflicting borrows of the innermost local.
                     debug!(
@@ -252,7 +252,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
                         local, location
                     );
 
-                    if let Some(borrow_indices) = self.borrow_set.local_map.get(local) {
+                    if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
                         for &borrow_index in borrow_indices {
                             let places_conflict = places_conflict::places_conflict(
                                 self.infcx.tcx,
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 59b2796db7a..26bead3047d 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -6,8 +6,8 @@ use crate::borrow_check::nll::region_infer::{Cause, RegionName};
 use crate::borrow_check::nll::ConstraintDescription;
 use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
 use rustc::mir::{
-    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, PlaceBase,
-    Rvalue, Statement, StatementKind, TerminatorKind,
+    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Body, Operand, Place, Rvalue,
+    Statement, StatementKind, TerminatorKind,
 };
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::adjustment::{PointerCast};
@@ -273,12 +273,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 let mut should_note_order = false;
                 if body.local_decls[local].name.is_some() {
                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
-                        if let Place {
-                            base: PlaceBase::Local(borrowed_local),
-                            projection: box [],
-                        } = place {
-                             if body.local_decls[*borrowed_local].name.is_some()
-                                && local != *borrowed_local
+                        if let Some(borrowed_local) = place.as_local() {
+                             if body.local_decls[borrowed_local].name.is_some()
+                                && local != borrowed_local
                             {
                                 should_note_order = true;
                             }
@@ -494,22 +491,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         // Just point to the function, to reduce the chance of overlapping spans.
                         let function_span = match func {
                             Operand::Constant(c) => c.span,
-                            Operand::Copy(Place {
-                                base: PlaceBase::Local(l),
-                                projection: box [],
-                            }) |
-                            Operand::Move(Place {
-                                base: PlaceBase::Local(l),
-                                projection: box [],
-                            }) => {
-                                let local_decl = &self.body.local_decls[*l];
-                                if local_decl.name.is_none() {
-                                    local_decl.source_info.span
+                            Operand::Copy(place) |
+                            Operand::Move(place) => {
+                                if let Some(l) = place.as_local() {
+                                    let local_decl = &self.body.local_decls[l];
+                                    if local_decl.name.is_none() {
+                                        local_decl.source_info.span
+                                    } else {
+                                        span
+                                    }
                                 } else {
                                     span
                                 }
                             }
-                            _ => span,
                         };
                         return (LaterUseKind::Call, function_span);
                     } else {
@@ -542,14 +536,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // it which simplifies the termination logic.
         let mut queue = vec![location];
         let mut target = if let Some(&Statement {
-            kind: StatementKind::Assign(box(Place {
-                base: PlaceBase::Local(local),
-                projection: box [],
-            }, _)),
+            kind: StatementKind::Assign(box(ref place, _)),
             ..
-        }) = stmt
-        {
-            local
+        }) = stmt {
+            if let Some(local) = place.as_local() {
+                local
+            } else {
+                return false;
+            }
         } else {
             return false;
         };
@@ -582,17 +576,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         // If we see a use, we should check whether it is our data, and if so
                         // update the place that we're looking for to that new place.
                         Rvalue::Use(operand) => match operand {
-                            Operand::Copy(Place {
-                                base: PlaceBase::Local(from),
-                                projection: box [],
-                            })
-                            | Operand::Move(Place {
-                                base: PlaceBase::Local(from),
-                                projection: box [],
-                            })
-                                if *from == target =>
-                            {
-                                target = into;
+                            Operand::Copy(place)
+                            | Operand::Move(place) => {
+                                if let Some(from) = place.as_local() {
+                                    if from == target {
+                                        target = into;
+                                    }
+                                }
                             }
                             _ => {}
                         },
@@ -601,28 +591,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         Rvalue::Cast(
                             CastKind::Pointer(PointerCast::Unsize), operand, ty
                         ) => match operand {
-                            Operand::Copy(Place {
-                                base: PlaceBase::Local(from),
-                                projection: box [],
-                            })
-                            | Operand::Move(Place {
-                                base: PlaceBase::Local(from),
-                                projection: box [],
-                            })
-                                if *from == target =>
-                            {
-                                debug!("was_captured_by_trait_object: ty={:?}", ty);
-                                // Check the type for a trait object.
-                                return match ty.kind {
-                                    // `&dyn Trait`
-                                    ty::Ref(_, ty, _) if ty.is_trait() => true,
-                                    // `Box<dyn Trait>`
-                                    _ if ty.is_box() && ty.boxed_ty().is_trait() => true,
-                                    // `dyn Trait`
-                                    _ if ty.is_trait() => true,
-                                    // Anything else.
-                                    _ => false,
-                                };
+                            Operand::Copy(place)
+                            | Operand::Move(place) => {
+                                if let Some(from) = place.as_local() {
+                                    if from == target {
+                                        debug!("was_captured_by_trait_object: ty={:?}", ty);
+                                        // Check the type for a trait object.
+                                        return match ty.kind {
+                                            // `&dyn Trait`
+                                            ty::Ref(_, ty, _) if ty.is_trait() => true,
+                                            // `Box<dyn Trait>`
+                                            _ if ty.is_box() && ty.boxed_ty().is_trait() => true,
+                                            // `dyn Trait`
+                                            _ if ty.is_trait() => true,
+                                            // Anything else.
+                                            _ => false,
+                                        };
+                                    }
+                                }
+                                return false;
                             }
                             _ => return false,
                         },
@@ -638,34 +625,33 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 debug!("was_captured_by_trait_object: terminator={:?}", terminator);
 
                 if let TerminatorKind::Call {
-                    destination: Some((Place {
-                        base: PlaceBase::Local(dest),
-                        projection: box [],
-                    }, block)),
+                    destination: Some((place, block)),
                     args,
                     ..
-                } = &terminator.kind
-                {
-                    debug!(
-                        "was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
-                        target, dest, args
-                    );
-                    // Check if one of the arguments to this function is the target place.
-                    let found_target = args.iter().any(|arg| {
-                        if let Operand::Move(Place {
-                            base: PlaceBase::Local(potential),
-                            projection: box [],
-                        }) = arg {
-                            *potential == target
-                        } else {
-                            false
-                        }
-                    });
+                } = &terminator.kind {
+                    if let Some(dest) = place.as_local() {
+                        debug!(
+                            "was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
+                            target, dest, args
+                        );
+                        // Check if one of the arguments to this function is the target place.
+                        let found_target = args.iter().any(|arg| {
+                            if let Operand::Move(place) = arg {
+                                if let Some(potential) = place.as_local() {
+                                    potential == target
+                                } else {
+                                    false
+                                }
+                            } else {
+                                false
+                            }
+                        });
 
-                    // If it is, follow this to the next block and update the target.
-                    if found_target {
-                        target = *dest;
-                        queue.push(block.start_location());
+                        // If it is, follow this to the next block and update the target.
+                        if found_target {
+                            target = dest;
+                            queue.push(block.start_location());
+                        }
                     }
                 }
             }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index ed639e8eee7..b5560fe6751 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -480,13 +480,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         if place.projection.is_empty() {
             if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
-                let is_promoted = match place {
-                    Place {
-                        base: PlaceBase::Static(box Static {
+                let is_promoted = match place.as_ref() {
+                    PlaceRef {
+                        base: &PlaceBase::Static(box Static {
                             kind: StaticKind::Promoted(..),
                             ..
                         }),
-                        projection: box [],
+                        projection: &[],
                     } => true,
                     _ => false,
                 };
@@ -1366,11 +1366,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 // they are not caused by the user, but rather artifacts
                 // of lowering. Assignments to other sorts of places *are* interesting
                 // though.
-                let category = match *place {
-                    Place {
-                        base: PlaceBase::Local(RETURN_PLACE),
-                        projection: box [],
-                    } => if let BorrowCheckContext {
+                let category = match place.as_local() {
+                    Some(RETURN_PLACE) => if let BorrowCheckContext {
                         universal_regions:
                             UniversalRegions {
                                 defining_ty: DefiningTy::Const(def_id, _),
@@ -1386,10 +1383,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     } else {
                         ConstraintCategory::Return
                     },
-                    Place {
-                        base: PlaceBase::Local(l),
-                        projection: box [],
-                    } if !body.local_decls[l].is_user_variable.is_some() => {
+                    Some(l) if !body.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
@@ -1675,11 +1669,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(body, tcx).ty;
                 let dest_ty = self.normalize(dest_ty, term_location);
-                let category = match *dest {
-                    Place {
-                        base: PlaceBase::Local(RETURN_PLACE),
-                        projection: box [],
-                    } => {
+                let category = match dest.as_local() {
+                    Some(RETURN_PLACE) => {
                         if let BorrowCheckContext {
                             universal_regions:
                                 UniversalRegions {
@@ -1698,10 +1689,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             ConstraintCategory::Return
                         }
                     }
-                    Place {
-                        base: PlaceBase::Local(l),
-                        projection: box [],
-                    } if !body.local_decls[l].is_user_variable.is_some() => {
+                    Some(l) if !body.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
@@ -2432,7 +2420,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             location, borrow_region, borrowed_place
         );
 
-        let mut cursor = &*borrowed_place.projection;
+        let mut cursor = borrowed_place.projection.as_ref();
         while let [proj_base @ .., elem] = cursor {
             cursor = proj_base;
 
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 9dd3e119c21..264e4807af0 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -64,14 +64,8 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
 
     // This Local/Local case is handled by the more general code below, but
     // it's so common that it's a speed win to check for it first.
-    if let Place {
-        base: PlaceBase::Local(l1),
-        projection: box [],
-    } = borrow_place {
-        if let PlaceRef {
-            base: PlaceBase::Local(l2),
-            projection: [],
-        } = access_place {
+    if let Some(l1) = borrow_place.as_local() {
+        if let Some(l2) = access_place.as_local() {
             return l1 == l2;
         }
     }
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
index 695080dfe23..95471afb788 100644
--- a/src/librustc_mir/borrow_check/used_muts.rs
+++ b/src/librustc_mir/borrow_check/used_muts.rs
@@ -1,7 +1,5 @@
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{
-    Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind
-};
+use rustc::mir::{Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind};
 
 use rustc_data_structures::fx::FxHashSet;
 
@@ -118,10 +116,7 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc
                     "assignment of {:?} to {:?}, adding {:?} to used mutable set",
                     path.place, local, path.place
                 );
-                if let Place {
-                    base: PlaceBase::Local(user_local),
-                    projection: box [],
-                } = path.place {
+                if let Some(user_local) = path.place.as_local() {
                     self.mbcx.used_mut.insert(user_local);
                 }
             }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 87d95a75153..43ee6557634 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -496,14 +496,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         let arg_place = unpack!(block = this.as_place(block, arg));
 
-        let mutability = match arg_place {
-            Place {
-                base: PlaceBase::Local(local),
-                projection: box [],
+        let mutability = match arg_place.as_ref() {
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: &[],
             } => this.local_decls[local].mutability,
-            Place {
-                base: PlaceBase::Local(local),
-                projection: box [ProjectionElem::Deref],
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: &[ProjectionElem::Deref],
             } => {
                 debug_assert!(
                     this.local_decls[local].is_ref_for_guard(),
@@ -511,13 +511,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 );
                 this.local_decls[local].mutability
             }
-            Place {
+            PlaceRef {
                 ref base,
-                projection: box [ref proj_base @ .., ProjectionElem::Field(upvar_index, _)],
+                projection: &[ref proj_base @ .., ProjectionElem::Field(upvar_index, _)],
             }
-            | Place {
+            | PlaceRef {
                 ref base,
-                projection: box [
+                projection: &[
                     ref proj_base @ ..,
                     ProjectionElem::Field(upvar_index, _),
                     ProjectionElem::Deref
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 2e451fc88d9..b86bb21f6e3 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -1293,7 +1293,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Insert a Shallow borrow of the prefixes of any fake borrows.
         for place in fake_borrows
         {
-            let mut cursor = &*place.projection;
+            let mut cursor = place.projection.as_ref();
             while let [proj_base @ .., elem] = cursor {
                 cursor = proj_base;
 
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index a749b4263ea..1b3d8641f20 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -926,46 +926,43 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // If constants and statics, we don't generate StorageLive for this
             // temporary, so don't try to generate StorageDead for it either.
             _ if self.local_scope().is_none() => (),
-            Operand::Copy(Place {
-                base: PlaceBase::Local(cond_temp),
-                projection: box [],
-            })
-            | Operand::Move(Place {
-                base: PlaceBase::Local(cond_temp),
-                projection: box [],
-            }) => {
-                // Manually drop the condition on both branches.
-                let top_scope = self.scopes.scopes.last_mut().unwrap();
-                let top_drop_data = top_scope.drops.pop().unwrap();
-
-                match top_drop_data.kind {
-                    DropKind::Value { .. } => {
-                        bug!("Drop scheduled on top of condition variable")
-                    }
-                    DropKind::Storage => {
-                        let source_info = top_scope.source_info(top_drop_data.span);
-                        let local = top_drop_data.local;
-                        assert_eq!(local, cond_temp, "Drop scheduled on top of condition");
-                        self.cfg.push(
-                            true_block,
-                            Statement {
-                                source_info,
-                                kind: StatementKind::StorageDead(local)
-                            },
-                        );
-                        self.cfg.push(
-                            false_block,
-                            Statement {
-                                source_info,
-                                kind: StatementKind::StorageDead(local)
-                            },
-                        );
+            Operand::Copy(place)
+            | Operand::Move(place) => {
+                if let Some(cond_temp) = place.as_local() {
+                    // Manually drop the condition on both branches.
+                    let top_scope = self.scopes.scopes.last_mut().unwrap();
+                    let top_drop_data = top_scope.drops.pop().unwrap();
+
+                    match top_drop_data.kind {
+                        DropKind::Value { .. } => {
+                            bug!("Drop scheduled on top of condition variable")
+                        }
+                        DropKind::Storage => {
+                            let source_info = top_scope.source_info(top_drop_data.span);
+                            let local = top_drop_data.local;
+                            assert_eq!(local, cond_temp, "Drop scheduled on top of condition");
+                            self.cfg.push(
+                                true_block,
+                                Statement {
+                                    source_info,
+                                    kind: StatementKind::StorageDead(local)
+                                },
+                            );
+                            self.cfg.push(
+                                false_block,
+                                Statement {
+                                    source_info,
+                                    kind: StatementKind::StorageDead(local)
+                                },
+                            );
+                        }
                     }
-                }
 
-                top_scope.invalidate_cache(true, self.is_generator, true);
+                    top_scope.invalidate_cache(true, self.is_generator, true);
+                } else {
+                    bug!("Expected as_local_operand to produce a temporary");
+                }
             }
-            _ => bug!("Expected as_local_operand to produce a temporary"),
         }
 
         (true_block, false_block)
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index c1695ba66d0..1b81032bfe6 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -157,10 +157,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
         // Since `propagate_call_unwind` doesn't exist, we have to kill the
         // destination here, and then gen it again in `propagate_call_return`.
         if let TerminatorKind::Call {
-            destination: Some((Place { base: PlaceBase::Local(local), projection: box [] }, _)),
+            destination: Some((ref place, _)),
             ..
         } = self.body[loc.block].terminator().kind {
-            sets.kill(local);
+            if let Some(local) = place.as_local() {
+                sets.kill(local);
+            }
         }
         self.check_for_move(sets, loc);
     }
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index f5a03316d80..b599f479944 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -327,7 +327,7 @@ impl<'tcx> MoveData<'tcx> {
     pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> {
         loop {
             let path = &self.move_paths[mpi];
-            if let Place { base: PlaceBase::Local(l), projection: box [] } = path.place {
+            if let Some(l) = path.place.as_local() {
                 return Some(l);
             }
             if let Some(parent) = path.parent {
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 40007eb3c4a..c8605e22e10 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -164,8 +164,8 @@ pub trait Qualif {
 
             Rvalue::Ref(_, _, ref place) => {
                 // Special-case reborrows to be more like a copy of the reference.
-                if let box [proj_base @ .., elem] = &place.projection {
-                    if ProjectionElem::Deref == *elem {
+                if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
+                    if ProjectionElem::Deref == elem {
                         let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty;
                         if let ty::Ref(..) = base_ty.kind {
                             return Self::in_place(cx, per_local, PlaceRef {
diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs
index 4fa4eba4c23..fc9290d6380 100644
--- a/src/librustc_mir/transform/check_consts/resolver.rs
+++ b/src/librustc_mir/transform/check_consts/resolver.rs
@@ -56,16 +56,16 @@ where
     fn assign_qualif_direct(&mut self, place: &mir::Place<'tcx>, value: bool) {
         debug_assert!(!place.is_indirect());
 
-        match (value, place) {
-            (true, mir::Place { base: mir::PlaceBase::Local(local), .. }) => {
-                self.qualifs_per_local.insert(*local);
+        match (value, place.as_ref()) {
+            (true, mir::PlaceRef { base: &mir::PlaceBase::Local(local), .. }) => {
+                self.qualifs_per_local.insert(local);
             }
 
             // For now, we do not clear the qualif if a local is overwritten in full by
             // an unqualified rvalue (e.g. `y = 5`). This is to be consistent
             // with aggregates where we overwrite all fields with assignments, which would not
             // get this feature.
-            (false, mir::Place { base: mir::PlaceBase::Local(_local), projection: box [] }) => {
+            (false, mir::PlaceRef { base: &mir::PlaceBase::Local(_local), projection: &[] }) => {
                 // self.qualifs_per_local.remove(*local);
             }
 
@@ -101,11 +101,10 @@ where
 
         // If a local with no projections is moved from (e.g. `x` in `y = x`), record that
         // it no longer needs to be dropped.
-        if let mir::Operand::Move(mir::Place {
-            base: mir::PlaceBase::Local(local),
-            projection: box [],
-        }) = *operand {
-            self.qualifs_per_local.remove(local);
+        if let mir::Operand::Move(place) = operand {
+            if let Some(local) = place.as_local() {
+                self.qualifs_per_local.remove(local);
+            }
         }
     }
 
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 87cd39b02cd..76a73adf038 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -244,8 +244,8 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
         if let Rvalue::Ref(_, kind, ref place) = *rvalue {
             // Special-case reborrows to be more like a copy of a reference.
             let mut reborrow_place = None;
-            if let box [proj_base @ .., elem] = &place.projection {
-                if *elem == ProjectionElem::Deref {
+            if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
+                if elem == ProjectionElem::Deref {
                     let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
                         reborrow_place = Some(proj_base);
@@ -376,12 +376,15 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
             );
 
             if rvalue_has_mut_interior {
-                let is_derived_from_illegal_borrow = match *borrowed_place {
+                let is_derived_from_illegal_borrow = match borrowed_place.as_local() {
                     // If an unprojected local was borrowed and its value was the result of an
                     // illegal borrow, suppress this error and mark the result of this borrow as
                     // illegal as well.
-                    Place { base: PlaceBase::Local(borrowed_local), projection: box [] }
-                        if self.derived_from_illegal_borrow.contains(borrowed_local) => true,
+                    Some(borrowed_local)
+                        if self.derived_from_illegal_borrow.contains(borrowed_local) =>
+                    {
+                        true
+                    }
 
                     // Otherwise proceed normally: check the legality of a mutable borrow in this
                     // context.
@@ -394,7 +397,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
                 // FIXME: should we also clear `derived_from_illegal_borrow` when a local is
                 // assigned a new value?
                 if is_derived_from_illegal_borrow {
-                    if let Place { base: PlaceBase::Local(dest), projection: box [] } = *dest {
+                    if let Some(dest) = dest.as_local() {
                         self.derived_from_illegal_borrow.insert(dest);
                     }
                 }
@@ -571,10 +574,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
                     return;
                 }
 
-                let needs_drop = if let Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                } = *dropped_place {
+                let needs_drop = if let Some(local) = dropped_place.as_local() {
                     // Use the span where the local was declared as the span of the drop error.
                     err_span = self.body.local_decls[local].source_info.span;
                     self.qualifs.needs_drop.contains(local)
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 70855d70228..029754dede2 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -407,8 +407,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         place: &Place<'tcx>,
         is_mut_use: bool,
     ) {
-        let mut cursor = &*place.projection;
-        while let [proj_base @ .., elem] = cursor {
+        let mut cursor = place.projection.as_ref();
+        while let &[ref proj_base @ .., elem] = cursor {
             cursor = proj_base;
 
             match elem {
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 108c6c9786b..dc6cb9650f0 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -7,10 +7,9 @@ use std::cell::Cell;
 use rustc::hir::def::DefKind;
 use rustc::hir::def_id::DefId;
 use rustc::mir::{
-    AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
-    Local, UnOp, StatementKind, Statement, LocalKind,
-    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp,
-    SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock,
+    AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, UnOp,
+    StatementKind, Statement, LocalKind, TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo,
+    BinOp, SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock,
 };
 use rustc::mir::visit::{
     Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
@@ -525,18 +524,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             // (e.g. for CTFE) it can never happen. But here in const_prop
             // unknown data is uninitialized, so if e.g. a function argument is unsized
             // and has a reference taken, we get an ICE.
-            Rvalue::Ref(_, _, Place { base: PlaceBase::Local(local), projection: box [] }) => {
-                trace!("checking Ref({:?})", place);
-                let alive =
-                    if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value {
-                        true
-                    } else {
-                        false
-                    };
+            Rvalue::Ref(_, _, place_ref) => {
+                trace!("checking Ref({:?})", place_ref);
 
-                if !alive {
-                    trace!("skipping Ref({:?}) to uninitialized local", place);
-                    return None;
+                if let Some(local) = place_ref.as_local() {
+                    let alive =
+                        if let LocalValue::Live(_) = self.ecx.frame().locals[local].value {
+                            true
+                        } else {
+                            false
+                        };
+
+                    if !alive {
+                        trace!("skipping Ref({:?}) to uninitialized local", place);
+                        return None;
+                    }
                 }
             }
 
@@ -706,10 +708,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                 .ty(&self.local_decls, self.tcx)
                 .ty;
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
-                if let Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                } = *place {
+                if let Some(local) = place.as_local() {
                     let source = statement.source_info;
                     if let Some(()) = self.const_prop(rval, place_layout, source, place) {
                         if self.can_const_prop[local] {
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index 28f97f41b50..c20726eceba 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -19,9 +19,7 @@
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
-use rustc::mir::{
-    Constant, Local, LocalKind, Location, Place, PlaceBase, Body, Operand, Rvalue, StatementKind
-};
+use rustc::mir::{Constant, Local, LocalKind, Location, Place, Body, Operand, Rvalue, StatementKind};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
 use crate::transform::{MirPass, MirSource};
@@ -92,28 +90,32 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation {
                     };
 
                     // That use of the source must be an assignment.
-                    match statement.kind {
-                        StatementKind::Assign(
-                            box(
-                                Place {
-                                    base: PlaceBase::Local(local),
-                                    projection: box [],
-                                },
-                                Rvalue::Use(ref operand)
-                            )
-                        ) if local == dest_local => {
-                            let maybe_action = match *operand {
-                                Operand::Copy(ref src_place) |
-                                Operand::Move(ref src_place) => {
-                                    Action::local_copy(&body, &def_use_analysis, src_place)
-                                }
-                                Operand::Constant(ref src_constant) => {
-                                    Action::constant(src_constant)
+                    match &statement.kind {
+                        StatementKind::Assign(box(place, Rvalue::Use(operand))) => {
+                            if let Some(local) = place.as_local() {
+                                if local == dest_local {
+                                    let maybe_action = match operand {
+                                        Operand::Copy(ref src_place) |
+                                        Operand::Move(ref src_place) => {
+                                            Action::local_copy(&body, &def_use_analysis, src_place)
+                                        }
+                                        Operand::Constant(ref src_constant) => {
+                                            Action::constant(src_constant)
+                                        }
+                                    };
+                                    match maybe_action {
+                                        Some(this_action) => action = this_action,
+                                        None => continue,
+                                    }
+                                } else {
+                                    debug!("  Can't copy-propagate local: source use is not an \
+                                    assignment");
+                                    continue
                                 }
-                            };
-                            match maybe_action {
-                                Some(this_action) => action = this_action,
-                                None => continue,
+                            } else {
+                                debug!("  Can't copy-propagate local: source use is not an \
+                                    assignment");
+                                continue
                             }
                         }
                         _ => {
@@ -148,31 +150,20 @@ fn eliminate_self_assignments(
         for def in dest_use_info.defs_not_including_drop() {
             let location = def.location;
             if let Some(stmt) = body[location.block].statements.get(location.statement_index) {
-                match stmt.kind {
-                    StatementKind::Assign(
-                        box(
-                            Place {
-                                base: PlaceBase::Local(local),
-                                projection: box [],
-                            },
-                            Rvalue::Use(Operand::Copy(Place {
-                                base: PlaceBase::Local(src_local),
-                                projection: box [],
-                            })),
-                        )
-                    ) |
-                    StatementKind::Assign(
-                        box(
-                            Place {
-                                base: PlaceBase::Local(local),
-                                projection: box [],
-                            },
-                            Rvalue::Use(Operand::Move(Place {
-                                base: PlaceBase::Local(src_local),
-                                projection: box [],
-                            })),
-                        )
-                    ) if local == dest_local && dest_local == src_local => {}
+                match &stmt.kind {
+                    StatementKind::Assign(box (place, Rvalue::Use(Operand::Copy(src_place))))
+                    | StatementKind::Assign(box (place, Rvalue::Use(Operand::Move(src_place)))) => {
+                        if let (Some(local), Some(src_local)) =
+                            (place.as_local(), src_place.as_local())
+                        {
+                            if local == dest_local && dest_local == src_local {
+                            } else {
+                                continue;
+                            }
+                        } else {
+                            continue;
+                        }
+                    }
                     _ => {
                         continue;
                     }
@@ -198,10 +189,7 @@ impl<'tcx> Action<'tcx> {
     fn local_copy(body: &Body<'tcx>, def_use_analysis: &DefUseAnalysis, src_place: &Place<'tcx>)
                   -> Option<Action<'tcx>> {
         // The source must be a local.
-        let src_local = if let Place {
-            base: PlaceBase::Local(local),
-            projection: box [],
-        } = *src_place {
+        let src_local = if let Some(local) = src_place.as_local() {
             local
         } else {
             debug!("  Can't copy-propagate local: source is not a local");
@@ -354,15 +342,18 @@ impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> {
     fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
         self.super_operand(operand, location);
 
-        match *operand {
-            Operand::Copy(Place {
-                base: PlaceBase::Local(local),
-                projection: box [],
-            }) |
-            Operand::Move(Place {
-                base: PlaceBase::Local(local),
-                projection: box [],
-            }) if local == self.dest_local => {}
+        match operand {
+            Operand::Copy(place) |
+            Operand::Move(place) => {
+                if let Some(local) = place.as_local() {
+                    if local == self.dest_local {
+                    } else {
+                        return;
+                    }
+                } else {
+                    return;
+                }
+            }
             _ => return,
         }
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 6533e3c5ba8..d0cb1b8297a 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -864,17 +864,24 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut
 
     for (block, block_data) in body.basic_blocks().iter_enumerated() {
         let (target, unwind, source_info) = match block_data.terminator() {
-            &Terminator {
+            Terminator {
                 source_info,
                 kind: TerminatorKind::Drop {
-                    location: Place {
-                        base: PlaceBase::Local(local),
-                        projection: box [],
-                    },
+                    location,
                     target,
                     unwind
                 }
-            } if local == gen => (target, unwind, source_info),
+            } => {
+                if let Some(local) = location.as_local() {
+                    if local == gen {
+                        (target, unwind, source_info)
+                    } else {
+                        continue;
+                    }
+                } else {
+                    continue;
+                }
+            }
             _ => continue,
         };
         let unwind = if block_data.is_cleanup {
@@ -884,10 +891,10 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut
         };
         elaborate_drop(
             &mut elaborator,
-            source_info,
+            *source_info,
             &Place::from(gen),
             (),
-            target,
+            *target,
             unwind,
             block,
         );
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 0cbdcedff47..353d89cf086 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -587,13 +587,12 @@ impl Inliner<'tcx> {
         // FIXME: Analysis of the usage of the arguments to avoid
         // unnecessary temporaries.
 
-        if let Operand::Move(Place {
-            base: PlaceBase::Local(local),
-            projection: box [],
-        }) = arg {
-            if caller_body.local_kind(local) == LocalKind::Temp {
-                // Reuse the operand if it's a temporary already
-                return local;
+        if let Operand::Move(place) = &arg {
+            if let Some(local) = place.as_local() {
+                if caller_body.local_kind(local) == LocalKind::Temp {
+                    // Reuse the operand if it's a temporary already
+                    return local;
+                }
             }
         }
 
@@ -650,14 +649,9 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
 
     fn make_integrate_local(&self, local: &Local) -> Local {
         if *local == RETURN_PLACE {
-            match self.destination {
-                Place {
-                    base: PlaceBase::Local(l),
-                    projection: box [],
-                } => {
-                    return l;
-                },
-                ref place => bug!("Return place is {:?}, not local", place)
+            match self.destination.as_local() {
+                Some(l) => return l,
+                ref place => bug!("Return place is {:?}, not local", place),
             }
         }
 
@@ -686,17 +680,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
         context: PlaceContext,
         location: Location,
     ) {
-        match place {
-            Place {
-                base: PlaceBase::Local(RETURN_PLACE),
-                projection: box [],
-            } => {
-                // Return pointer; update the place itself
-                *place = self.destination.clone();
-            },
-            _ => {
-                self.super_place(place, context, location);
-            }
+        if let Some(RETURN_PLACE) = place.as_local() {
+            // Return pointer; update the place itself
+            *place = self.destination.clone();
+        } else {
+            self.super_place(place, context, location);
         }
     }
 
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index bb98d63b1ee..08668716fee 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -1,7 +1,8 @@
 //! Performs various peephole optimizations.
 
-use rustc::mir::{Constant, Location, Place, PlaceBase, Body, Operand, ProjectionElem, Rvalue,
-    Local};
+use rustc::mir::{
+    Constant, Location, Place, PlaceBase, PlaceRef, Body, Operand, ProjectionElem, Rvalue, Local
+};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -40,20 +41,18 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
     fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
         if self.optimizations.and_stars.remove(&location) {
             debug!("replacing `&*`: {:?}", rvalue);
-            let new_place = match *rvalue {
-                Rvalue::Ref(_, _, Place {
-                    ref mut base,
-                    projection: ref mut projection @ box [.., _],
-                }) => {
-                    if let box [proj_l @ .., proj_r] = projection {
-                        let place = Place {
-                            // Replace with dummy
-                            base: mem::replace(base, PlaceBase::Local(Local::new(0))),
-                            projection: proj_l.to_vec().into_boxed_slice(),
-                        };
-                        *projection = vec![proj_r.clone()].into_boxed_slice();
+            let new_place = match rvalue {
+                Rvalue::Ref(_, _, place) => {
+                    if let &[ref proj_l @ .., proj_r] = place.projection.as_ref() {
+                        let new_projection = proj_l.to_vec().into_boxed_slice();
+
+                        place.projection = vec![proj_r.clone()].into_boxed_slice();
 
-                        place
+                        Place {
+                            // Replace with dummy
+                            base: mem::replace(&mut place.base, PlaceBase::Local(Local::new(0))),
+                            projection: new_projection,
+                        }
                     } else {
                         unreachable!();
                     }
@@ -91,12 +90,14 @@ impl OptimizationFinder<'b, 'tcx> {
 
 impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        if let Rvalue::Ref(_, _, Place {
-            base,
-            projection: box [proj_base @ .., ProjectionElem::Deref],
-        }) = rvalue {
-            if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
-                self.optimizations.and_stars.insert(location);
+        if let Rvalue::Ref(_, _, place) = rvalue {
+            if let PlaceRef {
+                base,
+                projection: &[ref proj_base @ .., ProjectionElem::Deref],
+            } = place.as_ref() {
+                if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() {
+                    self.optimizations.and_stars.insert(location);
+                }
             }
         }
 
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index ad1785417cd..f13d49e3f54 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -434,14 +434,13 @@ pub fn promote_candidates<'tcx>(
         match candidate {
             Candidate::Repeat(Location { block, statement_index }) |
             Candidate::Ref(Location { block, statement_index }) => {
-                match body[block].statements[statement_index].kind {
-                    StatementKind::Assign(box(Place {
-                        base: PlaceBase::Local(local),
-                        projection: box [],
-                    }, _)) => {
-                        if temps[local] == TempState::PromotedOut {
-                            // Already promoted.
-                            continue;
+                match &body[block].statements[statement_index].kind {
+                    StatementKind::Assign(box(place, _)) => {
+                        if let Some(local) = place.as_local() {
+                            if temps[local] == TempState::PromotedOut {
+                                // Already promoted.
+                                continue;
+                            }
                         }
                     }
                     _ => {}
@@ -487,28 +486,30 @@ pub fn promote_candidates<'tcx>(
     let promoted = |index: Local| temps[index] == TempState::PromotedOut;
     for block in body.basic_blocks_mut() {
         block.statements.retain(|statement| {
-            match statement.kind {
-                StatementKind::Assign(box(Place {
-                    base: PlaceBase::Local(index),
-                    projection: box [],
-                }, _)) |
+            match &statement.kind {
+                StatementKind::Assign(box(place, _)) => {
+                    if let Some(index) = place.as_local() {
+                        !promoted(index)
+                    } else {
+                        true
+                    }
+                }
                 StatementKind::StorageLive(index) |
                 StatementKind::StorageDead(index) => {
-                    !promoted(index)
+                    !promoted(*index)
                 }
                 _ => true
             }
         });
         let terminator = block.terminator_mut();
-        match terminator.kind {
-            TerminatorKind::Drop { location: Place {
-                base: PlaceBase::Local(index),
-                projection: box [],
-            }, target, .. } => {
-                if promoted(index) {
-                    terminator.kind = TerminatorKind::Goto {
-                        target,
-                    };
+        match &terminator.kind {
+            TerminatorKind::Drop { location: place, target, .. } => {
+                if let Some(index) = place.as_local() {
+                    if promoted(index) {
+                        terminator.kind = TerminatorKind::Goto {
+                            target: *target,
+                        };
+                    }
                 }
             }
             _ => {}
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index da1abb9747c..6aba91f4162 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -292,8 +292,8 @@ trait Qualif {
 
             Rvalue::Ref(_, _, ref place) => {
                 // Special-case reborrows to be more like a copy of the reference.
-                if let box [proj_base @ .., elem] = &place.projection {
-                    if ProjectionElem::Deref == *elem {
+                if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
+                    if ProjectionElem::Deref == elem {
                         let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty;
                         if let ty::Ref(..) = base_ty.kind {
                             return Self::in_place(cx, PlaceRef {
@@ -1041,26 +1041,24 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
             match *candidate {
                 Candidate::Repeat(Location { block: bb, statement_index: stmt_idx }) => {
                     if let StatementKind::Assign(box(_, Rvalue::Repeat(
-                        Operand::Move(Place {
-                            base: PlaceBase::Local(index),
-                            projection: box [],
-                        }),
+                        Operand::Move(place),
                         _
-                    ))) = self.body[bb].statements[stmt_idx].kind {
-                        promoted_temps.insert(index);
+                    ))) = &self.body[bb].statements[stmt_idx].kind {
+                        if let Some(index) = place.as_local() {
+                            promoted_temps.insert(index);
+                        }
                     }
                 }
                 Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
                     if let StatementKind::Assign(
                         box(
                             _,
-                            Rvalue::Ref(_, _, Place {
-                                base: PlaceBase::Local(index),
-                                projection: box [],
-                            })
+                            Rvalue::Ref(_, _, place)
                         )
-                    ) = self.body[bb].statements[stmt_idx].kind {
-                        promoted_temps.insert(index);
+                    ) = &self.body[bb].statements[stmt_idx].kind {
+                        if let Some(index) = place.as_local() {
+                            promoted_temps.insert(index);
+                        }
                     }
                 }
                 Candidate::Argument { .. } => {}
@@ -1237,10 +1235,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         match *operand {
             Operand::Move(ref place) => {
                 // Mark the consumed locals to indicate later drops are noops.
-                if let Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                } = *place {
+                if let Some(local) = place.as_local() {
                     self.cx.per_local[NeedsDrop].remove(local);
                 }
             }
@@ -1256,8 +1251,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         if let Rvalue::Ref(_, kind, ref place) = *rvalue {
             // Special-case reborrows.
             let mut reborrow_place = None;
-            if let box [proj_base @ .., elem] = &place.projection {
-                if *elem == ProjectionElem::Deref {
+            if let &[ref proj_base @ .., elem] = place.projection.as_ref() {
+                if elem == ProjectionElem::Deref {
                     let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.kind {
                         reborrow_place = Some(proj_base);
@@ -1568,10 +1563,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                 unleash_miri!(self);
                 // HACK(eddyb): emulate a bit of dataflow analysis,
                 // conservatively, that drop elaboration will do.
-                let needs_drop = if let Place {
-                    base: PlaceBase::Local(local),
-                    projection: box [],
-                } = *place {
+                let needs_drop = if let Some(local) = place.as_local() {
                     if NeedsDrop::in_local(self, local) {
                         Some(self.body.local_decls[local].source_info.span)
                     } else {
@@ -1817,16 +1809,17 @@ fn remove_drop_and_storage_dead_on_promoted_locals(
             }
         });
         let terminator = block.terminator_mut();
-        match terminator.kind {
+        match &terminator.kind {
             TerminatorKind::Drop {
-                location: Place {
-                    base: PlaceBase::Local(index),
-                    projection: box [],
-                },
+                location,
                 target,
                 ..
-            } if promoted_temps.contains(index) => {
-                terminator.kind = TerminatorKind::Goto { target };
+            } => {
+                if let Some(index) = location.as_local() {
+                    if promoted_temps.contains(index) {
+                        terminator.kind = TerminatorKind::Goto { target: *target };
+                    }
+                }
             }
             _ => {}
         }
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 7b6255defd1..c4e44091bc9 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -259,8 +259,8 @@ fn check_place(
     def_id: DefId,
     body: &Body<'tcx>
 ) -> McfResult {
-    let mut cursor = &*place.projection;
-    while let [proj_base @ .., elem] = cursor {
+    let mut cursor = place.projection.as_ref();
+    while let &[ref proj_base @ .., elem] = cursor {
         cursor = proj_base;
         match elem {
             ProjectionElem::Downcast(..) => {
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index e1994c5f639..130393e2c4c 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -32,7 +32,7 @@ impl RemoveNoopLandingPads {
         nop_landing_pads: &BitSet<BasicBlock>,
     ) -> bool {
         for stmt in &body[bb].statements {
-            match stmt.kind {
+            match &stmt.kind {
                 StatementKind::FakeRead(..) |
                 StatementKind::StorageLive(_) |
                 StatementKind::StorageDead(_) |
@@ -41,12 +41,13 @@ impl RemoveNoopLandingPads {
                     // These are all nops in a landing pad
                 }
 
-                StatementKind::Assign(box(Place {
-                    base: PlaceBase::Local(_),
-                    projection: box [],
-                }, Rvalue::Use(_))) => {
-                    // Writing to a local (e.g., a drop flag) does not
-                    // turn a landing pad to a non-nop
+                StatementKind::Assign(box(place, Rvalue::Use(_))) => {
+                    if place.as_local().is_some() {
+                        // Writing to a local (e.g., a drop flag) does not
+                        // turn a landing pad to a non-nop
+                    } else {
+                        return false;
+                    }
                 }
 
                 StatementKind::Assign { .. } |
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 6edd28a4259..aada7641df6 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -155,8 +155,8 @@ fn value_assigned_to_local<'a, 'tcx>(
     local: Local,
 ) -> Option<&'a mir::Rvalue<'tcx>> {
     if let mir::StatementKind::Assign(box (place, rvalue)) = &stmt.kind {
-        if let mir::Place { base: mir::PlaceBase::Local(l), projection: box [] } = place {
-            if local == *l {
+        if let Some(l) = place.as_local() {
+            if local == l {
                 return Some(&*rvalue);
             }
         }
@@ -192,7 +192,7 @@ impl PeekCall {
         tcx: TyCtxt<'tcx>,
         terminator: &mir::Terminator<'tcx>,
     ) -> Option<Self> {
-        use mir::{Operand, Place, PlaceBase};
+        use mir::Operand;
 
         let span = terminator.source_info.span;
         if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
@@ -207,14 +207,23 @@ impl PeekCall {
 
                 assert_eq!(args.len(), 1);
                 let kind = PeekCallKind::from_arg_ty(substs.type_at(0));
-                let arg = match args[0] {
-                    | Operand::Copy(Place { base: PlaceBase::Local(local), projection: box [] })
-                    | Operand::Move(Place { base: PlaceBase::Local(local), projection: box [] })
-                    => local,
-
+                let arg = match &args[0] {
+                    Operand::Copy(place) | Operand::Move(place) => {
+                        if let Some(local) = place.as_local() {
+                            local
+                        } else {
+                            tcx.sess.diagnostic().span_err(
+                                span,
+                                "dataflow::sanity_check cannot feed a non-temp to rustc_peek.",
+                            );
+                            return None;
+                        }
+                    }
                     _ => {
                         tcx.sess.diagnostic().span_err(
-                            span, "dataflow::sanity_check cannot feed a non-temp to rustc_peek.");
+                            span,
+                            "dataflow::sanity_check cannot feed a non-temp to rustc_peek.",
+                        );
                         return None;
                     }
                 };
@@ -277,12 +286,11 @@ impl<'tcx> RustcPeekAt<'tcx> for IndirectlyMutableLocals<'_, 'tcx> {
         call: PeekCall,
     ) {
         warn!("peek_at: place={:?}", place);
-        let local = match place {
-            mir::Place { base: mir::PlaceBase::Local(l), projection: box [] } => *l,
-            _ => {
-                tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
-                return;
-            }
+        let local = if let Some(l) = place.as_local() {
+            l
+        } else {
+            tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
+            return;
         };
 
         if !flow_state.contains(local) {
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index efa39d91205..07a7def3ea2 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -61,7 +61,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
                     rvalue: &Rvalue<'tcx>,
                     location: Location) {
         if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue {
-            if let box [proj_base @ .., elem] = &src_place.projection {
+            if let &[ref proj_base @ .., elem] = src_place.projection.as_ref() {
                 if let ProjectionElem::ConstantIndex{offset: _,
                                                      min_length: _,
                                                      from_end: false} = elem {
@@ -203,18 +203,17 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut {
                 if let StatementKind::Assign(box(ref dst_place, ref rval)) = statement.kind {
                     if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval {
                         let items : Vec<_> = items.iter().map(|item| {
-                            if let Operand::Move(Place {
-                                base: PlaceBase::Local(local),
-                                projection: box [],
-                            }) = item {
-                                let local_use = &visitor.locals_use[*local];
-                                let opt_index_and_place =
-                                    Self::try_get_item_source(local_use, body);
-                                // each local should be used twice:
-                                //  in assign and in aggregate statements
-                                if local_use.use_count == 2 && opt_index_and_place.is_some() {
-                                    let (index, src_place) = opt_index_and_place.unwrap();
-                                    return Some((local_use, index, src_place));
+                            if let Operand::Move(place) = item {
+                                if let Some(local) = place.as_local() {
+                                    let local_use = &visitor.locals_use[local];
+                                    let opt_index_and_place =
+                                        Self::try_get_item_source(local_use, body);
+                                    // each local should be used twice:
+                                    //  in assign and in aggregate statements
+                                    if local_use.use_count == 2 && opt_index_and_place.is_some() {
+                                        let (index, src_place) = opt_index_and_place.unwrap();
+                                        return Some((local_use, index, src_place));
+                                    }
                                 }
                             }
                             None
@@ -293,33 +292,27 @@ impl RestoreSubsliceArrayMoveOut {
             if block.statements.len() > location.statement_index {
                 let statement = &block.statements[location.statement_index];
                 if let StatementKind::Assign(
-                    box(
-                        Place {
-                            base: PlaceBase::Local(_),
-                            projection: box [],
-                        },
-                        Rvalue::Use(Operand::Move(Place {
-                            base: _,
-                            projection: box [.., ProjectionElem::ConstantIndex {
-                                offset, min_length: _, from_end: false
-                            }],
-                        })),
-                    )
+                    box(place, Rvalue::Use(Operand::Move(src_place)))
                 ) = &statement.kind {
-                    // FIXME remove once we can use slices patterns
-                    if let StatementKind::Assign(
-                        box(
-                            _,
-                            Rvalue::Use(Operand::Move(Place {
+                    if let (Some(_), PlaceRef {
+                        base: _,
+                        projection: &[.., ProjectionElem::ConstantIndex {
+                            offset, min_length: _, from_end: false
+                        }],
+                    }) = (place.as_local(), src_place.as_ref()) {
+                        if let StatementKind::Assign(
+                            box(_, Rvalue::Use(Operand::Move(place)))
+                        ) = &statement.kind {
+                            if let PlaceRef {
                                 base,
-                                projection: box [proj_base @ .., _],
-                            })),
-                        )
-                    ) = &statement.kind {
-                        return Some((*offset, PlaceRef {
-                            base,
-                            projection: proj_base,
-                        }))
+                                projection: &[ref proj_base @ .., _],
+                            } = place.as_ref() {
+                                return Some((offset, PlaceRef {
+                                    base,
+                                    projection: proj_base,
+                                }))
+                            }
+                        }
                     }
                 }
             }
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index 1bad85ec42d..f949fcf0745 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -38,8 +38,8 @@ fn is_within_packed<'tcx, L>(tcx: TyCtxt<'tcx>, local_decls: &L, place: &Place<'
 where
     L: HasLocalDecls<'tcx>,
 {
-    let mut cursor = &*place.projection;
-    while let [proj_base @ .., elem] = cursor {
+    let mut cursor = place.projection.as_ref();
+    while let &[ref proj_base @ .., elem] = cursor {
         cursor = proj_base;
 
         match elem {