diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py
index 2c651c90f82eb..fdc1c4fa0cc38 100644
--- a/src/etc/lldb_rust_formatters.py
+++ b/src/etc/lldb_rust_formatters.py
@@ -290,6 +290,8 @@ def render_element(i):
 
 
 def read_utf8_string(ptr_val, byte_count):
+    if byte_count == 0:
+        return '""'
     error = lldb.SBError()
     process = ptr_val.get_wrapped_value().GetProcess()
     data = process.ReadMemory(ptr_val.as_integer(), byte_count, error)
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index fe852e42b5cd3..1dd2bd3ee78aa 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -185,13 +185,13 @@ bench_sums! {
 bench_sums! {
     bench_filter_sum,
     bench_filter_ref_sum,
-    (0i64..1000000).filter(|x| x % 2 == 0)
+    (0i64..1000000).filter(|x| x % 3 == 0)
 }
 
 bench_sums! {
     bench_filter_chain_sum,
     bench_filter_chain_ref_sum,
-    (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
+    (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
 }
 
 bench_sums! {
@@ -306,3 +306,31 @@ fn bench_skip_then_zip(b: &mut Bencher) {
         assert_eq!(s, 2009900);
     });
 }
+
+#[bench]
+fn bench_filter_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_ref_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_chain_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_chain_ref_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+    })
+}
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index bca1b76dbb975..d4ad22c16bbfa 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -681,12 +681,7 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
 
     #[inline]
     fn next(&mut self) -> Option<I::Item> {
-        for x in &mut self.iter {
-            if (self.predicate)(&x) {
-                return Some(x);
-            }
-        }
-        None
+        self.try_for_each(Err).err()
     }
 
     #[inline]
@@ -707,12 +702,9 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
     // Using the branchless version will also simplify the LLVM byte code, thus
     // leaving more budget for LLVM optimizations.
     #[inline]
-    fn count(mut self) -> usize {
-        let mut count = 0;
-        for x in &mut self.iter {
-            count += (self.predicate)(&x) as usize;
-        }
-        count
+    fn count(self) -> usize {
+        let mut predicate = self.predicate;
+        self.iter.map(|x| predicate(&x) as usize).sum()
     }
 
     #[inline]
@@ -746,12 +738,7 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
 {
     #[inline]
     fn next_back(&mut self) -> Option<I::Item> {
-        for x in self.iter.by_ref().rev() {
-            if (self.predicate)(&x) {
-                return Some(x);
-            }
-        }
-        None
+        self.try_rfold((), |_, x| Err(x)).err()
     }
 
     #[inline]
@@ -820,12 +807,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
 
     #[inline]
     fn next(&mut self) -> Option<B> {
-        for x in self.iter.by_ref() {
-            if let Some(y) = (self.f)(x) {
-                return Some(y);
-            }
-        }
-        None
+        self.try_for_each(Err).err()
     }
 
     #[inline]
@@ -863,12 +845,7 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
 {
     #[inline]
     fn next_back(&mut self) -> Option<B> {
-        for x in self.iter.by_ref().rev() {
-            if let Some(y) = (self.f)(x) {
-                return Some(y);
-            }
-        }
-        None
+        self.try_rfold((), |_, x| Err(x)).err()
     }
 
     #[inline]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 8b51d8465141a..53334adadb856 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3965,7 +3965,7 @@ impl str {
         me.make_ascii_lowercase()
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_debug`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_debug`].
     ///
     /// Note: only extended grapheme codepoints that begin the string will be
     /// escaped.
@@ -4013,7 +4013,7 @@ impl str {
         }
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_default`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
     ///
     /// [`char::escape_default`]: ../std/primitive.char.html#method.escape_default
     ///
@@ -4051,7 +4051,7 @@ impl str {
         EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_unicode`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
     ///
     /// [`char::escape_unicode`]: ../std/primitive.char.html#method.escape_unicode
     ///
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index ddc091b718706..41b78ee509655 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -209,13 +209,13 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Place<'gcx> {
                                           hasher: &mut StableHasher<W>) {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
-            mir::Place::Local(ref local) => {
+            mir::Place::Base(mir::PlaceBase::Local(ref local)) => {
                 local.hash_stable(hcx, hasher);
             }
-            mir::Place::Static(ref statik) => {
+            mir::Place::Base(mir::PlaceBase::Static(ref statik)) => {
                 statik.hash_stable(hcx, hasher);
             }
-            mir::Place::Promoted(ref promoted) => {
+            mir::Place::Base(mir::PlaceBase::Promoted(ref promoted)) => {
                 promoted.hash_stable(hcx, hasher);
             }
             mir::Place::Projection(ref place_projection) => {
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index dd003e44bea09..496ff568b31b4 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -132,14 +132,22 @@ macro_rules! declare_lint {
 
 #[macro_export]
 macro_rules! declare_tool_lint {
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => (
-        declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false}
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
+    ) => (
+        declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
     );
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr,
-     report_in_external_macro: $rep: expr) => (
-         declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep}
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+        report_in_external_macro: $rep:expr
+    ) => (
+         declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
     );
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+        $external:expr
+    ) => (
+        $(#[$attr])*
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: &concat!(stringify!($tool), "::", stringify!($NAME)),
             default_level: $crate::lint::$Level,
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index bfc74979af42c..b6f5ff25c8fb8 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1896,6 +1896,14 @@ impl<'tcx> Debug for Statement<'tcx> {
 /// changing or disturbing program state.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub enum Place<'tcx> {
+    Base(PlaceBase<'tcx>),
+
+    /// projection out of a place (access a field, deref a pointer, etc)
+    Projection(Box<PlaceProjection<'tcx>>),
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub enum PlaceBase<'tcx> {
     /// local variable
     Local(Local),
 
@@ -1904,9 +1912,6 @@ pub enum Place<'tcx> {
 
     /// Constant code promoted to an injected static
     Promoted(Box<(Promoted, Ty<'tcx>)>),
-
-    /// projection out of a place (access a field, deref a pointer, etc)
-    Projection(Box<PlaceProjection<'tcx>>),
 }
 
 /// The `DefId` of a static, along with its normalized type (which is
@@ -1994,6 +1999,8 @@ newtype_index! {
 }
 
 impl<'tcx> Place<'tcx> {
+    pub const RETURN_PLACE: Place<'tcx> = Place::Base(PlaceBase::Local(RETURN_PLACE));
+
     pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
         self.elem(ProjectionElem::Field(f, ty))
     }
@@ -2020,9 +2027,9 @@ impl<'tcx> Place<'tcx> {
     // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local(&self) -> Option<Local> {
         match self {
-            Place::Local(local) |
+            Place::Base(PlaceBase::Local(local)) |
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) => Some(*local),
             _ => None,
@@ -2032,9 +2039,9 @@ impl<'tcx> Place<'tcx> {
     /// Finds the innermost `Local` from this `Place`.
     pub fn base_local(&self) -> Option<Local> {
         match self {
-            Place::Local(local) => Some(*local),
+            Place::Base(PlaceBase::Local(local)) => Some(*local),
             Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
-            Place::Promoted(..) | Place::Static(..) => None,
+            Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
         }
     }
 }
@@ -2044,14 +2051,19 @@ impl<'tcx> Debug for Place<'tcx> {
         use self::Place::*;
 
         match *self {
-            Local(id) => write!(fmt, "{:?}", id),
-            Static(box self::Static { def_id, ty }) => write!(
+            Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
+            Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
                 fmt,
                 "({}: {:?})",
                 ty::tls::with(|tcx| tcx.item_path_str(def_id)),
                 ty
             ),
-            Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1),
+            Base(PlaceBase::Promoted(ref promoted)) => write!(
+                fmt,
+                "({:?}: {:?})",
+                promoted.0,
+                promoted.1
+            ),
             Projection(ref data) => match data.elem {
                 ProjectionElem::Downcast(ref adt_def, index) => {
                     write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index dbf911851bf2d..a6f153eaf6461 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -158,10 +158,10 @@ impl<'tcx> Place<'tcx> {
         where D: HasLocalDecls<'tcx>
     {
         match *self {
-            Place::Local(index) =>
+            Place::Base(PlaceBase::Local(index)) =>
                 PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
-            Place::Promoted(ref data) => PlaceTy::Ty { ty: data.1 },
-            Place::Static(ref data) =>
+            Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
+            Place::Base(PlaceBase::Static(ref data)) =>
                 PlaceTy::Ty { ty: data.ty },
             Place::Projection(ref proj) =>
                 proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 4f31cebca088d..28e816f134365 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -733,13 +733,13 @@ macro_rules! make_mir_visitor {
                             context: PlaceContext<'tcx>,
                             location: Location) {
                 match place {
-                    Place::Local(local) => {
+                    Place::Base(PlaceBase::Local(local)) => {
                         self.visit_local(local, context, location);
                     }
-                    Place::Static(static_) => {
+                    Place::Base(PlaceBase::Static(static_)) => {
                         self.visit_static(static_, context, location);
                     }
-                    Place::Promoted(promoted) => {
+                    Place::Base(PlaceBase::Promoted(promoted)) => {
                         self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
                     },
                     Place::Projection(proj) => {
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index db5430a4219a0..8f991a9ef490b 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -13,10 +13,8 @@ use crate::common;
 use crate::LlvmCodegenBackend;
 use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler};
 use rustc_codegen_ssa::traits::*;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::session::config::{self, OutputType, Passes, Lto};
 use rustc::session::Session;
-use rustc::ty::TyCtxt;
 use rustc_codegen_ssa::{ModuleCodegen, CompiledModule};
 use rustc::util::common::time_ext;
 use rustc_fs_util::{path_to_c_string, link_or_copy};
@@ -82,14 +80,6 @@ pub fn write_output_file(
     }
 }
 
-pub fn create_target_machine(
-    tcx: TyCtxt<'_, '_, '_>,
-    find_features: bool,
-) -> &'static mut llvm::TargetMachine {
-    target_machine_factory(tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE), find_features)()
-        .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise() )
-}
-
 pub fn create_informational_target_machine(
     sess: &Session,
     find_features: bool,
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 23e3a8425d370..619304ad9afd0 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -154,7 +154,7 @@ pub unsafe fn create_module(
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
-        let tm = crate::back::write::create_target_machine(tcx, false);
+        let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
         llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
         llvm::LLVMRustDisposeTargetMachine(tm);
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 5b8c7461bcb60..38b16078a7d38 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -24,7 +24,7 @@
 #![deny(rust_2018_idioms)]
 #![allow(explicit_outlives_requirements)]
 
-use back::write::create_target_machine;
+use back::write::create_informational_target_machine;
 use syntax_pos::symbol::Symbol;
 
 extern crate flate2;
@@ -114,8 +114,9 @@ pub struct LlvmCodegenBackend(());
 
 impl ExtraBackendMethods for LlvmCodegenBackend {
     fn new_metadata(&self, tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> ModuleLlvm {
-        ModuleLlvm::new(tcx, mod_name)
+        ModuleLlvm::new_metadata(tcx, mod_name)
     }
+
     fn write_metadata<'b, 'gcx>(
         &self,
         tcx: TyCtxt<'b, 'gcx, 'gcx>,
@@ -366,15 +367,14 @@ unsafe impl Send for ModuleLlvm { }
 unsafe impl Sync for ModuleLlvm { }
 
 impl ModuleLlvm {
-    fn new(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
+    fn new_metadata(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
         unsafe {
             let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
             let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
-
             ModuleLlvm {
                 llmod_raw,
                 llcx,
-                tm: create_target_machine(tcx, false),
+                tm: create_informational_target_machine(&tcx.sess, false),
             }
         }
     }
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 908ee95efcba3..2bade64ddbd34 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1022,7 +1022,13 @@ fn start_executing_work<B: ExtraBackendMethods>(
         None
     };
 
-    let ol = tcx.backend_optimization_level(LOCAL_CRATE);
+    let ol = if tcx.sess.opts.debugging_opts.no_codegen
+             || !tcx.sess.opts.output_types.should_codegen() {
+        // If we know that we won’t be doing codegen, create target machines without optimisation.
+        config::OptLevel::No
+    } else {
+        tcx.backend_optimization_level(LOCAL_CRATE)
+    };
     let cgcx = CodegenContext::<B> {
         backend: backend.clone(),
         crate_types: sess.crate_types.borrow().clone(),
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 9fe2e58bc203c..facae9a979706 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -103,7 +103,7 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                     location: Location) {
         debug!("visit_assign(block={:?}, place={:?}, rvalue={:?})", block, place, rvalue);
 
-        if let mir::Place::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             self.assign(index, location);
             if !self.fx.rvalue_creates_operand(rvalue) {
                 self.not_ssa(index);
@@ -245,7 +245,8 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
             }
 
             PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
-                let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx());
+                let ty = mir::Place::Base(mir::PlaceBase::Local(local)).ty(self.fx.mir,
+                                                                           self.fx.cx.tcx());
                 let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx()));
 
                 // Only need the place if we're actually dropping it.
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index caca1789fc98c..46b1cce437702 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -240,7 +240,10 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
                     PassMode::Direct(_) | PassMode::Pair(..) => {
                         let op =
-                            self.codegen_consume(&mut bx, &mir::Place::Local(mir::RETURN_PLACE));
+                            self.codegen_consume(
+                                &mut bx,
+                                &mir::Place::RETURN_PLACE,
+                            );
                         if let Ref(llval, _, align) = op.val {
                             bx.load(llval, align)
                         } else {
@@ -589,8 +592,12 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 // 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(mir::Place::Promoted(box(index, ty))) |
-                                mir::Operand::Move(mir::Place::Promoted(box(index, ty))) => {
+                                mir::Operand::Copy(
+                                    mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+                                ) |
+                                mir::Operand::Move(
+                                    mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+                                ) => {
                                     let param_env = ty::ParamEnv::reveal_all();
                                     let cid = mir::interpret::GlobalId {
                                         instance: self.instance,
@@ -964,7 +971,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         if fn_ret.is_ignore() {
             return ReturnDest::Nothing;
         }
-        let dest = if let mir::Place::Local(index) = *dest {
+        let dest = if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dest {
             match self.locals[index] {
                 LocalRef::Place(dest) => dest,
                 LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
@@ -1019,7 +1026,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         src: &mir::Operand<'tcx>,
         dst: &mir::Place<'tcx>
     ) {
-        if let mir::Place::Local(index) = *dst {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *dst {
             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/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 0e8cdc83b486e..0a6549851f446 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -378,7 +378,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // watch out for locals that do not have an
         // alloca; they are handled somewhat differently
-        if let mir::Place::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             match self.locals[index] {
                 LocalRef::Operand(Some(o)) => {
                     return Some(o);
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 1edcbfead2c94..0408ccf039f34 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -392,7 +392,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let cx = self.cx;
         let tcx = self.cx.tcx();
 
-        if let mir::Place::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             match self.locals[index] {
                 LocalRef::Place(place) => {
                     return place;
@@ -407,8 +407,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
 
         let result = match *place {
-            mir::Place::Local(_) => bug!(), // handled above
-            mir::Place::Promoted(box (index, ty)) => {
+            mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
+            mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
                 let param_env = ty::ParamEnv::reveal_all();
                 let cid = mir::interpret::GlobalId {
                     instance: self.instance,
@@ -435,7 +435,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 }
             }
-            mir::Place::Static(box mir::Static { def_id, ty }) => {
+            mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
                 // NB: The layout of a static may be unsized as is the case when working
                 // with a static that is an extern_type.
                 let layout = cx.layout_of(self.monomorphize(&ty));
@@ -457,7 +457,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         cg_base.project_field(bx, field.index())
                     }
                     mir::ProjectionElem::Index(index) => {
-                        let index = &mir::Operand::Copy(mir::Place::Local(index));
+                        let index = &mir::Operand::Copy(
+                            mir::Place::Base(mir::PlaceBase::Local(index))
+                        );
                         let index = self.codegen_operand(bx, index);
                         let llindex = index.immediate();
                         cg_base.project_index(bx, llindex)
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 25a7754d118d7..b0c667a965daa 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -534,7 +534,7 @@ impl<'a, 'tcx: 'a, 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::Local(index) = *place {
+        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if let ty::Array(_, n) = op.layout.ty.sty {
                     let n = n.unwrap_usize(bx.cx().tcx());
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index a1bd919c43354..97729e8aeb35f 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -17,7 +17,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         self.set_debug_loc(&mut bx, statement.source_info);
         match statement.kind {
             mir::StatementKind::Assign(ref place, ref rvalue) => {
-                if let mir::Place::Local(index) = *place {
+                if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
                     match self.locals[index] {
                         LocalRef::Place(cg_dest) => {
                             self.codegen_rvalue(bx, cg_dest, rvalue)
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index 2a3a616317c17..cbef7a7f6c481 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -333,7 +333,7 @@ impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
         //    TEMP = &foo
         //
         // so extract `temp`.
-        let temp = if let &mir::Place::Local(temp) = assigned_place {
+        let temp = if let &mir::Place::Base(mir::PlaceBase::Local(temp)) = assigned_place {
             temp
         } else {
             span_bug!(
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 67fbe5762e73a..dc1979b6380b1 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -8,7 +8,7 @@ use rustc::middle::region::ScopeTree;
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
     ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
-    Place, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
+    Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
     TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, DefIdTree};
@@ -220,7 +220,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         );
                     }
                 }
-                if let Place::Local(local) = place {
+                if let Place::Base(PlaceBase::Local(local)) = place {
                     let decl = &self.mir.local_decls[*local];
                     err.span_label(
                         decl.source_info.span,
@@ -679,7 +679,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let borrow_span = borrow_spans.var_or_use();
 
         let proper_span = match *root_place {
-            Place::Local(local) => self.mir.local_decls[local].source_info.span,
+            Place::Base(PlaceBase::Local(local)) => self.mir.local_decls[local].source_info.span,
             _ => drop_span,
         };
 
@@ -1061,7 +1061,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
             let local_kind = match borrow.borrowed_place {
-                Place::Local(local) => {
+                Place::Base(PlaceBase::Local(local)) => {
                     match self.mir.local_kind(local) {
                         LocalKind::ReturnPointer
                         | LocalKind::Temp => bug!("temporary or return pointer with a name"),
@@ -1086,7 +1086,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
                 .last()
                 .unwrap();
-            let local = if let Place::Local(local) = *root_place {
+            let local = if let Place::Base(PlaceBase::Local(local)) = *root_place {
                 local
             } else {
                 bug!("report_cannot_return_reference_to_local: not a local")
@@ -1385,7 +1385,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         assigned_span: Span,
         err_place: &Place<'tcx>,
     ) {
-        let (from_arg, local_decl) = if let Place::Local(local) = *err_place {
+        let (from_arg, local_decl) = if let Place::Base(PlaceBase::Local(local)) = *err_place {
             if let LocalKind::Arg = self.mir.local_kind(local) {
                 (true, Some(&self.mir.local_decls[local]))
             } else {
@@ -1600,13 +1600,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         including_downcast: &IncludingDowncast,
     ) -> Result<(), ()> {
         match *place {
-            Place::Promoted(_) => {
+            Place::Base(PlaceBase::Promoted(_)) => {
                 buf.push_str("promoted");
             }
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 self.append_local_to_string(local, buf)?;
             }
-            Place::Static(ref static_) => {
+            Place::Base(PlaceBase::Static(ref static_)) => {
                 buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
             }
             Place::Projection(ref proj) => {
@@ -1630,7 +1630,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                     autoderef,
                                     &including_downcast,
                                 )?;
-                            } else if let Place::Local(local) = proj.base {
+                            } else if let Place::Base(PlaceBase::Local(local)) = proj.base {
                                 if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
                                     self.mir.local_decls[local].is_user_variable
                                 {
@@ -1742,12 +1742,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// End-user visible description of the `field`nth field of `base`
     fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
         match *base {
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 let local = &self.mir.local_decls[local];
                 self.describe_field_from_ty(&local.ty, field)
             }
-            Place::Promoted(ref prom) => self.describe_field_from_ty(&prom.1, field),
-            Place::Static(ref static_) => self.describe_field_from_ty(&static_.ty, field),
+            Place::Base(PlaceBase::Promoted(ref prom)) =>
+                self.describe_field_from_ty(&prom.1, field),
+            Place::Base(PlaceBase::Static(ref static_)) =>
+                self.describe_field_from_ty(&static_.ty, field),
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Deref => self.describe_field(&proj.base, field),
                 ProjectionElem::Downcast(def, variant_index) =>
@@ -1809,7 +1811,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
     /// Checks if a place is a thread-local static.
     pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
-        if let Place::Static(statik) = place {
+        if let Place::Base(PlaceBase::Static(statik)) = place {
             let attrs = self.infcx.tcx.get_attrs(statik.def_id);
             let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
 
@@ -1827,7 +1829,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
         match place {
-            Place::Local(_) | Place::Static(_) | Place::Promoted(_) => {
+            Place::Base(PlaceBase::Local(_)) |
+            Place::Base(PlaceBase::Static(_)) |
+            Place::Base(PlaceBase::Promoted(_)) => {
                 StorageDeadOrDrop::LocalStorageDead
             }
             Place::Projection(box PlaceProjection { base, elem }) => {
@@ -1912,7 +1916,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             );
             // Check that the initial assignment of the reserve location is into a temporary.
             let mut target = *match reservation {
-                Place::Local(local) if self.mir.local_kind(*local) == LocalKind::Temp => local,
+                Place::Base(PlaceBase::Local(local))
+                    if self.mir.local_kind(*local) == LocalKind::Temp => local,
                 _ => return None,
             };
 
@@ -1924,8 +1929,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}",
                     target, stmt
                 );
-                if let StatementKind::Assign(Place::Local(assigned_to), box rvalue) = &stmt.kind
-                {
+                if let StatementKind::Assign(
+                    Place::Base(PlaceBase::Local(assigned_to)),
+                    box rvalue
+                ) = &stmt.kind {
                     debug!(
                         "annotate_argument_and_return_for_borrow: assigned_to={:?} \
                          rvalue={:?}",
@@ -2048,7 +2055,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 target, terminator
             );
             if let TerminatorKind::Call {
-                destination: Some((Place::Local(assigned_to), _)),
+                destination: Some((Place::Base(PlaceBase::Local(assigned_to)), _)),
                 args,
                 ..
             } = &terminator.kind
@@ -2496,7 +2503,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             .get(location.statement_index)
         {
             Some(&Statement {
-                kind: StatementKind::Assign(Place::Local(local), _),
+                kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
                 ..
             }) => local,
             _ => return OtherUse(use_span),
@@ -2522,7 +2529,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     def_id, is_generator, places
                 );
                 if let Some((args_span, var_span)) = self.closure_span(
-                    *def_id, &Place::Local(target), places
+                    *def_id, &Place::Base(PlaceBase::Local(target)), places
                 ) {
                     return ClosureUse {
                         is_generator,
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 1091646bdd5c6..715ee856a7a62 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -8,7 +8,7 @@ use rustc::infer::InferCtxt;
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::middle::borrowck::SignalledError;
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
-use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
+use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
 use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
@@ -588,7 +588,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
             StatementKind::StorageDead(local) => {
                 self.access_place(
                     ContextKind::StorageDead.new(location),
-                    (&Place::Local(local), span),
+                    (&Place::Base(PlaceBase::Local(local)), span),
                     (Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
                     LocalMutationIsAllowed::Yes,
                     flow_state,
@@ -1104,7 +1104,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, '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::Local(local) = place_span.0 {
+        if let &Place::Base(PlaceBase::Local(local)) = place_span.0 {
             if let Mutability::Not = self.mir.local_decls[local].mutability {
                 // check for reassignments to immutable local variables
                 self.check_if_reassignment_to_immutable_state(
@@ -1231,8 +1231,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             // captures of a closure are copied/moved directly
                             // when generating MIR.
                             match operands[field.index()] {
-                                Operand::Move(Place::Local(local))
-                                | Operand::Copy(Place::Local(local)) => {
+                                Operand::Move(Place::Base(PlaceBase::Local(local)))
+                                | Operand::Copy(Place::Base(PlaceBase::Local(local))) => {
                                     self.used_mut.insert(local);
                                 }
                                 Operand::Move(ref place @ Place::Projection(_))
@@ -1242,10 +1242,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                         self.used_mut_upvars.push(field);
                                     }
                                 }
-                                Operand::Move(Place::Static(..))
-                                | Operand::Copy(Place::Static(..))
-                                | Operand::Move(Place::Promoted(..))
-                                | Operand::Copy(Place::Promoted(..))
+                                Operand::Move(Place::Base(PlaceBase::Static(..)))
+                                | Operand::Copy(Place::Base(PlaceBase::Static(..)))
+                                | Operand::Move(Place::Base(PlaceBase::Promoted(..)))
+                                | Operand::Copy(Place::Base(PlaceBase::Promoted(..)))
                                 | Operand::Constant(..) => {}
                             }
                         }
@@ -1328,14 +1328,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         //
         // FIXME: allow thread-locals to borrow other thread locals?
         let (might_be_alive, will_be_dropped) = match root_place {
-            Place::Promoted(_) => (true, false),
-            Place::Static(_) => {
+            Place::Base(PlaceBase::Promoted(_)) => (true, false),
+            Place::Base(PlaceBase::Static(_)) => {
                 // Thread-locals might be dropped after the function exits, but
                 // "true" statics will never be.
                 let is_thread_local = self.is_place_thread_local(&root_place);
                 (true, is_thread_local)
             }
-            Place::Local(_) => {
+            Place::Base(PlaceBase::Local(_)) => {
                 // Locals are always dropped at function exit, and if they
                 // have a destructor it would've been called already.
                 (false, self.locals_are_invalidated_at_exit)
@@ -1594,10 +1594,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             last_prefix = prefix;
         }
         match *last_prefix {
-            Place::Local(_) => panic!("should have move path for every Local"),
+            Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
             Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
-            Place::Promoted(_) |
-            Place::Static(_) => Err(NoMovePathFound::ReachedStatic),
+            Place::Base(PlaceBase::Promoted(_)) |
+            Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
         }
     }
 
@@ -1623,8 +1623,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let mut place = place;
         loop {
             match *place {
-                Place::Promoted(_) |
-                Place::Local(_) | Place::Static(_) => {
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
                     // assigning to `x` does not require `x` be initialized.
                     break;
                 }
@@ -1947,7 +1947,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     ) {
         match root_place {
             RootPlace {
-                place: Place::Local(local),
+                place: Place::Base(PlaceBase::Local(local)),
                 is_local_mutation_allowed,
             } => {
                 // If the local may have been initialized, and it is now currently being
@@ -1972,11 +1972,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 }
             }
             RootPlace {
-                place: Place::Promoted(..),
+                place: Place::Base(PlaceBase::Promoted(..)),
                 is_local_mutation_allowed: _,
             } => {}
             RootPlace {
-                place: Place::Static(..),
+                place: Place::Base(PlaceBase::Static(..)),
                 is_local_mutation_allowed: _,
             } => {}
         }
@@ -1990,7 +1990,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         is_local_mutation_allowed: LocalMutationIsAllowed,
     ) -> Result<RootPlace<'d, 'tcx>, &'d Place<'tcx>> {
         match *place {
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 let local = &self.mir.local_decls[local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
@@ -2012,11 +2012,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             }
             // The rules for promotion are made by `qualify_consts`, there wouldn't even be a
             // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
-            Place::Promoted(_) => Ok(RootPlace {
+            Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
                 place,
                 is_local_mutation_allowed,
             }),
-            Place::Static(ref static_) => {
+            Place::Base(PlaceBase::Static(ref static_)) => {
                 if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
                     Err(place)
                 } else {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index 2a5433d431786..bd4bf67d0b154 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -111,7 +111,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 // If that ever stops being the case, then the ever initialized
                 // flow could be used.
                 if let Some(StatementKind::Assign(
-                    Place::Local(local),
+                    Place::Base(PlaceBase::Local(local)),
                     box Rvalue::Use(Operand::Move(move_from)),
                 )) = self.mir.basic_blocks()[location.block]
                     .statements
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 008c081aeb601..f68ed4422bca0 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -1,8 +1,8 @@
 use rustc::hir;
 use rustc::hir::Node;
 use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
-use rustc::mir::{Mutability, Operand, Place, Projection, ProjectionElem, Static, Terminator};
-use rustc::mir::TerminatorKind;
+use rustc::mir::{Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static};
+use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
@@ -45,9 +45,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
-            Place::Local(local) => {
+            Place::Base(PlaceBase::Local(local)) => {
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if let Place::Local(_) = access_place {
+                if let Place::Base(PlaceBase::Local(_)) = access_place {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
                     let name = self.mir.local_decls[*local]
@@ -78,7 +78,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 base,
                 elem: ProjectionElem::Deref,
             }) => {
-                if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() {
+                if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
+                    !self.mir.upvar_decls.is_empty() {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
                     debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
                     debug_assert!(is_closure_or_generator(
@@ -92,7 +93,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         ", as `Fn` closures cannot mutate their captured variables".to_string()
                     }
                 } else if {
-                    if let Place::Local(local) = *base {
+                    if let Place::Base(PlaceBase::Local(local)) = *base {
                         if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
                             = self.mir.local_decls[local].is_user_variable {
                                 true
@@ -128,10 +129,10 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 }
             }
 
-            Place::Promoted(_) => unreachable!(),
+            Place::Base(PlaceBase::Promoted(_)) => unreachable!(),
 
-            Place::Static(box Static { def_id, ty: _ }) => {
-                if let Place::Static(_) = access_place {
+            Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
+                if let Place::Base(PlaceBase::Static(_)) = access_place {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
                     reason = String::new();
                 } else {
@@ -241,7 +242,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             },
 
             // Suggest removing a `&mut` from the use of a mutable reference.
-            Place::Local(local)
+            Place::Base(PlaceBase::Local(local))
                 if {
                     self.mir.local_decls.get(*local).map(|local_decl| {
                         if let ClearCrossCrate::Set(
@@ -276,7 +277,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
             // We want to suggest users use `let mut` for local (user
             // variable) mutations...
-            Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
+            Place::Base(PlaceBase::Local(local))
+                if self.mir.local_decls[*local].can_be_made_mutable() => {
                 // ... but it doesn't make sense to suggest it on
                 // variables that are `ref x`, `ref mut x`, `&self`,
                 // or `&mut self` (such variables are simply not
@@ -330,7 +332,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             // complete hack to approximate old AST-borrowck
             // diagnostic: if the span starts with a mutable borrow of
             // a local variable, then just suggest the user remove it.
-            Place::Local(_)
+            Place::Base(PlaceBase::Local(_))
                 if {
                     if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         snippet.starts_with("&mut ")
@@ -344,7 +346,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }
 
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) if {
                 if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
@@ -368,7 +370,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             // FIXME: can this case be generalized to work for an
             // arbitrary base for the projection?
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) if self.mir.local_decls[*local].is_user_variable.is_some() =>
             {
@@ -447,7 +449,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             Place::Projection(box Projection {
                 base,
                 elem: ProjectionElem::Deref,
-            }) if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() =>
+            }) if *base == Place::Base(PlaceBase::Local(Local::new(1))) &&
+                  !self.mir.upvar_decls.is_empty() =>
             {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
                 err.span_help(
@@ -457,7 +460,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             }
 
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             })  if error_access == AccessKind::MutableBorrow => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 9eb09b514741c..375dd6e97f1a2 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -6,7 +6,7 @@ use crate::borrow_check::nll::region_infer::values::LivenessValues;
 use rustc::infer::InferCtxt;
 use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
+use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, PlaceBase, Rvalue};
 use rustc::mir::{SourceInfo, Statement, Terminator};
 use rustc::mir::UserTypeProjection;
 use rustc::ty::fold::TypeFoldable;
@@ -130,7 +130,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         // When we see `X = ...`, then kill borrows of
         // `(*X).foo` and so forth.
         if let Some(all_facts) = self.all_facts {
-            if let Place::Local(temp) = place {
+            if let Place::Base(PlaceBase::Local(temp)) = place {
                 if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) {
                     all_facts.killed.reserve(borrow_indices.len());
                     for &borrow_index in borrow_indices {
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 8ea249959dd2c..17f8c23f4fddc 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::{Context, MirBorrowckCtxt, WriteKind};
 use rustc::mir::{
-    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, Projection,
-    ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
+    CastKind, ConstraintCategory, FakeReadCause, Local, Location, Mir, Operand, Place, PlaceBase,
+    Projection, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind,
 };
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
@@ -245,7 +245,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             Some(Cause::LiveVar(local, location)) => {
                 let span = mir.source_info(location).span;
                 let spans = self
-                    .move_spans(&Place::Local(local), location)
+                    .move_spans(&Place::Base(PlaceBase::Local(local)), location)
                     .or_else(|| self.borrow_spans(span, location));
 
                 let borrow_location = context.loc;
@@ -265,7 +265,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 let mut should_note_order = false;
                 if mir.local_decls[local].name.is_some() {
                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
-                        if let Place::Local(borrowed_local) = place {
+                        if let Place::Base(PlaceBase::Local(borrowed_local)) = place {
                             let dropped_local_scope = mir.local_decls[local].visibility_scope;
                             let borrowed_local_scope =
                                 mir.local_decls[*borrowed_local].visibility_scope;
@@ -481,7 +481,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, '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::Local(l)) | Operand::Move(Place::Local(l)) => {
+                            Operand::Copy(Place::Base(PlaceBase::Local(l))) |
+                            Operand::Move(Place::Base(PlaceBase::Local(l))) => {
                                 let local_decl = &self.mir.local_decls[*l];
                                 if local_decl.name.is_none() {
                                     local_decl.source_info.span
@@ -522,7 +523,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // it which simplifies the termination logic.
         let mut queue = vec![location];
         let mut target = if let Some(&Statement {
-            kind: StatementKind::Assign(Place::Local(local), _),
+            kind: StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _),
             ..
         }) = stmt
         {
@@ -547,9 +548,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // The only kind of statement that we care about is assignments...
                 if let StatementKind::Assign(place, box rvalue) = &stmt.kind {
                     let into = match place {
-                        Place::Local(into) => into,
+                        Place::Base(PlaceBase::Local(into)) => into,
                         Place::Projection(box Projection {
-                            base: Place::Local(into),
+                            base: Place::Base(PlaceBase::Local(into)),
                             elem: ProjectionElem::Deref,
                         }) => into,
                         _ => {
@@ -563,8 +564,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, '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::Local(from))
-                            | Operand::Move(Place::Local(from))
+                            Operand::Copy(Place::Base(PlaceBase::Local(from)))
+                            | Operand::Move(Place::Base(PlaceBase::Local(from)))
                                 if *from == target =>
                             {
                                 target = *into;
@@ -574,8 +575,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         // If we see a unsized cast, then if it is our data we should check
                         // whether it is being cast to a trait object.
                         Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand {
-                            Operand::Copy(Place::Local(from))
-                            | Operand::Move(Place::Local(from))
+                            Operand::Copy(Place::Base(PlaceBase::Local(from)))
+                            | Operand::Move(Place::Base(PlaceBase::Local(from)))
                                 if *from == target =>
                             {
                                 debug!("was_captured_by_trait_object: ty={:?}", ty);
@@ -605,7 +606,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 debug!("was_captured_by_trait_object: terminator={:?}", terminator);
 
                 if let TerminatorKind::Call {
-                    destination: Some((Place::Local(dest), block)),
+                    destination: Some((Place::Base(PlaceBase::Local(dest)), block)),
                     args,
                     ..
                 } = &terminator.kind
@@ -616,7 +617,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     );
                     // 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::Local(potential)) = arg {
+                        if let Operand::Move(Place::Base(PlaceBase::Local(potential))) = arg {
                             *potential == target
                         } else {
                             false
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 9c06767762108..aafbff3577647 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -12,7 +12,7 @@ use crate::borrow_check::path_utils::*;
 use crate::dataflow::move_paths::indexes::BorrowIndex;
 use rustc::ty::TyCtxt;
 use rustc::mir::visit::Visitor;
-use rustc::mir::{BasicBlock, Location, Mir, Place, Rvalue};
+use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase, Rvalue};
 use rustc::mir::{Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::mir::{Operand, BorrowKind};
@@ -131,7 +131,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
             StatementKind::StorageDead(local) => {
                 self.access_place(
                     ContextKind::StorageDead.new(location),
-                    &Place::Local(local),
+                    &Place::Base(PlaceBase::Local(local)),
                     (Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
                     LocalMutationIsAllowed::Yes,
                 );
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 4202d10aa63d0..76975a5fac7e7 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -451,10 +451,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
         let place_ty = match *place {
-            Place::Local(index) => PlaceTy::Ty {
+            Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
                 ty: self.mir.local_decls[index].ty,
             },
-            Place::Promoted(box (_index, sty)) => {
+            Place::Base(PlaceBase::Promoted(box (_index, sty))) => {
                 let sty = self.sanitize_type(place, sty);
                 // FIXME -- promoted MIR return types reference
                 // various "free regions" (e.g., scopes and things)
@@ -469,7 +469,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 // promoted_mir.return_ty()
                 PlaceTy::Ty { ty: sty }
             }
-            Place::Static(box Static { def_id, ty: sty }) => {
+            Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
                 let sty = self.sanitize_type(place, sty);
                 let ty = self.tcx().type_of(def_id);
                 let ty = self.cx.normalize(ty, location);
@@ -553,7 +553,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 }
             }
             ProjectionElem::Index(i) => {
-                let index_ty = Place::Local(i).ty(self.mir, tcx).to_ty(tcx);
+                let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).to_ty(tcx);
                 if index_ty != tcx.types.usize {
                     PlaceTy::Ty {
                         ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
@@ -1234,7 +1234,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 // of lowering. Assignments to other sorts of places *are* interesting
                 // though.
                 let category = match *place {
-                    Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
+                    Place::Base(PlaceBase::Local(RETURN_PLACE)) => if let Some(BorrowCheckContext {
                         universal_regions:
                             UniversalRegions {
                                 defining_ty: DefiningTy::Const(def_id, _),
@@ -1251,7 +1251,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     } else {
                         ConstraintCategory::Return
                     },
-                    Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+                    Place::Base(PlaceBase::Local(l))
+                        if !mir.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
@@ -1537,7 +1538,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             Some((ref dest, _target_block)) => {
                 let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
                 let category = match *dest {
-                    Place::Local(RETURN_PLACE) => {
+                    Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
                         if let Some(BorrowCheckContext {
                             universal_regions:
                                 UniversalRegions {
@@ -1556,7 +1557,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                             ConstraintCategory::Return
                         }
                     }
-                    Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
+                    Place::Base(PlaceBase::Local(l))
+                        if !mir.local_decls[l].is_user_variable.is_some() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index 9073ae6bed5b2..9e0bb93c33a5d 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -3,7 +3,7 @@ use crate::borrow_check::places_conflict;
 use crate::borrow_check::Context;
 use crate::borrow_check::AccessDepth;
 use crate::dataflow::indexes::BorrowIndex;
-use rustc::mir::{BasicBlock, Location, Mir, Place};
+use rustc::mir::{BasicBlock, Location, Mir, Place, PlaceBase};
 use rustc::mir::{ProjectionElem, BorrowKind};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::graph::dominators::Dominators;
@@ -138,9 +138,9 @@ pub(super) fn is_active<'tcx>(
 /// This is called for all Yield statements on movable generators
 pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
     match place {
-        Place::Promoted(_) |
-        Place::Static(..) => false,
-        Place::Local(..) => true,
+        Place::Base(PlaceBase::Promoted(_)) |
+        Place::Base(PlaceBase::Static(..)) => false,
+        Place::Base(PlaceBase::Local(..)) => true,
         Place::Projection(box proj) => {
             match proj.elem {
                 // Reborrow of already borrowed data is ignored
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index d6d2861b557ab..c05ee3cf65b36 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -1,6 +1,6 @@
 use rustc::hir;
 use rustc::mir::ProjectionElem;
-use rustc::mir::{Local, Mir, Place, Mutability};
+use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability};
 use rustc::ty::{self, TyCtxt};
 use crate::borrow_check::borrow_set::LocalsStateAtExit;
 
@@ -30,7 +30,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
         match self {
-            Place::Promoted(_) => false,
+            Place::Base(PlaceBase::Promoted(_)) => false,
 
             // If a local variable is immutable, then we only need to track borrows to guard
             // against two kinds of errors:
@@ -40,7 +40,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
             //
             // In particular, the variable cannot be mutated -- the "access checks" will fail --
             // so we don't have to worry about mutation while borrowed.
-            Place::Local(index) => {
+            Place::Base(PlaceBase::Local(index)) => {
                 match locals_state_at_exit {
                     LocalsStateAtExit::AllAreInvalidated => false,
                     LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
@@ -51,7 +51,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
                     }
                 }
             }
-            Place::Static(static_) => {
+            Place::Base(PlaceBase::Static(static_)) => {
                 tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
             }
             Place::Projection(proj) => match proj.elem {
@@ -88,9 +88,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
         loop {
             match p {
                 Place::Projection(pi) => p = &pi.base,
-                Place::Promoted(_) |
-                Place::Static(_) => return None,
-                Place::Local(l) => return Some(*l),
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Static(_)) => return None,
+                Place::Base(PlaceBase::Local(l)) => return Some(*l),
             }
         }
     }
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index b5175cf41dd5c..1d18ada1fb69c 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -2,8 +2,7 @@ use crate::borrow_check::ArtificialField;
 use crate::borrow_check::Overlap;
 use crate::borrow_check::{Deep, Shallow, AccessDepth};
 use rustc::hir;
-use rustc::mir::{BorrowKind, Mir, Place};
-use rustc::mir::{Projection, ProjectionElem};
+use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
 use rustc::ty::{self, TyCtxt};
 use std::cmp::max;
 
@@ -60,8 +59,8 @@ pub(super) fn borrow_conflicts_with_place<'gcx, '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::Local(l1) = borrow_place {
-        if let Place::Local(l2) = access_place {
+    if let Place::Base(PlaceBase::Local(l1)) = borrow_place {
+        if let Place::Base(PlaceBase::Local(l2)) = access_place {
             return l1 == l2;
         }
     }
@@ -339,8 +338,8 @@ fn unroll_place<'tcx, R>(
             op,
         ),
 
-        Place::Promoted(_) |
-        Place::Local(_) | Place::Static(_) => {
+        Place::Base(PlaceBase::Promoted(_)) |
+        Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
             let list = PlaceComponents {
                 component: place,
                 next,
@@ -361,7 +360,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
     bias: PlaceConflictBias,
 ) -> Overlap {
     match (elem1, elem2) {
-        (Place::Local(l1), Place::Local(l2)) => {
+        (Place::Base(PlaceBase::Local(l1)), Place::Base(PlaceBase::Local(l2))) => {
             if l1 == l2 {
                 // the same local - base case, equal
                 debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
@@ -372,7 +371,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 Overlap::Disjoint
             }
         }
-        (Place::Static(static1), Place::Static(static2)) => {
+        (Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => {
             if static1.def_id != static2.def_id {
                 debug!("place_element_conflict: DISJOINT-STATIC");
                 Overlap::Disjoint
@@ -385,7 +384,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 Overlap::EqualOrDisjoint
             }
         }
-        (Place::Promoted(p1), Place::Promoted(p2)) => {
+        (Place::Base(PlaceBase::Promoted(p1)), Place::Base(PlaceBase::Promoted(p2))) => {
             if p1.0 == p2.0 {
                 if let ty::Array(_, size) = p1.1.sty {
                     if size.unwrap_usize(tcx) == 0 {
@@ -403,9 +402,12 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 Overlap::Disjoint
             }
         }
-        (Place::Local(_), Place::Promoted(_)) | (Place::Promoted(_), Place::Local(_)) |
-        (Place::Promoted(_), Place::Static(_)) | (Place::Static(_), Place::Promoted(_)) |
-        (Place::Local(_), Place::Static(_)) | (Place::Static(_), Place::Local(_)) => {
+        (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Promoted(_))) |
+        (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Local(_))) |
+        (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Static(_))) |
+        (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Promoted(_))) |
+        (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
+        (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
             debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
             Overlap::Disjoint
         }
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index c3a8381cd5810..384fd5c9987b8 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -11,7 +11,7 @@ use super::MirBorrowckCtxt;
 
 use rustc::hir;
 use rustc::ty::{self, TyCtxt};
-use rustc::mir::{Mir, Place, ProjectionElem};
+use rustc::mir::{Mir, Place, PlaceBase, ProjectionElem};
 
 pub trait IsPrefixOf<'tcx> {
     fn is_prefix_of(&self, other: &Place<'tcx>) -> bool;
@@ -26,8 +26,9 @@ impl<'tcx> IsPrefixOf<'tcx> for Place<'tcx> {
             }
 
             match *cursor {
-                Place::Promoted(_) |
-                Place::Local(_) | Place::Static(_) => return false,
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Local(_)) |
+                Place::Base(PlaceBase::Static(_)) => return false,
                 Place::Projection(ref proj) => {
                     cursor = &proj.base;
                 }
@@ -86,9 +87,9 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
 
         'cursor: loop {
             let proj = match *cursor {
-                Place::Promoted(_) |
-                Place::Local(_) | // search yielded this leaf
-                Place::Static(_) => {
+                Place::Base(PlaceBase::Promoted(_)) |
+                Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
+                Place::Base(PlaceBase::Static(_)) => {
                     self.next = None;
                     return Some(cursor);
                 }
diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs
index 8c7359bdee768..b102bced0e335 100644
--- a/src/librustc_mir/borrow_check/used_muts.rs
+++ b/src/librustc_mir/borrow_check/used_muts.rs
@@ -1,5 +1,7 @@
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{BasicBlock, Local, Location, Place, Statement, StatementKind, TerminatorKind};
+use rustc::mir::{
+    BasicBlock, Local, Location, Place, PlaceBase, Statement, StatementKind, TerminatorKind
+};
 
 use rustc_data_structures::fx::FxHashSet;
 
@@ -114,7 +116,7 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c
                     "assignment of {:?} to {:?}, adding {:?} to used mutable set",
                     path.place, local, path.place
                 );
-                if let Place::Local(user_local) = path.place {
+                if let Place::Base(PlaceBase::Local(user_local)) = path.place {
                     self.mbcx.used_mut.insert(user_local);
                 }
             }
diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs
index 38fae8539c8d7..e354a2ee8160b 100644
--- a/src/librustc_mir/build/expr/as_operand.rs
+++ b/src/librustc_mir/build/expr/as_operand.rs
@@ -74,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             }
             Category::Place | Category::Rvalue(..) => {
                 let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
-                block.and(Operand::Move(Place::Local(operand)))
+                block.and(Operand::Move(Place::Base(PlaceBase::Local(operand))))
             }
         }
     }
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index ed444191226a1..3bea88024b3f9 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -98,19 +98,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     &lt,
                     Rvalue::BinaryOp(
                         BinOp::Lt,
-                        Operand::Copy(Place::Local(idx)),
+                        Operand::Copy(Place::Base(PlaceBase::Local(idx))),
                         Operand::Copy(len.clone()),
                     ),
                 );
 
                 let msg = BoundsCheck {
                     len: Operand::Move(len),
-                    index: Operand::Copy(Place::Local(idx)),
+                    index: Operand::Copy(Place::Base(PlaceBase::Local(idx))),
                 };
                 let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
                 success.and(slice.index(idx))
             }
-            ExprKind::SelfRef => block.and(Place::Local(Local::new(1))),
+            ExprKind::SelfRef => block.and(Place::Base(PlaceBase::Local(Local::new(1)))),
             ExprKind::VarRef { id } => {
                 let place = if this.is_bound_var_in_guard(id) && this
                     .hir
@@ -118,17 +118,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     .all_pat_vars_are_implicit_refs_within_guards()
                 {
                     let index = this.var_local_id(id, RefWithinGuard);
-                    Place::Local(index).deref()
+                    Place::Base(PlaceBase::Local(index)).deref()
                 } else {
                     let index = this.var_local_id(id, OutsideGuard);
-                    Place::Local(index)
+                    Place::Base(PlaceBase::Local(index))
                 };
                 block.and(place)
             }
-            ExprKind::StaticRef { id } => block.and(Place::Static(Box::new(Static {
+            ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
                 def_id: id,
                 ty: expr.ty,
-            }))),
+            })))),
 
             ExprKind::PlaceTypeAscription { source, user_ty } => {
                 let place = unpack!(block = this.as_place(block, source));
@@ -172,14 +172,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         Statement {
                             source_info,
                             kind: StatementKind::AscribeUserType(
-                                Place::Local(temp.clone()),
+                                Place::Base(PlaceBase::Local(temp.clone())),
                                 Variance::Invariant,
                                 box UserTypeProjection { base: annotation_index, projs: vec![], },
                             ),
                         },
                     );
                 }
-                block.and(Place::Local(temp))
+                block.and(Place::Base(PlaceBase::Local(temp)))
             }
 
             ExprKind::Array { .. }
@@ -219,7 +219,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 });
                 let temp =
                     unpack!(block = this.as_temp(block, expr.temp_lifetime, expr, mutability));
-                block.and(Place::Local(temp))
+                block.and(Place::Base(PlaceBase::Local(temp)))
             }
         }
     }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 88dbd93939e54..b00d1c612edf3 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -127,7 +127,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     this.schedule_drop_storage_and_value(
                         expr_span,
                         scope,
-                        &Place::Local(result),
+                        &Place::Base(PlaceBase::Local(result)),
                         value.ty,
                     );
                 }
@@ -135,11 +135,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // malloc some memory of suitable type (thus far, uninitialized):
                 let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
                 this.cfg
-                    .push_assign(block, source_info, &Place::Local(result), box_);
+                    .push_assign(block, source_info, &Place::Base(PlaceBase::Local(result)), box_);
 
                 // initialize the box contents:
-                unpack!(block = this.into(&Place::Local(result).deref(), block, value));
-                block.and(Rvalue::Use(Operand::Move(Place::Local(result))))
+                unpack!(
+                    block = this.into(
+                        &Place::Base(PlaceBase::Local(result)).deref(),
+                        block, value
+                    )
+                );
+                block.and(Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(result)))))
             }
             ExprKind::Cast { source } => {
                 let source = this.hir.mirror(source);
@@ -522,9 +527,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let arg_place = unpack!(block = this.as_place(block, arg));
 
         let mutability = match arg_place {
-            Place::Local(local) => this.local_decls[local].mutability,
+            Place::Base(PlaceBase::Local(local)) => this.local_decls[local].mutability,
             Place::Projection(box Projection {
-                base: Place::Local(local),
+                base: Place::Base(PlaceBase::Local(local)),
                 elem: ProjectionElem::Deref,
             }) => {
                 debug_assert!(
@@ -554,11 +559,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // Not projected from the implicit `self` in a closure.
                 debug_assert!(
                     match *base {
-                        Place::Local(local) => local == Local::new(1),
+                        Place::Base(PlaceBase::Local(local)) => local == Local::new(1),
                         Place::Projection(box Projection {
                             ref base,
                             elem: ProjectionElem::Deref,
-                        }) => *base == Place::Local(Local::new(1)),
+                        }) => *base == Place::Base(PlaceBase::Local(Local::new(1))),
                         _ => false,
                     },
                     "Unexpected capture place"
@@ -583,7 +588,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         this.cfg.push_assign(
             block,
             source_info,
-            &Place::Local(temp),
+            &Place::Base(PlaceBase::Local(temp)),
             Rvalue::Ref(this.hir.tcx().types.re_erased, borrow_kind, arg_place),
         );
 
@@ -594,12 +599,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             this.schedule_drop_storage_and_value(
                 upvar_span,
                 temp_lifetime,
-                &Place::Local(temp),
+                &Place::Base(PlaceBase::Local(temp)),
                 upvar_ty,
             );
         }
 
-        block.and(Operand::Move(Place::Local(temp)))
+        block.and(Operand::Move(Place::Base(PlaceBase::Local(temp))))
     }
 
     // Helper to get a `-1` value of the appropriate type
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index efa1a4895e0c0..cba771f27065d 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -73,7 +73,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             );
         }
 
-        unpack!(block = this.into(&Place::Local(temp), block, expr));
+        unpack!(block = this.into(&Place::Base(PlaceBase::Local(temp)), block, expr));
 
         // In constants, temp_lifetime is None for temporaries that live for the
         // 'static lifetime. Thus we do not drop these temporaries and simply leak them.
@@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             this.schedule_drop_storage_and_value(
                 expr_span,
                 temp_lifetime,
-                &Place::Local(temp),
+                &Place::Base(PlaceBase::Local(temp)),
                 expr_ty,
             );
         }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 07db67a6ae00f..d9839e0c6ec5a 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -295,7 +295,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         is_user_variable: None,
                         is_block_tail: None,
                     });
-                    let ptr_temp = Place::Local(ptr_temp);
+                    let ptr_temp = Place::Base(PlaceBase::Local(ptr_temp));
                     let block = unpack!(this.into(&ptr_temp, block, ptr));
                     this.into(&ptr_temp.deref(), block, val)
                 } else {
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index aadc2368f5aec..9527a23279570 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -139,13 +139,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     Some(value) => {
                         debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
                         this.block_context.push(BlockFrame::SubExpr);
-                        let result = unpack!(this.into(&Place::Local(RETURN_PLACE), block, value));
+                        let result = unpack!(
+                            this.into(
+                                &Place::RETURN_PLACE,
+                                block,
+                                value
+                            )
+                        );
                         this.block_context.pop();
                         result
                     }
                     None => {
-                        this.cfg
-                            .push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE));
+                        this.cfg.push_assign_unit(
+                            block,
+                            source_info,
+                            &Place::RETURN_PLACE,
+                        );
                         block
                     }
                 };
@@ -226,7 +235,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         }
                     }
                     let temp = this.local_decls.push(local_decl);
-                    let place = Place::Local(temp);
+                    let place = Place::Base(PlaceBase::Local(temp));
                     debug!("created temp {:?} for expr {:?} in block_context: {:?}",
                            temp, expr, this.block_context);
                     place
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 2c4eb0bc091c3..8f1301b743e9d 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -543,7 +543,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 kind: StatementKind::StorageLive(local_id),
             },
         );
-        let place = Place::Local(local_id);
+        let place = Place::Base(PlaceBase::Local(local_id));
         let var_ty = self.local_decls[local_id].ty;
         let hir_id = self.hir.tcx().hir().node_to_hir_id(var);
         let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
@@ -559,7 +559,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         self.schedule_drop(
             span,
             region_scope,
-            &Place::Local(local_id),
+            &Place::Base(PlaceBase::Local(local_id)),
             var_ty,
             DropKind::Value {
                 cached_block: CachedBlock::default(),
@@ -1452,7 +1452,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 self.cfg.push_assign(
                     block,
                     scrutinee_source_info,
-                    &Place::Local(temp),
+                    &Place::Base(PlaceBase::Local(temp)),
                     borrow,
                 );
             }
@@ -1478,7 +1478,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     source_info: guard_end,
                     kind: StatementKind::FakeRead(
                         FakeReadCause::ForMatchGuard,
-                        Place::Local(temp),
+                        Place::Base(PlaceBase::Local(temp)),
                     ),
                 });
             }
@@ -1529,7 +1529,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // place they refer to can't be modified by the guard.
                 for binding in by_value_bindings.clone() {
                     let local_id = self.var_local_id(binding.var_id, RefWithinGuard);
-                    let place = Place::Local(local_id);
+                    let place = Place::Base(PlaceBase::Local(local_id));
                     self.cfg.push(
                         block,
                         Statement {
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 900f7f1744a13..2692c24806ff7 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -16,7 +16,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// call `schedule_drop` once the temporary is initialized.
     pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
         let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
-        let place = Place::Local(temp);
+        let place = Place::Base(PlaceBase::Local(temp));
         debug!("temp: created temp {:?} with type {:?}",
                place, self.local_decls[temp].ty);
         place
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 19507c900da64..e4f85887841eb 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -741,7 +741,7 @@ fn construct_const<'a, 'gcx, 'tcx>(
 
     let mut block = START_BLOCK;
     let expr = builder.hir.mirror(ast_expr);
-    unpack!(block = builder.into_expr(&Place::Local(RETURN_PLACE), block, expr));
+    unpack!(block = builder.into_expr(&Place::RETURN_PLACE, block, expr));
 
     let source_info = builder.source_info(span);
     builder.cfg.terminate(block, source_info, TerminatorKind::Return);
@@ -887,7 +887,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         for (index, arg_info) in arguments.iter().enumerate() {
             // Function arguments always get the first Local indices after the return place
             let local = Local::new(index + 1);
-            let place = Place::Local(local);
+            let place = Place::Base(PlaceBase::Local(local));
             let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
 
             // Make sure we drop (parts of) the argument even when not matched on.
@@ -936,7 +936,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         }
 
         let body = self.hir.mirror(ast_body);
-        self.into(&Place::Local(RETURN_PLACE), block, body)
+        self.into(&Place::RETURN_PLACE, block, body)
     }
 
     fn get_unit_temp(&mut self) -> Place<'tcx> {
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 71acf747d0856..4189e3e7ddbb6 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -662,7 +662,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             DropKind::Value { .. } => if !needs_drop { return },
             DropKind::Storage => {
                 match *place {
-                    Place::Local(index) => if index.index() <= self.arg_count {
+                    Place::Base(PlaceBase::Local(index)) => if index.index() <= self.arg_count {
                         span_bug!(
                             span, "`schedule_drop` called with index {} and arg_count {}",
                             index.index(),
@@ -936,7 +936,7 @@ fn build_scope_drops<'tcx>(
                 // Drop the storage for both value and storage drops.
                 // Only temps and vars need their storage dead.
                 match drop_data.location {
-                    Place::Local(index) if index.index() > arg_count => {
+                    Place::Base(PlaceBase::Local(index)) if index.index() > arg_count => {
                         cfg.push(block, Statement {
                             source_info,
                             kind: StatementKind::StorageDead(index)
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index 151a004dce942..f78c82a93020c 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -163,7 +163,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
 {
     let move_data = &ctxt.move_data;
     for arg in mir.args_iter() {
-        let place = mir::Place::Local(arg);
+        let place = mir::Place::Base(mir::PlaceBase::Local(arg));
         let lookup_result = move_data.rev_lookup.find(&place);
         on_lookup_result_bits(tcx, mir, move_data,
                               lookup_result,
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index 51d628ce6c5c2..b9c8879b3c364 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -92,9 +92,9 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> {
 
 fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
     match *place {
-        Place::Local(l) => Some(l),
-        Place::Promoted(_) |
-        Place::Static(..) => None,
+        Place::Base(PlaceBase::Local(l)) => Some(l),
+        Place::Base(PlaceBase::Promoted(_)) |
+        Place::Base(PlaceBase::Static(..)) => None,
         Place::Projection(ref proj) => {
             match proj.elem {
                 ProjectionElem::Deref => None,
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index beb0b3187082b..b47aff3a4f855 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -1,7 +1,7 @@
 use crate::borrow_check::borrow_set::{BorrowSet, BorrowData};
 use crate::borrow_check::place_ext::PlaceExt;
 
-use rustc::mir::{self, Location, Place, Mir};
+use rustc::mir::{self, Location, Place, PlaceBase, Mir};
 use rustc::ty::TyCtxt;
 use rustc::ty::RegionVid;
 
@@ -189,7 +189,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
     ) {
         debug!("kill_borrows_on_place: place={:?}", place);
         // Handle the `Place::Local(..)` case first and exit early.
-        if let Place::Local(local) = place {
+        if let Place::Base(PlaceBase::Local(local)) = place {
             if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
                 debug!("kill_borrows_on_place: borrow_indices={:?}", borrow_indices);
                 sets.kill_all(borrow_indices);
@@ -285,7 +285,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'gcx, 'tcx> {
             mir::StatementKind::StorageDead(local) => {
                 // Make sure there are no remaining borrows for locals that
                 // are gone out of scope.
-                self.kill_borrows_on_place(sets, &Place::Local(local));
+                self.kill_borrows_on_place(sets, &Place::Base(PlaceBase::Local(local)));
             }
 
             mir::StatementKind::InlineAsm { ref outputs, ref asm, .. } => {
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index cc92ebfab89b7..4dcfb3f1a7fc3 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -493,7 +493,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'gcx, 'tc
                 // storagedeads after everything ends, so if we don't regard the
                 // storagelive as killing storage, we would have a multiple assignment
                 // to immutable data error.
-                if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
+                if let LookupResult::Exact(mpi) =
+                    rev_lookup.find(&mir::Place::Base(mir::PlaceBase::Local(local))) {
                     debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
                            stmt, location, &init_path_map[mpi]);
                     sets.kill_all(&init_path_map[mpi]);
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 1ae050654b4b0..7a9140bce6288 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -33,13 +33,13 @@ impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
                 moves: IndexVec::new(),
                 loc_map: LocationMap::new(mir),
                 rev_lookup: MovePathLookup {
-                    locals: mir.local_decls.indices().map(Place::Local).map(|v| {
+                    locals: mir.local_decls.indices().map(PlaceBase::Local).map(|v| {
                         Self::new_move_path(
                             &mut move_paths,
                             &mut path_map,
                             &mut init_path_map,
                             None,
-                            v,
+                            Place::Base(v),
                         )
                     }).collect(),
                     projections: Default::default(),
@@ -96,9 +96,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
     {
         debug!("lookup({:?})", place);
         match *place {
-            Place::Local(local) => Ok(self.builder.data.rev_lookup.locals[local]),
-            Place::Promoted(..) |
-            Place::Static(..) => {
+            Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
+            Place::Base(PlaceBase::Promoted(..)) |
+            Place::Base(PlaceBase::Static(..)) => {
                 Err(MoveError::cannot_move_out_of(self.loc, Static))
             }
             Place::Projection(ref proj) => {
@@ -285,7 +285,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
             }
             StatementKind::StorageLive(_) => {}
             StatementKind::StorageDead(local) => {
-                self.gather_move(&Place::Local(local));
+                self.gather_move(&Place::Base(PlaceBase::Local(local)));
             }
             StatementKind::SetDiscriminant{ .. } => {
                 span_bug!(stmt.source_info.span,
@@ -345,7 +345,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
             TerminatorKind::Unreachable => { }
 
             TerminatorKind::Return => {
-                self.gather_move(&Place::Local(RETURN_PLACE));
+                self.gather_move(&Place::RETURN_PLACE);
             }
 
             TerminatorKind::Assert { ref cond, .. } => {
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index efd979a7da4fb..0c29ea8ab4afa 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -273,9 +273,9 @@ impl<'tcx> MovePathLookup<'tcx> {
     // parent.
     pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
         match *place {
-            Place::Local(local) => LookupResult::Exact(self.locals[local]),
-            Place::Promoted(_) |
-            Place::Static(..) => LookupResult::Parent(None),
+            Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
+            Place::Base(PlaceBase::Promoted(_)) |
+            Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
             Place::Projection(ref proj) => {
                 match self.find(&proj.base) {
                     LookupResult::Exact(base_path) => {
@@ -347,7 +347,7 @@ impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
     pub fn base_local(&self, mut mpi: MovePathIndex) -> Option<Local> {
         loop {
             let path = &self.move_paths[mpi];
-            if let Place::Local(l) = path.place { return Some(l); }
+            if let Place::Base(PlaceBase::Local(l)) = path.place { return Some(l); }
             if let Some(parent) = path.parent { mpi = parent; continue } else { return None }
         }
     }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 474df457f61a2..979595d6c0009 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -515,9 +515,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
+        use rustc::mir::PlaceBase;
         let op = match *mir_place {
-            Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
-            Local(local) => self.access_local(self.frame(), local, layout)?,
+            Base(PlaceBase::Local(mir::RETURN_PLACE)) => return err!(ReadFromReturnPointer),
+            Base(PlaceBase::Local(local)) => self.access_local(self.frame(), local, layout)?,
 
             Projection(ref proj) => {
                 let op = self.eval_place_to_op(&proj.base, None)?;
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 7b66d11131c13..4df274bc9df97 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -581,8 +581,9 @@ where
         mir_place: &mir::Place<'tcx>
     ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
+        use rustc::mir::PlaceBase;
         Ok(match *mir_place {
-            Promoted(ref promoted) => {
+            Base(PlaceBase::Promoted(ref promoted)) => {
                 let instance = self.frame().instance;
                 self.const_eval_raw(GlobalId {
                     instance,
@@ -590,7 +591,7 @@ where
                 })?
             }
 
-            Static(ref static_) => {
+            Base(PlaceBase::Static(ref static_)) => {
                 assert!(!static_.ty.needs_subst());
                 let layout = self.layout_of(static_.ty)?;
                 let instance = ty::Instance::mono(*self.tcx, static_.def_id);
@@ -624,8 +625,9 @@ where
         mir_place: &mir::Place<'tcx>
     ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
+        use rustc::mir::PlaceBase;
         let place = match *mir_place {
-            Local(mir::RETURN_PLACE) => match self.frame().return_place {
+            Base(PlaceBase::Local(mir::RETURN_PLACE)) => match self.frame().return_place {
                 Some(return_place) =>
                     // We use our layout to verify our assumption; caller will validate
                     // their layout on return.
@@ -635,7 +637,7 @@ where
                     },
                 None => return err!(InvalidNullPointerUsage),
             },
-            Local(local) => PlaceTy {
+            Base(PlaceBase::Local(local)) => PlaceTy {
                 place: Place::Local {
                     frame: self.cur_frame(),
                     local,
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index c2ee3f5715bd3..83469d749870f 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -352,7 +352,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     // not advance `caller_iter` for ZSTs.
                     let mut locals_iter = mir.args_iter();
                     while let Some(local) = locals_iter.next() {
-                        let dest = self.eval_place(&mir::Place::Local(local))?;
+                        let dest = self.eval_place(
+                            &mir::Place::Base(mir::PlaceBase::Local(local))
+                        )?;
                         if Some(local) == mir.spread_arg {
                             // Must be a tuple
                             for i in 0..dest.layout.fields.count() {
@@ -371,7 +373,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     }
                     // Don't forget to check the return type!
                     if let Some(caller_ret) = dest {
-                        let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
+                        let callee_ret = self.eval_place(
+                            &mir::Place::RETURN_PLACE
+                        )?;
                         if !Self::check_argument_compat(
                             rust_abi,
                             caller_ret.layout,
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index ce7c9af81cb07..adc328f1033ec 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -221,7 +221,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(..) = ty {
         // The first argument (index 0), but add 1 for the return value.
-        let dropee_ptr = Place::Local(Local::new(1+0));
+        let dropee_ptr = Place::Base(PlaceBase::Local(Local::new(1+0)));
         if tcx.sess.opts.debugging_opts.mir_emit_retag {
             // Function arguments should be retagged, and we make this one raw.
             mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
@@ -317,8 +317,8 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
     let is_copy = self_ty.is_copy_modulo_regions(tcx, tcx.param_env(def_id), builder.span);
 
-    let dest = Place::Local(RETURN_PLACE);
-    let src = Place::Local(Local::new(1+0)).deref();
+    let dest = Place::RETURN_PLACE;
+    let src = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
 
     match self_ty.sty {
         _ if is_copy => builder.copy_shim(),
@@ -424,10 +424,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
     }
 
     fn copy_shim(&mut self) {
-        let rcvr = Place::Local(Local::new(1+0)).deref();
+        let rcvr = Place::Base(PlaceBase::Local(Local::new(1+0))).deref();
         let ret_statement = self.make_statement(
             StatementKind::Assign(
-                Place::Local(RETURN_PLACE),
+                Place::RETURN_PLACE,
                 box Rvalue::Use(Operand::Copy(rcvr))
             )
         );
@@ -436,9 +436,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
 
     fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
         let span = self.span;
-        Place::Local(
+        Place::Base(PlaceBase::Local(
             self.local_decls.push(temp_decl(mutability, ty, span))
-        )
+        ))
     }
 
     fn make_clone_call(
@@ -546,7 +546,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         let inits = vec![
             self.make_statement(
                 StatementKind::Assign(
-                    Place::Local(beg),
+                    Place::Base(PlaceBase::Local(beg)),
                     box Rvalue::Use(Operand::Constant(self.make_usize(0)))
                 )
             ),
@@ -564,7 +564,11 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         //     BB #3;
         // }
         // BB #4;
-        self.loop_header(Place::Local(beg), end, BasicBlock::new(2), BasicBlock::new(4), false);
+        self.loop_header(Place::Base(PlaceBase::Local(beg)),
+                         end,
+                         BasicBlock::new(2),
+                         BasicBlock::new(4),
+                         false);
 
         // BB #2
         // `dest[i] = Clone::clone(src[beg])`;
@@ -580,10 +584,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         let statements = vec![
             self.make_statement(
                 StatementKind::Assign(
-                    Place::Local(beg),
+                    Place::Base(PlaceBase::Local(beg)),
                     box Rvalue::BinaryOp(
                         BinOp::Add,
-                        Operand::Copy(Place::Local(beg)),
+                        Operand::Copy(Place::Base(PlaceBase::Local(beg))),
                         Operand::Constant(self.make_usize(1))
                     )
                 )
@@ -603,7 +607,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         let beg = self.local_decls.push(temp_decl(Mutability::Mut, tcx.types.usize, span));
         let init = self.make_statement(
             StatementKind::Assign(
-                Place::Local(beg),
+                Place::Base(PlaceBase::Local(beg)),
                 box Rvalue::Use(Operand::Constant(self.make_usize(0)))
             )
         );
@@ -614,7 +618,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         //     BB #8;
         // }
         // BB #9;
-        self.loop_header(Place::Local(beg), Place::Local(end),
+        self.loop_header(Place::Base(PlaceBase::Local(beg)), Place::Base(PlaceBase::Local(end)),
                          BasicBlock::new(7), BasicBlock::new(9), true);
 
         // BB #7 (cleanup)
@@ -630,10 +634,10 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
         // `goto #6;`
         let statement = self.make_statement(
             StatementKind::Assign(
-                Place::Local(beg),
+                Place::Base(PlaceBase::Local(beg)),
                 box Rvalue::BinaryOp(
                     BinOp::Add,
-                    Operand::Copy(Place::Local(beg)),
+                    Operand::Copy(Place::Base(PlaceBase::Local(beg))),
                     Operand::Constant(self.make_usize(1))
                 )
             )
@@ -718,7 +722,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
 
     let rcvr_arg = Local::new(1+0);
-    let rcvr_l = Place::Local(rcvr_arg);
+    let rcvr_l = Place::Base(PlaceBase::Local(rcvr_arg));
     let mut statements = vec![];
 
     let rcvr = match rcvr_adjustment {
@@ -748,11 +752,11 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             statements.push(Statement {
                 source_info,
                 kind: StatementKind::Assign(
-                    Place::Local(ref_rcvr),
+                    Place::Base(PlaceBase::Local(ref_rcvr)),
                     box Rvalue::Ref(tcx.types.re_erased, borrow_kind, rcvr_l)
                 )
             });
-            Operand::Move(Place::Local(ref_rcvr))
+            Operand::Move(Place::Base(PlaceBase::Local(ref_rcvr)))
         }
     };
 
@@ -774,12 +778,12 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(untuple_args) = untuple_args {
         args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
-            let arg_place = Place::Local(Local::new(1+1));
+            let arg_place = Place::Base(PlaceBase::Local(Local::new(1+1)));
             Operand::Move(arg_place.field(Field::new(i), *ity))
         }));
     } else {
         args.extend((1..sig.inputs().len()).map(|i| {
-            Operand::Move(Place::Local(Local::new(1+i)))
+            Operand::Move(Place::Base(PlaceBase::Local(Local::new(1+i))))
         }));
     }
 
@@ -797,7 +801,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     block(&mut blocks, statements, TerminatorKind::Call {
         func: callee,
         args,
-        destination: Some((Place::Local(RETURN_PLACE),
+        destination: Some((Place::RETURN_PLACE,
                            BasicBlock::new(1))),
         cleanup: if let Adjustment::RefMut = rcvr_adjustment {
             Some(BasicBlock::new(3))
@@ -810,7 +814,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if let Adjustment::RefMut = rcvr_adjustment {
         // BB #1 - drop for Self
         block(&mut blocks, vec![], TerminatorKind::Drop {
-            location: Place::Local(rcvr_arg),
+            location: Place::Base(PlaceBase::Local(rcvr_arg)),
             target: BasicBlock::new(2),
             unwind: None
         }, false);
@@ -820,7 +824,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if let Adjustment::RefMut = rcvr_adjustment {
         // BB #3 - drop if closure panics
         block(&mut blocks, vec![], TerminatorKind::Drop {
-            location: Place::Local(rcvr_arg),
+            location: Place::Base(PlaceBase::Local(rcvr_arg)),
             target: BasicBlock::new(4),
             unwind: None
         }, true);
@@ -892,11 +896,11 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
         statements: vec![Statement {
             source_info,
             kind: StatementKind::Assign(
-                Place::Local(RETURN_PLACE),
+                Place::RETURN_PLACE,
                 box Rvalue::Aggregate(
                     box AggregateKind::Adt(adt_def, variant_no, substs, None, None),
                     (1..sig.inputs().len()+1).map(|i| {
-                        Operand::Move(Place::Local(Local::new(i)))
+                        Operand::Move(Place::Base(PlaceBase::Local(Local::new(i))))
                     }).collect()
                 )
             )
diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
index 4d4c89b8b6a40..e8528eee0bcab 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -121,10 +121,10 @@ fn add_move_for_packed_drop<'a, 'tcx>(
 
     patch.add_statement(
         loc, StatementKind::StorageLive(temp));
-    patch.add_assign(loc, Place::Local(temp),
+    patch.add_assign(loc, Place::Base(PlaceBase::Local(temp)),
                      Rvalue::Use(Operand::Move(location.clone())));
     patch.patch_terminator(loc.block, TerminatorKind::Drop {
-        location: Place::Local(temp),
+        location: Place::Base(PlaceBase::Local(temp)),
         target: storage_dead_block,
         unwind
     });
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index e66c11aa36e0e..20b75c5586794 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -21,9 +21,9 @@ fn is_stable<'tcx>(
 
     match *place {
         // Locals and statics have stable addresses, for sure
-        Local { .. } |
-        Promoted { .. } |
-        Static { .. } =>
+        Base(PlaceBase::Local { .. }) |
+        Base(PlaceBase::Promoted { .. }) |
+        Base(PlaceBase::Static { .. }) =>
             true,
         // Recurse for projections
         Projection(ref proj) => {
@@ -101,7 +101,7 @@ impl MirPass for AddRetag {
             };
             // Gather all arguments, skip return value.
             let places = local_decls.iter_enumerated().skip(1).take(arg_count)
-                    .map(|(local, _)| Place::Local(local))
+                    .map(|(local, _)| Place::Base(PlaceBase::Local(local)))
                     .filter(needs_retag)
                     .collect::<Vec<_>>();
             // Emit their retags.
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 3ed63d749cd35..ceef15091b5f0 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -241,7 +241,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                     );
                 }
                 let old_source_info = self.source_info;
-                if let &Place::Local(local) = base {
+                if let &Place::Base(PlaceBase::Local(local)) = base {
                     if self.mir.local_decls[local].internal {
                         // Internal locals are used in the `move_val_init` desugaring.
                         // We want to check unsafety against the source info of the
@@ -297,13 +297,13 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 }
                 self.source_info = old_source_info;
             }
-            &Place::Local(..) => {
+            &Place::Base(PlaceBase::Local(..)) => {
                 // locals are safe
             }
-            &Place::Promoted(_) => {
+            &Place::Base(PlaceBase::Promoted(_)) => {
                 bug!("unsafety checking should happen before promotion")
             }
-            &Place::Static(box Static { def_id, ty: _ }) => {
+            &Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
                 if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
                     self.require_unsafe("use of mutable static",
                         "mutable statics can be mutated by multiple threads: aliasing violations \
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 5ed0055e7c4f4..25dee3ec95566 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -3,7 +3,7 @@
 
 
 use rustc::hir::def::Def;
-use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
 use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
@@ -267,7 +267,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
 
     fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         match *place {
-            Place::Local(loc) => self.places[loc].clone(),
+            Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Field(field, _) => {
                     trace!("field proj on {:?}", proj.base);
@@ -282,7 +282,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
                 // an `Index` projection would throw us off-track.
                 _ => None,
             },
-            Place::Promoted(ref promoted) => {
+            Place::Base(PlaceBase::Promoted(ref promoted)) => {
                 let generics = self.tcx.generics_of(self.source.def_id());
                 if generics.requires_monomorphization(self.tcx) {
                     // FIXME: can't handle code with generics
@@ -556,7 +556,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                 .to_ty(self.tcx);
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
                 if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
-                    if let Place::Local(local) = *place {
+                    if let Place::Base(PlaceBase::Local(local)) = *place {
                         trace!("checking whether {:?} can be stored to {:?}", value, local);
                         if self.can_const_prop[local] {
                             trace!("storing {:?} to {:?}", value, local);
@@ -591,7 +591,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                             while let Place::Projection(ref proj) = *place {
                                 place = &proj.base;
                             }
-                            if let Place::Local(local) = *place {
+                            if let Place::Base(PlaceBase::Local(local)) = *place {
                                 self.places[local] = None;
                             }
                         },
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index 7d907ca3a215e..817a2f31c0736 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -19,7 +19,9 @@
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
-use rustc::mir::{Constant, Local, LocalKind, Location, Place, Mir, Operand, Rvalue, StatementKind};
+use rustc::mir::{
+    Constant, Local, LocalKind, Location, Place, PlaceBase, Mir, Operand, Rvalue, StatementKind
+};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
 use crate::transform::{MirPass, MirSource};
@@ -94,8 +96,10 @@ impl MirPass for CopyPropagation {
 
                     // That use of the source must be an assignment.
                     match statement.kind {
-                        StatementKind::Assign(Place::Local(local), box Rvalue::Use(ref operand)) if
-                                local == dest_local => {
+                        StatementKind::Assign(
+                            Place::Base(PlaceBase::Local(local)),
+                            box Rvalue::Use(ref operand)
+                        ) if local == dest_local => {
                             let maybe_action = match *operand {
                                 Operand::Copy(ref src_place) |
                                 Operand::Move(ref src_place) => {
@@ -144,12 +148,12 @@ fn eliminate_self_assignments<'tcx>(
             if let Some(stmt) = mir[location.block].statements.get(location.statement_index) {
                 match stmt.kind {
                     StatementKind::Assign(
-                        Place::Local(local),
-                        box Rvalue::Use(Operand::Copy(Place::Local(src_local))),
+                        Place::Base(PlaceBase::Local(local)),
+                        box Rvalue::Use(Operand::Copy(Place::Base(PlaceBase::Local(src_local)))),
                     ) |
                     StatementKind::Assign(
-                        Place::Local(local),
-                        box Rvalue::Use(Operand::Move(Place::Local(src_local))),
+                        Place::Base(PlaceBase::Local(local)),
+                        box Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(src_local)))),
                     ) if local == dest_local && dest_local == src_local => {}
                     _ => {
                         continue;
@@ -176,7 +180,7 @@ impl<'tcx> Action<'tcx> {
     fn local_copy(mir: &Mir<'tcx>, def_use_analysis: &DefUseAnalysis<'_>, src_place: &Place<'tcx>)
                   -> Option<Action<'tcx>> {
         // The source must be a local.
-        let src_local = if let Place::Local(local) = *src_place {
+        let src_local = if let Place::Base(PlaceBase::Local(local)) = *src_place {
             local
         } else {
             debug!("  Can't copy-propagate local: source is not a local");
@@ -330,8 +334,8 @@ impl<'tcx> MutVisitor<'tcx> for ConstantPropagationVisitor<'tcx> {
         self.super_operand(operand, location);
 
         match *operand {
-            Operand::Copy(Place::Local(local)) |
-            Operand::Move(Place::Local(local)) if local == self.dest_local => {}
+            Operand::Copy(Place::Base(PlaceBase::Local(local))) |
+            Operand::Move(Place::Base(PlaceBase::Local(local))) if local == self.dest_local => {}
             _ => return,
         }
 
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 0f8db5f7334bd..74175d0149ff4 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -330,7 +330,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     }
 
     fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
-        self.drop_flags.get(&index).map(|t| Place::Local(*t))
+        self.drop_flags.get(&index).map(|t| Place::Base(PlaceBase::Local(*t)))
     }
 
     /// create a patch that elaborates all drops in the input
@@ -543,7 +543,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         if let Some(&flag) = self.drop_flags.get(&path) {
             let span = self.patch.source_info_for_location(self.mir, loc).span;
             let val = self.constant_bool(span, val.value());
-            self.patch.add_assign(loc, Place::Local(flag), val);
+            self.patch.add_assign(loc, Place::Base(PlaceBase::Local(flag)), val);
         }
     }
 
@@ -552,7 +552,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         let span = self.patch.source_info_for_location(self.mir, loc).span;
         let false_ = self.constant_bool(span, false);
         for flag in self.drop_flags.values() {
-            self.patch.add_assign(loc, Place::Local(*flag), false_.clone());
+            self.patch.add_assign(loc, Place::Base(PlaceBase::Local(*flag)), false_.clone());
         }
     }
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 09142828f18af..c455d38cebce8 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -102,7 +102,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
                     place: &mut Place<'tcx>,
                     context: PlaceContext<'tcx>,
                     location: Location) {
-        if *place == Place::Local(self_arg()) {
+        if *place == Place::Base(PlaceBase::Local(self_arg())) {
             *place = Place::Projection(Box::new(Projection {
                 base: place.clone(),
                 elem: ProjectionElem::Deref,
@@ -129,7 +129,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
                     place: &mut Place<'tcx>,
                     context: PlaceContext<'tcx>,
                     location: Location) {
-        if *place == Place::Local(self_arg()) {
+        if *place == Place::Base(PlaceBase::Local(self_arg())) {
             *place = Place::Projection(Box::new(Projection {
                 base: place.clone(),
                 elem: ProjectionElem::Field(Field::new(0), self.ref_gen_ty),
@@ -183,7 +183,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
 
     // Create a Place referencing a generator struct field
     fn make_field(&self, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> {
-        let base = Place::Local(self_arg());
+        let base = Place::Base(PlaceBase::Local(self_arg()));
         let field = Projection {
             base: base,
             elem: ProjectionElem::Field(Field::new(idx), ty),
@@ -223,7 +223,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
                     place: &mut Place<'tcx>,
                     context: PlaceContext<'tcx>,
                     location: Location) {
-        if let Place::Local(l) = *place {
+        if let Place::Base(PlaceBase::Local(l)) = *place {
             // Replace an Local in the remap with a generator struct access
             if let Some(&(ty, idx)) = self.remap.get(&l) {
                 *place = self.make_field(idx, ty);
@@ -249,7 +249,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
         let ret_val = match data.terminator().kind {
             TerminatorKind::Return => Some((VariantIdx::new(1),
                 None,
-                Operand::Move(Place::Local(self.new_ret_local)),
+                Operand::Move(Place::Base(PlaceBase::Local(self.new_ret_local))),
                 None)),
             TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
                 Some(resume),
@@ -263,7 +263,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
             // We must assign the value first in case it gets declared dead below
             data.statements.push(Statement {
                 source_info,
-                kind: StatementKind::Assign(Place::Local(RETURN_PLACE),
+                kind: StatementKind::Assign(Place::RETURN_PLACE,
                                             box self.make_state(state_idx, v)),
             });
             let state = if let Some(resume) = resume { // Yield
@@ -597,7 +597,7 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             &Terminator {
                 source_info,
                 kind: TerminatorKind::Drop {
-                    location: Place::Local(local),
+                    location: Place::Base(PlaceBase::Local(local)),
                     target,
                     unwind
                 }
@@ -619,7 +619,7 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             elaborate_drop(
                 &mut elaborator,
                 source_info,
-                &Place::Local(gen),
+                &Place::Base(PlaceBase::Local(gen)),
                 (),
                 target,
                 unwind,
@@ -693,7 +693,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         // Alias tracking must know we changed the type
         mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
             source_info,
-            kind: StatementKind::Retag(RetagKind::Raw, Place::Local(self_arg())),
+            kind: StatementKind::Retag(RetagKind::Raw, Place::Base(PlaceBase::Local(self_arg()))),
         })
     }
 
@@ -809,7 +809,7 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
     let drop_clean = BasicBlock::new(mir.basic_blocks().len());
     let term = TerminatorKind::Drop {
-        location: Place::Local(self_arg()),
+        location: Place::Base(PlaceBase::Local(self_arg())),
         target: return_block,
         unwind: None,
     };
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 56e4926090eac..4cdef015b53ff 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -449,7 +449,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                         }
                         // Static variables need a borrow because the callee
                         // might modify the same static.
-                        Place::Static(_) => true,
+                        Place::Base(PlaceBase::Static(_)) => true,
                         _ => false
                     }
                 }
@@ -466,7 +466,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     let temp = LocalDecl::new_temp(ty, callsite.location.span);
 
                     let tmp = caller_mir.local_decls.push(temp);
-                    let tmp = Place::Local(tmp);
+                    let tmp = Place::Base(PlaceBase::Local(tmp));
 
                     let stmt = Statement {
                         source_info: callsite.location,
@@ -560,7 +560,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_mir);
             assert!(args.next().is_none());
 
-            let tuple = Place::Local(tuple);
+            let tuple = Place::Base(PlaceBase::Local(tuple));
             let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
                 s
             } else {
@@ -599,7 +599,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
         // FIXME: Analysis of the usage of the arguments to avoid
         // unnecessary temporaries.
 
-        if let Operand::Move(Place::Local(local)) = arg {
+        if let Operand::Move(Place::Base(PlaceBase::Local(local))) = arg {
             if caller_mir.local_kind(local) == LocalKind::Temp {
                 // Reuse the operand if it's a temporary already
                 return local;
@@ -617,7 +617,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
         let stmt = Statement {
             source_info: callsite.location,
-            kind: StatementKind::Assign(Place::Local(arg_tmp), box arg),
+            kind: StatementKind::Assign(Place::Base(PlaceBase::Local(arg_tmp)), box arg),
         };
         caller_mir[callsite.bb].statements.push(stmt);
         arg_tmp
@@ -665,7 +665,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
                    _location: Location) {
         if *local == RETURN_PLACE {
             match self.destination {
-                Place::Local(l) => {
+                Place::Base(PlaceBase::Local(l)) => {
                     *local = l;
                     return;
                 },
@@ -686,11 +686,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
                     _location: Location) {
 
         match place {
-            Place::Local(RETURN_PLACE) => {
+            Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
                 // Return pointer; update the place itself
                 *place = self.destination.clone();
             },
-            Place::Promoted(ref mut promoted) => {
+            Place::Base(PlaceBase::Promoted(ref mut promoted)) => {
                 if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
                     promoted.0 = p;
                 }
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 290915763e275..e0e64fd1f9b54 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -1,6 +1,6 @@
 //! Performs various peephole optimizations.
 
-use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local};
+use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::{TyCtxt, TyKind};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -45,7 +45,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
             let new_place = match *rvalue {
                 Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
                     // Replace with dummy
-                    mem::replace(&mut projection.base, Place::Local(Local::new(0)))
+                    mem::replace(&mut projection.base, Place::Base(PlaceBase::Local(Local::new(0))))
                 }
                 _ => bug!("Detected `&*` but didn't find `&*`!"),
             };
diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs
index 3d1f55e530e62..ad108587247fb 100644
--- a/src/librustc_mir/transform/lower_128bit.rs
+++ b/src/librustc_mir/transform/lower_128bit.rs
@@ -86,13 +86,13 @@ impl Lower128Bit {
                     block.statements.push(Statement {
                         source_info: source_info,
                         kind: StatementKind::Assign(
-                            Place::Local(local),
+                            Place::Base(PlaceBase::Local(local)),
                             box Rvalue::Cast(
                                 CastKind::Misc,
                                 rhs,
                                 rhs_override_ty.unwrap())),
                     });
-                    rhs = Operand::Move(Place::Local(local));
+                    rhs = Operand::Move(Place::Base(PlaceBase::Local(local)));
                 }
 
                 let call_did = check_lang_item_type(
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index a6726718e2d23..831d8b46a65c3 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -178,7 +178,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 span,
                 scope: OUTERMOST_SOURCE_SCOPE
             },
-            kind: StatementKind::Assign(Place::Local(dest), box rvalue)
+            kind: StatementKind::Assign(Place::Base(PlaceBase::Local(dest)), box rvalue)
         });
     }
 
@@ -268,7 +268,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                             func,
                             args,
                             cleanup: None,
-                            destination: Some((Place::Local(new_temp), new_target)),
+                            destination: Some(
+                                (Place::Base(PlaceBase::Local(new_temp)), new_target)
+                            ),
                             from_hir_call,
                         },
                         ..terminator
@@ -292,7 +294,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] =
                     LocalDecl::new_return_place(ty, span);
-                Place::Promoted(box (promoted_id, ty))
+                Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
             match candidate {
@@ -373,7 +375,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         match candidate {
             Candidate::Ref(Location { block, statement_index }) => {
                 match mir[block].statements[statement_index].kind {
-                    StatementKind::Assign(Place::Local(local), _) => {
+                    StatementKind::Assign(Place::Base(PlaceBase::Local(local)), _) => {
                         if temps[local] == TempState::PromotedOut {
                             // Already promoted.
                             continue;
@@ -420,7 +422,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
     for block in mir.basic_blocks_mut() {
         block.statements.retain(|statement| {
             match statement.kind {
-                StatementKind::Assign(Place::Local(index), _) |
+                StatementKind::Assign(Place::Base(PlaceBase::Local(index)), _) |
                 StatementKind::StorageLive(index) |
                 StatementKind::StorageDead(index) => {
                     !promoted(index)
@@ -430,7 +432,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         });
         let terminator = block.terminator_mut();
         match terminator.kind {
-            TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
+            TerminatorKind::Drop { location: Place::Base(PlaceBase::Local(index)), target, .. } => {
                 if promoted(index) {
                     terminator.kind = TerminatorKind::Goto {
                         target,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 285c674643f2e..d41098e2881a6 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -186,9 +186,9 @@ trait Qualif {
 
     fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
         match *place {
-            Place::Local(local) => Self::in_local(cx, local),
-            Place::Promoted(_) => bug!("qualifying already promoted MIR"),
-            Place::Static(ref static_) => Self::in_static(cx, static_),
+            Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
+            Place::Base(PlaceBase::Promoted(_)) => bug!("qualifying already promoted MIR"),
+            Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_),
             Place::Projection(ref proj) => Self::in_projection(cx, proj),
         }
     }
@@ -730,7 +730,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                     place = &proj.base;
                 }
                 debug!("qualify_consts: promotion candidate: place={:?}", place);
-                if let Place::Local(local) = *place {
+                if let Place::Base(PlaceBase::Local(local)) = *place {
                     if self.mir.local_kind(local) == LocalKind::Temp {
                         debug!("qualify_consts: promotion candidate: local={:?}", local);
                         // The borrowed place doesn't have `HasMutInterior`
@@ -754,7 +754,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
         let index = loop {
             match dest {
                 // We treat all locals equal in constants
-                Place::Local(index) => break *index,
+                Place::Base(PlaceBase::Local(index)) => break *index,
                 // projections are transparent for assignments
                 // we qualify the entire destination at once, even if just a field would have
                 // stricter qualification
@@ -768,8 +768,9 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                     );
                     dest = &proj.base;
                 },
-                Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
-                Place::Static(..) => {
+                Place::Base(PlaceBase::Promoted(..)) =>
+                    bug!("promoteds don't exist yet during promotion"),
+                Place::Base(PlaceBase::Static(..)) => {
                     // Catch more errors in the destination. `visit_place` also checks that we
                     // do not try to access statics from constants or try to mutate statics
                     self.visit_place(
@@ -878,7 +879,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
             match *candidate {
                 Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
                     match self.mir[bb].statements[stmt_idx].kind {
-                        StatementKind::Assign(_, box Rvalue::Ref(_, _, Place::Local(index))) => {
+                        StatementKind::Assign(
+                            _,
+                            box Rvalue::Ref(_, _, Place::Base(PlaceBase::Local(index)))
+                        ) => {
                             promoted_temps.insert(index);
                         }
                         _ => {}
@@ -915,9 +919,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
         self.super_place(place, context, location);
         match *place {
-            Place::Local(_) |
-            Place::Promoted(_) => {}
-            Place::Static(ref global) => {
+            Place::Base(PlaceBase::Local(_)) |
+            Place::Base(PlaceBase::Promoted(_)) => {}
+            Place::Base(PlaceBase::Static(ref global)) => {
                 if self.tcx
                        .get_attrs(global.def_id)
                        .iter()
@@ -1032,7 +1036,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::Local(local) = *place {
+                if let Place::Base(PlaceBase::Local(local)) = *place {
                     self.cx.per_local[NeedsDrop].remove(local);
                 }
             }
@@ -1335,7 +1339,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::Local(local) = *place {
+                let needs_drop = if let Place::Base(PlaceBase::Local(local)) = *place {
                     if NeedsDrop::in_local(self, local) {
                         Some(self.mir.local_decls[local].source_info.span)
                     } else {
@@ -1565,7 +1569,11 @@ impl MirPass for QualifyAndPromoteConstants {
                 });
                 let terminator = block.terminator_mut();
                 match terminator.kind {
-                    TerminatorKind::Drop { location: Place::Local(index), target, .. } => {
+                    TerminatorKind::Drop {
+                        location: Place::Base(PlaceBase::Local(index)),
+                        target,
+                        ..
+                    } => {
                         if promoted_temps.contains(index) {
                             terminator.kind = TerminatorKind::Goto {
                                 target,
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 34f850fc4aad2..6c44fac10f59d 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -252,10 +252,11 @@ fn check_place(
     span: Span,
 ) -> McfResult {
     match place {
-        Place::Local(_) => Ok(()),
+        Place::Base(PlaceBase::Local(_)) => Ok(()),
         // promoteds are always fine, they are essentially constants
-        Place::Promoted(_) => Ok(()),
-        Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
+        Place::Base(PlaceBase::Promoted(_)) => Ok(()),
+        Place::Base(PlaceBase::Static(_)) =>
+            Err((span, "cannot access `static` items in const fn".into())),
         Place::Projection(proj) => {
             match proj.elem {
                 | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 0ad33bff9d6ca..b7493b25d4650 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -47,7 +47,7 @@ impl RemoveNoopLandingPads {
                     // These are all nops in a landing pad
                 }
 
-                StatementKind::Assign(Place::Local(_), box Rvalue::Use(_)) => {
+                StatementKind::Assign(Place::Base(PlaceBase::Local(_)), box Rvalue::Use(_)) => {
                     // Writing to a local (e.g., a drop flag) does not
                     // turn a landing pad to a non-nop
                 }
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 40e02e712c156..a44ec526f9ddc 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -115,8 +115,8 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
     assert!(args.len() == 1);
     let peek_arg_place = match args[0] {
-        mir::Operand::Copy(ref place @ mir::Place::Local(_)) |
-        mir::Operand::Move(ref place @ mir::Place::Local(_)) => Some(place),
+        mir::Operand::Copy(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) |
+        mir::Operand::Move(ref place @ mir::Place::Base(mir::PlaceBase::Local(_))) => Some(place),
         _ => None,
     };
 
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index fd8d68a482262..b1d898bb5b026 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
                     let temp = self.patch.new_temp(item_ty, self.mir.source_info(location).span);
                     self.patch.add_statement(location, StatementKind::StorageLive(temp));
                     self.patch.add_assign(location,
-                                          Place::Local(temp),
+                                          Place::Base(PlaceBase::Local(temp)),
                                           Rvalue::Use(
                                               Operand::Move(
                                                   Place::Projection(box PlaceProjection{
@@ -113,12 +113,16 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
                                                   }))));
                     temp
                 }).collect();
-                self.patch.add_assign(location,
-                                      dst_place.clone(),
-                                      Rvalue::Aggregate(box AggregateKind::Array(item_ty),
-                                      temps.iter().map(
-                                          |x| Operand::Move(Place::Local(*x))).collect()
-                                      ));
+                self.patch.add_assign(
+                    location,
+                    dst_place.clone(),
+                    Rvalue::Aggregate(
+                        box AggregateKind::Array(item_ty),
+                        temps.iter().map(
+                            |x| Operand::Move(Place::Base(PlaceBase::Local(*x)))
+                        ).collect()
+                    )
+                );
                 for temp in temps {
                     self.patch.add_statement(location, StatementKind::StorageDead(temp));
                 }
@@ -176,7 +180,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
                 if let StatementKind::Assign(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::Local(local)) = item {
+                            if let Operand::Move(Place::Base(PlaceBase::Local(local))) = item {
                                 let local_use = &visitor.locals_use[*local];
                                 let opt_index_and_place = Self::try_get_item_source(local_use, mir);
                                 // each local should be used twice:
@@ -257,7 +261,7 @@ impl RestoreSubsliceArrayMoveOut {
             if block.statements.len() > location.statement_index {
                 let statement = &block.statements[location.statement_index];
                 if let StatementKind::Assign(
-                    Place::Local(_),
+                    Place::Base(PlaceBase::Local(_)),
                     box Rvalue::Use(Operand::Move(Place::Projection(box PlaceProjection{
                         ref base, elem: ProjectionElem::ConstantIndex{
                             offset, min_length: _, from_end: false}})))) = statement.kind {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index cf3ba1765406c..26fa8d6d1f0bf 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -486,7 +486,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         // discriminant after it is free-ed, because that
         // way lies only trouble.
         let discr_ty = adt.repr.discr_type().to_ty(self.tcx());
-        let discr = Place::Local(self.new_temp(discr_ty));
+        let discr = Place::Base(PlaceBase::Local(self.new_temp(discr_ty)));
         let discr_rv = Rvalue::Discriminant(self.place.clone());
         let switch_block = BasicBlockData {
             statements: vec![self.assign(&discr, discr_rv)],
@@ -520,11 +520,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             mutbl: hir::Mutability::MutMutable
         });
         let ref_place = self.new_temp(ref_ty);
-        let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
+        let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
 
         let result = BasicBlockData {
             statements: vec![self.assign(
-                &Place::Local(ref_place),
+                &Place::Base(PlaceBase::Local(ref_place)),
                 Rvalue::Ref(tcx.types.re_erased,
                             BorrowKind::Mut { allow_two_phase_borrow: false },
                             self.place.clone())
@@ -533,7 +533,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 kind: TerminatorKind::Call {
                     func: Operand::function_handle(tcx, drop_fn.def_id, substs,
                                                    self.source_info.span),
-                    args: vec![Operand::Move(Place::Local(ref_place))],
+                    args: vec![Operand::Move(Place::Base(PlaceBase::Local(ref_place)))],
                     destination: Some((unit_temp, succ)),
                     cleanup: unwind.into_option(),
                     from_hir_call: true,
@@ -578,8 +578,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             ty: ety,
             mutbl: hir::Mutability::MutMutable
         });
-        let ptr = &Place::Local(self.new_temp(ref_ty));
-        let can_go = &Place::Local(self.new_temp(tcx.types.bool));
+        let ptr = &Place::Base(PlaceBase::Local(self.new_temp(ref_ty)));
+        let can_go = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
 
         let one = self.constant_usize(1);
         let (ptr_next, cur_next) = if ptr_based {
@@ -587,23 +587,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 tcx.types.re_erased,
                 BorrowKind::Mut { allow_two_phase_borrow: false },
                 Place::Projection(Box::new(Projection {
-                    base: Place::Local(cur),
+                    base: Place::Base(PlaceBase::Local(cur)),
                     elem: ProjectionElem::Deref,
                 }))
              ),
-             Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Local(cur)), one))
+             Rvalue::BinaryOp(BinOp::Offset, copy(&Place::Base(PlaceBase::Local(cur))), one))
         } else {
             (Rvalue::Ref(
                  tcx.types.re_erased,
                  BorrowKind::Mut { allow_two_phase_borrow: false },
                  self.place.clone().index(cur)),
-             Rvalue::BinaryOp(BinOp::Add, copy(&Place::Local(cur)), one))
+             Rvalue::BinaryOp(BinOp::Add, copy(&Place::Base(PlaceBase::Local(cur))), one))
         };
 
         let drop_block = BasicBlockData {
             statements: vec![
                 self.assign(ptr, ptr_next),
-                self.assign(&Place::Local(cur), cur_next)
+                self.assign(&Place::Base(PlaceBase::Local(cur)), cur_next)
             ],
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
@@ -617,7 +617,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         let loop_block = BasicBlockData {
             statements: vec![
                 self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq,
-                                                     copy(&Place::Local(cur)),
+                                                     copy(&Place::Base(PlaceBase::Local(cur))),
                                                      copy(length_or_end)))
             ],
             is_cleanup: unwind.is_cleanup(),
@@ -667,8 +667,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
 
         let move_ = |place: &Place<'tcx>| Operand::Move(place.clone());
         let tcx = self.tcx();
-        let size = &Place::Local(self.new_temp(tcx.types.usize));
-        let size_is_zero = &Place::Local(self.new_temp(tcx.types.bool));
+        let size = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
+        let size_is_zero = &Place::Base(PlaceBase::Local(self.new_temp(tcx.types.bool)));
         let base_block = BasicBlockData {
             statements: vec![
                 self.assign(size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
@@ -703,9 +703,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         };
 
         let cur = self.new_temp(iter_ty);
-        let length = Place::Local(self.new_temp(tcx.types.usize));
+        let length = Place::Base(PlaceBase::Local(self.new_temp(tcx.types.usize)));
         let length_or_end = if ptr_based {
-            Place::Local(self.new_temp(iter_ty))
+            // FIXME check if we want to make it return a `Place` directly
+            // if all use sites want a `Place::Base` anyway.
+            let temp = self.new_temp(iter_ty);
+            Place::Base(PlaceBase::Local(temp))
         } else {
             length.clone()
         };
@@ -728,13 +731,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             unwind,
             ptr_based);
 
-        let cur = Place::Local(cur);
+        let cur = Place::Base(PlaceBase::Local(cur));
         let zero = self.constant_usize(0);
         let mut drop_block_stmts = vec![];
         drop_block_stmts.push(self.assign(&length, Rvalue::Len(self.place.clone())));
         if ptr_based {
             let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
-            let tmp = Place::Local(self.new_temp(tmp_ty));
+            let tmp = Place::Base(PlaceBase::Local(self.new_temp(tmp_ty)));
             // tmp = &mut P;
             // cur = tmp as *mut T;
             // end = Offset(cur, len);
@@ -883,7 +886,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         unwind: Unwind
     ) -> BasicBlock {
         let tcx = self.tcx();
-        let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
+        let unit_temp = Place::Base(PlaceBase::Local(self.new_temp(tcx.mk_unit())));
         let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
         let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| {
             let field = Field::new(i);
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index e93b96c12161c..5d495fc04588b 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -134,7 +134,11 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         if i > 0 {
             write!(w, ", ")?;
         }
-        write!(w, "{:?}: {}", Place::Local(arg), escape(&mir.local_decls[arg].ty))?;
+        write!(w,
+               "{:?}: {}",
+               Place::Base(PlaceBase::Local(arg)),
+               escape(&mir.local_decls[arg].ty)
+        )?;
     }
 
     write!(w, ") -&gt; {}", escape(mir.return_ty()))?;
@@ -150,10 +154,10 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
         if let Some(name) = decl.name {
             write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
-                   Place::Local(local), escape(&decl.ty), name)?;
+                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty), name)?;
         } else {
             write!(w, r#"let mut {:?}: {};<br align="left"/>"#,
-                   Place::Local(local), escape(&decl.ty))?;
+                   Place::Base(PlaceBase::Local(local)), escape(&decl.ty))?;
         }
     }
 
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 8177de50776d6..c3fbee3a2a6e5 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -625,7 +625,7 @@ fn write_mir_sig(
             if i != 0 {
                 write!(w, ", ")?;
             }
-            write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
+            write!(w, "{:?}: {}", Place::Base(PlaceBase::Local(arg)), mir.local_decls[arg].ty)?;
         }
 
         write!(w, ") -> {}", mir.return_ty())?;
diff --git a/src/test/debuginfo/empty-string.rs b/src/test/debuginfo/empty-string.rs
new file mode 100644
index 0000000000000..46df427cf829b
--- /dev/null
+++ b/src/test/debuginfo/empty-string.rs
@@ -0,0 +1,34 @@
+// ignore-windows failing on win32 bot
+// compile-flags:-g
+// min-gdb-version: 7.7
+// min-lldb-version: 310
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print empty_string
+// gdb-check:$1 = ""
+
+// gdb-command: print empty_str
+// gdb-check:$2 = ""
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command: run
+
+// lldb-command: fr v empty_string
+// lldb-check:[...]empty_string = ""
+
+// lldb-command: fr v empty_str
+// lldb-check:[...]empty_str = ""
+
+fn main() {
+    let empty_string = String::new();
+
+    let empty_str = "";
+
+    zzz(); // #break
+}
+
+fn zzz() {}
diff --git a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
index 1a9bd9e66dbac..d25a5ea374627 100644
--- a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
@@ -13,7 +13,11 @@ use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
 use rustc_plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
-declare_tool_lint!(pub clippy::TEST_GROUP, Warn, "Warn about other stuff");
+declare_tool_lint!(
+    /// Some docs
+    pub clippy::TEST_GROUP,
+    Warn, "Warn about other stuff"
+);
 
 struct Pass;