about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-04-03 04:36:12 +0200
committerGitHub <noreply@github.com>2019-04-03 04:36:12 +0200
commita96e3883c130972ac01348df2a912dc97843939d (patch)
tree797ec7fc780c449cac492f1c782b274f7c8b02a1
parent9898182b478d0c6ad560627260d61c82a56c0f75 (diff)
parent4122d2221ec65232bc211a266d0796a4713e0d39 (diff)
downloadrust-a96e3883c130972ac01348df2a912dc97843939d.tar.gz
rust-a96e3883c130972ac01348df2a912dc97843939d.zip
Rollup merge of #59514 - tmandry:remove-adt-def-from-projection-elem, r=eddyb
Remove adt_def from projections and downcasts in MIR

As part of optimizing generator layouts in MIR, we'd like to allow downcasting generators to variants which do not have a corresponding `def_id`, since they are created by the compiler.

This refactor hopes to allow that, without regressing perf.

r? @eddyb
-rw-r--r--src/librustc/mir/mod.rs69
-rw-r--r--src/librustc/mir/tcx.rs119
-rw-r--r--src/librustc/mir/visit.rs10
-rw-r--r--src/librustc/ty/context.rs32
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs6
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs6
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs54
-rw-r--r--src/librustc_mir/borrow_check/mod.rs9
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs8
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs10
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs122
-rw-r--r--src/librustc_mir/borrow_check/place_ext.rs2
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs4
-rw-r--r--src/librustc_mir/borrow_check/prefixes.rs2
-rw-r--r--src/librustc_mir/build/block.rs2
-rw-r--r--src/librustc_mir/build/matches/mod.rs12
-rw-r--r--src/librustc_mir/build/matches/test.rs3
-rw-r--r--src/librustc_mir/build/misc.rs2
-rw-r--r--src/librustc_mir/dataflow/drop_flag_effects.rs4
-rw-r--r--src/librustc_mir/dataflow/move_paths/abs_domain.rs7
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs4
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs8
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs4
-rw-r--r--src/librustc_mir/interpret/place.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs3
-rw-r--r--src/librustc_mir/transform/add_moves_for_packed_drops.rs2
-rw-r--r--src/librustc_mir/transform/add_retag.rs2
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs6
-rw-r--r--src/librustc_mir/transform/const_prop.rs2
-rw-r--r--src/librustc_mir/transform/inline.rs5
-rw-r--r--src/librustc_mir/transform/instcombine.rs4
-rw-r--r--src/librustc_mir/transform/lower_128bit.rs2
-rw-r--r--src/librustc_mir/transform/promote_consts.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs18
-rw-r--r--src/librustc_mir/transform/uniform_array_move_out.rs4
-rw-r--r--src/librustc_mir/util/alignment.rs4
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs6
40 files changed, 277 insertions, 290 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index a7ab0d6cb04..a72161084f3 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -25,7 +25,7 @@ use std::slice;
 use std::vec::IntoIter;
 use std::{iter, mem, option, u32};
 use syntax::ast::{self, Name};
-use syntax::symbol::InternedString;
+use syntax::symbol::{InternedString, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::subst::{Subst, SubstsRef};
@@ -772,7 +772,7 @@ pub struct LocalDecl<'tcx> {
     /// e.g., via `let x: T`, then we carry that type here. The MIR
     /// borrow checker needs this information since it can affect
     /// region inference.
-    pub user_ty: UserTypeProjections<'tcx>,
+    pub user_ty: UserTypeProjections,
 
     /// Name of the local, used in debuginfo and pretty-printing.
     ///
@@ -1805,7 +1805,7 @@ pub enum StatementKind<'tcx> {
     /// - `Contravariant` -- requires that `T_y :> T`
     /// - `Invariant` -- requires that `T_y == T`
     /// - `Bivariant` -- no effect
-    AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection<'tcx>>),
+    AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection>),
 
     /// No-op. Useful for deleting instructions without affecting statement indices.
     Nop,
@@ -1939,14 +1939,14 @@ impl_stable_hash_for!(struct Static<'tcx> {
 /// `PlaceProjection` etc below.
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
          Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Projection<'tcx, B, V, T> {
+pub struct Projection<B, V, T> {
     pub base: B,
-    pub elem: ProjectionElem<'tcx, V, T>,
+    pub elem: ProjectionElem<V, T>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
          Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub enum ProjectionElem<'tcx, V, T> {
+pub enum ProjectionElem<V, T> {
     Deref,
     Field(Field, T),
     Index(V),
@@ -1980,16 +1980,18 @@ pub enum ProjectionElem<'tcx, V, T> {
     /// "Downcast" to a variant of an ADT. Currently, we only introduce
     /// this for ADTs with more than one variant. It may be better to
     /// just introduce it always, or always for enums.
-    Downcast(&'tcx AdtDef, VariantIdx),
+    ///
+    /// The included Symbol is the name of the variant, used for printing MIR.
+    Downcast(Option<Symbol>, VariantIdx),
 }
 
 /// Alias for projections as they appear in places, where the base is a place
 /// and the index is a local.
-pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
+pub type PlaceProjection<'tcx> = Projection<Place<'tcx>, Local, Ty<'tcx>>;
 
 /// Alias for projections as they appear in places, where the base is a place
 /// and the index is a local.
-pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
+pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 
 // at least on 64 bit systems, `PlaceElem` should not be larger than two pointers
 static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
@@ -1998,7 +2000,7 @@ static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
 
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
-pub type ProjectionKind<'tcx> = ProjectionElem<'tcx, (), ()>;
+pub type ProjectionKind = ProjectionElem<(), ()>;
 
 newtype_index! {
     pub struct Field {
@@ -2019,7 +2021,9 @@ impl<'tcx> Place<'tcx> {
     }
 
     pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
-        self.elem(ProjectionElem::Downcast(adt_def, variant_index))
+        self.elem(ProjectionElem::Downcast(
+            Some(adt_def.variants[variant_index].ident.name),
+            variant_index))
     }
 
     pub fn index(self, index: Local) -> Place<'tcx> {
@@ -2080,8 +2084,11 @@ impl<'tcx> Debug for Place<'tcx> {
                 )
             },
             Projection(ref data) => match data.elem {
-                ProjectionElem::Downcast(ref adt_def, index) => {
-                    write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
+                ProjectionElem::Downcast(Some(name), _index) => {
+                    write!(fmt, "({:?} as {})", data.base, name)
+                }
+                ProjectionElem::Downcast(None, index) => {
+                    write!(fmt, "({:?} as variant#{:?})", data.base, index)
                 }
                 ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base),
                 ProjectionElem::Field(field, ty) => {
@@ -2542,36 +2549,36 @@ pub struct Constant<'tcx> {
 /// inferred region `'1`). The second will lead to the constraint `w:
 /// &'static str`.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UserTypeProjections<'tcx> {
-    pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>,
+pub struct UserTypeProjections {
+    pub(crate) contents: Vec<(UserTypeProjection, Span)>,
 }
 
 BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections<'tcx> {
+    impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections {
         contents
     }
 }
 
-impl<'tcx> UserTypeProjections<'tcx> {
+impl<'tcx> UserTypeProjections {
     pub fn none() -> Self {
         UserTypeProjections { contents: vec![] }
     }
 
-    pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection<'tcx>, Span)>) -> Self {
+    pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection, Span)>) -> Self {
         UserTypeProjections { contents: projs.collect() }
     }
 
-    pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection<'tcx>, Span)> {
+    pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection, Span)> {
         self.contents.iter()
     }
 
-    pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
+    pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection> {
         self.contents.iter().map(|&(ref user_type, _span)| user_type)
     }
 
     pub fn push_projection(
         mut self,
-        user_ty: &UserTypeProjection<'tcx>,
+        user_ty: &UserTypeProjection,
         span: Span,
     ) -> Self {
         self.contents.push((user_ty.clone(), span));
@@ -2580,7 +2587,7 @@ impl<'tcx> UserTypeProjections<'tcx> {
 
     fn map_projections(
         mut self,
-        mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx>
+        mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection
     ) -> Self {
         self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
         self
@@ -2628,14 +2635,14 @@ impl<'tcx> UserTypeProjections<'tcx> {
 ///   `field[0]` (aka `.0`), indicating that the type of `s` is
 ///   determined by finding the type of the `.0` field from `T`.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UserTypeProjection<'tcx> {
+pub struct UserTypeProjection {
     pub base: UserTypeAnnotationIndex,
-    pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
+    pub projs: Vec<ProjectionElem<(), ()>>,
 }
 
-impl<'tcx> Copy for ProjectionKind<'tcx> { }
+impl Copy for ProjectionKind { }
 
-impl<'tcx> UserTypeProjection<'tcx> {
+impl UserTypeProjection {
     pub(crate) fn index(mut self) -> Self {
         self.projs.push(ProjectionElem::Index(()));
         self
@@ -2662,15 +2669,17 @@ impl<'tcx> UserTypeProjection<'tcx> {
         variant_index: VariantIdx,
         field: Field,
     ) -> Self {
-        self.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
+        self.projs.push(ProjectionElem::Downcast(
+            Some(adt_def.variants[variant_index].ident.name),
+            variant_index));
         self.projs.push(ProjectionElem::Field(field, ()));
         self
     }
 }
 
-CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, }
+CloneTypeFoldableAndLiftImpls! { ProjectionKind, }
 
-impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         use crate::mir::ProjectionElem::*;
 
@@ -3428,7 +3437,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
     }
 }
 
-impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T>
+impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<B, V, T>
 where
     B: TypeFoldable<'tcx>,
     V: TypeFoldable<'tcx>,
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index ac42eacacd7..0eb37f0ac9e 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -4,21 +4,17 @@
  */
 
 use crate::mir::*;
-use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::{self, AdtDef, Ty, TyCtxt};
+use crate::ty::subst::Subst;
+use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::layout::VariantIdx;
 use crate::hir;
 use crate::ty::util::IntTypeExt;
 
 #[derive(Copy, Clone, Debug)]
-pub enum PlaceTy<'tcx> {
-    /// Normal type.
-    Ty { ty: Ty<'tcx> },
-
-    /// Downcast to a particular variant of an enum.
-    Downcast { adt_def: &'tcx AdtDef,
-               substs: SubstsRef<'tcx>,
-               variant_index: VariantIdx },
+pub struct PlaceTy<'tcx> {
+    pub ty: Ty<'tcx>,
+    /// Downcast to a particular variant of an enum, if included.
+    pub variant_index: Option<VariantIdx>,
 }
 
 static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
@@ -27,16 +23,7 @@ static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
 
 impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
-        PlaceTy::Ty { ty }
-    }
-
-    pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        match *self {
-            PlaceTy::Ty { ty } =>
-                ty,
-            PlaceTy::Downcast { adt_def, substs, variant_index: _ } =>
-                tcx.mk_adt(adt_def, substs),
-        }
+        PlaceTy { ty, variant_index: None }
     }
 
     /// `place_ty.field_ty(tcx, f)` computes the type at a given field
@@ -48,21 +35,20 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     /// Note that the resulting type has not been normalized.
     pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
     {
-        // Pass `0` here so it can be used as a "default" variant_index in first arm below
-        let answer = match (self, VariantIdx::new(0)) {
-            (PlaceTy::Ty {
-                ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
-            (PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
-                let variant_def = &adt_def.variants[variant_index];
+        let answer = match self.ty.sty {
+            ty::TyKind::Adt(adt_def, substs) => {
+                let variant_def = match self.variant_index {
+                    None => adt_def.non_enum_variant(),
+                    Some(variant_index) => {
+                        assert!(adt_def.is_enum());
+                        &adt_def.variants[variant_index]
+                    }
+                };
                 let field_def = &variant_def.fields[f.index()];
                 field_def.ty(tcx, substs)
             }
-            (PlaceTy::Ty { ty }, _) => {
-                match ty.sty {
-                    ty::Tuple(ref tys) => tys[f.index()],
-                    _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
-                }
-            }
+            ty::Tuple(ref tys) => tys[f.index()],
+            _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
         };
         debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
         answer
@@ -86,7 +72,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn projection_ty_core<V, T>(
         self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        elem: &ProjectionElem<'tcx, V, T>,
+        elem: &ProjectionElem<V, T>,
         mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
         -> PlaceTy<'tcx>
     where
@@ -94,62 +80,43 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     {
         let answer = match *elem {
             ProjectionElem::Deref => {
-                let ty = self.to_ty(tcx)
+                let ty = self.ty
                              .builtin_deref(true)
                              .unwrap_or_else(|| {
                                  bug!("deref projection of non-dereferencable ty {:?}", self)
                              })
                              .ty;
-                PlaceTy::Ty {
-                    ty,
-                }
+                PlaceTy::from_ty(ty)
             }
             ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
-                PlaceTy::Ty {
-                    ty: self.to_ty(tcx).builtin_index().unwrap()
-                },
+                PlaceTy::from_ty(self.ty.builtin_index().unwrap()),
             ProjectionElem::Subslice { from, to } => {
-                let ty = self.to_ty(tcx);
-                PlaceTy::Ty {
-                    ty: match ty.sty {
-                        ty::Array(inner, size) => {
-                            let size = size.unwrap_usize(tcx);
-                            let len = size - (from as u64) - (to as u64);
-                            tcx.mk_array(inner, len)
-                        }
-                        ty::Slice(..) => ty,
-                        _ => {
-                            bug!("cannot subslice non-array type: `{:?}`", self)
-                        }
-                    }
-                }
-            }
-            ProjectionElem::Downcast(adt_def1, index) =>
-                match self.to_ty(tcx).sty {
-                    ty::Adt(adt_def, substs) => {
-                        assert!(adt_def.is_enum());
-                        assert!(index.as_usize() < adt_def.variants.len());
-                        assert_eq!(adt_def, adt_def1);
-                        PlaceTy::Downcast { adt_def,
-                                            substs,
-                                            variant_index: index }
+                PlaceTy::from_ty(match self.ty.sty {
+                    ty::Array(inner, size) => {
+                        let size = size.unwrap_usize(tcx);
+                        let len = size - (from as u64) - (to as u64);
+                        tcx.mk_array(inner, len)
                     }
+                    ty::Slice(..) => self.ty,
                     _ => {
-                        bug!("cannot downcast non-ADT type: `{:?}`", self)
+                        bug!("cannot subslice non-array type: `{:?}`", self)
                     }
-                },
+                })
+            }
+            ProjectionElem::Downcast(_name, index) =>
+                PlaceTy { ty: self.ty, variant_index: Some(index) },
             ProjectionElem::Field(ref f, ref fty) =>
-                PlaceTy::Ty { ty: handle_field(&self, f, fty) },
+                PlaceTy::from_ty(handle_field(&self, f, fty)),
         };
         debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
         answer
     }
 }
 
-EnumTypeFoldableImpl! {
+BraceStructTypeFoldableImpl! {
     impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> {
-        (PlaceTy::Ty) { ty },
-        (PlaceTy::Downcast) { adt_def, substs, variant_index },
+        ty,
+        variant_index,
     }
 }
 
@@ -159,9 +126,9 @@ impl<'tcx> Place<'tcx> {
     {
         match *self {
             Place::Base(PlaceBase::Local(index)) =>
-                PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
+                PlaceTy::from_ty(local_decls.local_decls()[index].ty),
             Place::Base(PlaceBase::Static(ref data)) =>
-                PlaceTy::Ty { ty: data.ty },
+                PlaceTy::from_ty(data.ty),
             Place::Projection(ref proj) =>
                 proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem),
         }
@@ -186,7 +153,7 @@ impl<'tcx> Place<'tcx> {
         match place {
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Field(field, _ty) => {
-                    let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx);
+                    let base_ty = proj.base.ty(mir, *tcx).ty;
 
                     if (base_ty.is_closure() || base_ty.is_generator()) &&
                         (!by_ref || mir.upvar_decls[field.index()].by_ref)
@@ -218,7 +185,7 @@ impl<'tcx> Rvalue<'tcx> {
                 tcx.mk_array(operand.ty(local_decls, tcx), count)
             }
             Rvalue::Ref(reg, bk, ref place) => {
-                let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
+                let place_ty = place.ty(local_decls, tcx).ty;
                 tcx.mk_ref(reg,
                     ty::TypeAndMut {
                         ty: place_ty,
@@ -244,7 +211,7 @@ impl<'tcx> Rvalue<'tcx> {
                 operand.ty(local_decls, tcx)
             }
             Rvalue::Discriminant(ref place) => {
-                let ty = place.ty(local_decls, tcx).to_ty(tcx);
+                let ty = place.ty(local_decls, tcx).ty;
                 if let ty::Adt(adt_def, _) = ty.sty {
                     adt_def.repr.discr_type().to_ty(tcx)
                 } else {
@@ -293,7 +260,7 @@ impl<'tcx> Operand<'tcx> {
     {
         match self {
             &Operand::Copy(ref l) |
-            &Operand::Move(ref l) => l.ty(local_decls, tcx).to_ty(tcx),
+            &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
             &Operand::Constant(ref c) => c.ty,
         }
     }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 4d44dc197cb..e41f1e3a91f 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -137,7 +137,7 @@ macro_rules! make_mir_visitor {
             fn visit_ascribe_user_ty(&mut self,
                                      place: & $($mutability)? Place<'tcx>,
                                      variance: & $($mutability)? ty::Variance,
-                                     user_ty: & $($mutability)? UserTypeProjection<'tcx>,
+                                     user_ty: & $($mutability)? UserTypeProjection,
                                      location: Location) {
                 self.super_ascribe_user_ty(place, variance, user_ty, location);
             }
@@ -205,7 +205,7 @@ macro_rules! make_mir_visitor {
 
             fn visit_user_type_projection(
                 &mut self,
-                ty: & $($mutability)? UserTypeProjection<'tcx>,
+                ty: & $($mutability)? UserTypeProjection,
             ) {
                 self.super_user_type_projection(ty);
             }
@@ -700,7 +700,7 @@ macro_rules! make_mir_visitor {
             fn super_ascribe_user_ty(&mut self,
                                      place: & $($mutability)? Place<'tcx>,
                                      _variance: & $($mutability)? ty::Variance,
-                                     user_ty: & $($mutability)? UserTypeProjection<'tcx>,
+                                     user_ty: & $($mutability)? UserTypeProjection,
                                      location: Location) {
                 self.visit_place(
                     place,
@@ -777,7 +777,7 @@ macro_rules! make_mir_visitor {
                                                     min_length: _,
                                                     from_end: _ } => {
                     }
-                    ProjectionElem::Downcast(_adt_def, _variant_index) => {
+                    ProjectionElem::Downcast(_name, _variant_index) => {
                     }
                 }
             }
@@ -851,7 +851,7 @@ macro_rules! make_mir_visitor {
 
             fn super_user_type_projection(
                 &mut self,
-                _ty: & $($mutability)? UserTypeProjection<'tcx>,
+                _ty: & $($mutability)? UserTypeProjection,
             ) {
             }
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 77330c7a9d1..03936a82c71 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -125,7 +125,7 @@ pub struct CtxtInterners<'tcx> {
     clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
     goal: InternedSet<'tcx, GoalKind<'tcx>>,
     goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
-    projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>,
+    projs: InternedSet<'tcx, List<ProjectionKind>>,
     const_: InternedSet<'tcx, Const<'tcx>>,
 }
 
@@ -1802,7 +1802,7 @@ nop_list_lift!{Ty<'a> => Ty<'tcx>}
 nop_list_lift!{ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
 nop_list_lift!{Predicate<'a> => Predicate<'tcx>}
 nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo}
-nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>}
+nop_list_lift!{ProjectionKind => ProjectionKind}
 
 // this is the impl for `&'a InternalSubsts<'a>`
 nop_list_lift!{Kind<'a> => Kind<'tcx>}
@@ -2261,9 +2261,9 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Kind<'lcx>]> for Interned<'tcx, InternalSubsts<'t
     }
 }
 
-impl<'tcx: 'lcx, 'lcx> Borrow<[ProjectionKind<'lcx>]>
-    for Interned<'tcx, List<ProjectionKind<'tcx>>> {
-    fn borrow<'a>(&'a self) -> &'a [ProjectionKind<'lcx>] {
+impl<'tcx> Borrow<[ProjectionKind]>
+    for Interned<'tcx, List<ProjectionKind>> {
+    fn borrow<'a>(&'a self) -> &'a [ProjectionKind] {
         &self.0[..]
     }
 }
@@ -2391,22 +2391,22 @@ direct_interners!('tcx,
 );
 
 macro_rules! slice_interners {
-    ($($field:ident: $method:ident($ty:ident)),+) => (
+    ($($field:ident: $method:ident($ty:ty)),+) => (
         $(intern_method!( 'tcx, $field: $method(
-            &[$ty<'tcx>],
+            &[$ty],
             |a, v| List::from_arena(a, v),
             Deref::deref,
-            |xs: &[$ty<'_>]| xs.iter().any(keep_local)) -> List<$ty<'tcx>>);)+
-    )
+            |xs: &[$ty]| xs.iter().any(keep_local)) -> List<$ty>);)+
+    );
 }
 
 slice_interners!(
-    existential_predicates: _intern_existential_predicates(ExistentialPredicate),
-    predicates: _intern_predicates(Predicate),
-    type_list: _intern_type_list(Ty),
-    substs: _intern_substs(Kind),
-    clauses: _intern_clauses(Clause),
-    goal_list: _intern_goals(Goal),
+    existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>),
+    predicates: _intern_predicates(Predicate<'tcx>),
+    type_list: _intern_type_list(Ty<'tcx>),
+    substs: _intern_substs(Kind<'tcx>),
+    clauses: _intern_clauses(Clause<'tcx>),
+    goal_list: _intern_goals(Goal<'tcx>),
     projs: _intern_projs(ProjectionKind)
 );
 
@@ -2774,7 +2774,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn intern_projs(self, ps: &[ProjectionKind<'tcx>]) -> &'tcx List<ProjectionKind<'tcx>> {
+    pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
         if ps.len() == 0 {
             List::empty()
         } else {
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 4f1fda3f4e5..262dc300334 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -936,7 +936,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind<'tcx>> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let v = self.iter().map(|t| t.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
         folder.tcx().intern_projs(&v)
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index facae9a9797..8253a167245 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -172,14 +172,14 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                 // ZSTs don't require any actual memory access.
                 let elem_ty = base_ty
                     .projection_ty(cx.tcx(), &proj.elem)
-                    .to_ty(cx.tcx());
+                    .ty;
                 let elem_ty = self.fx.monomorphize(&elem_ty);
                 if cx.layout_of(elem_ty).is_zst() {
                     return;
                 }
 
                 if let mir::ProjectionElem::Field(..) = proj.elem {
-                    let layout = cx.layout_of(base_ty.to_ty(cx.tcx()));
+                    let layout = cx.layout_of(base_ty.ty);
                     if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
                         // Recurse with the same context, instead of `Projection`,
                         // potentially stopping at non-operand projections,
@@ -247,7 +247,7 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
             PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
                 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()));
+                let ty = self.fx.monomorphize(&ty.ty);
 
                 // Only need the place if we're actually dropping it.
                 if self.fx.cx.type_needs_drop(ty) {
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 53e8f7ed88b..65f7e023fa2 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -301,7 +301,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         target: mir::BasicBlock,
         unwind: Option<mir::BasicBlock>,
     ) {
-        let ty = location.ty(self.mir, bx.tcx()).to_ty(bx.tcx());
+        let ty = location.ty(self.mir, bx.tcx()).ty;
         let ty = self.monomorphize(&ty);
         let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);
 
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 9ed7e26729f..2b7b9004753 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -494,8 +494,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     mir::ProjectionElem::Subslice { from, to } => {
                         let mut subslice = cg_base.project_index(bx,
                             bx.cx().const_usize(from as u64));
-                        let projected_ty = PlaceTy::Ty { ty: cg_base.layout.ty }
-                            .projection_ty(tcx, &projection.elem).to_ty(tcx);
+                        let projected_ty = PlaceTy::from_ty(cg_base.layout.ty)
+                            .projection_ty(tcx, &projection.elem).ty;
                         subslice.layout = bx.cx().layout_of(self.monomorphize(&projected_ty));
 
                         if subslice.layout.is_unsized() {
@@ -523,6 +523,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn monomorphized_place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
         let place_ty = place.ty(self.mir, tcx);
-        self.monomorphize(&place_ty.to_ty(tcx))
+        self.monomorphize(&place_ty.ty)
     }
 }
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index a94350f9cde..c04a36fe9c6 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -13,6 +13,7 @@ use rustc::mir::{
     Static, StaticKind, TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, DefIdTree};
+use rustc::ty::layout::VariantIdx;
 use rustc::ty::print::Print;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
@@ -201,7 +202,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 );
             }
 
-            let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+            let ty = used_place.ty(self.mir, self.infcx.tcx).ty;
             let needs_note = match ty.sty {
                 ty::Closure(id, _) => {
                     let tables = self.infcx.tcx.typeck_tables_of(id);
@@ -216,7 +217,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 let mpi = self.move_data.moves[move_out_indices[0]].path;
                 let place = &self.move_data.move_paths[mpi].place;
 
-                let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                let ty = place.ty(self.mir, self.infcx.tcx).ty;
                 let opt_name = self.describe_place_with_options(place, IncludingDowncast(true));
                 let note_msg = match opt_name {
                     Some(ref name) => format!("`{}`", name),
@@ -596,8 +597,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // Define a small closure that we can use to check if the type of a place
         // is a union.
         let is_union = |place: &Place<'tcx>| -> bool {
-            place.ty(self.mir, self.infcx.tcx)
-                .to_ty(self.infcx.tcx)
+            place.ty(self.mir, self.infcx.tcx).ty
                 .ty_adt_def()
                 .map(|adt| adt.is_union())
                 .unwrap_or(false)
@@ -646,7 +646,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                             // Also compute the name of the union type, eg. `Foo` so we
                             // can add a helpful note with it.
-                            let ty = base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                            let ty = base.ty(self.mir, self.infcx.tcx).ty;
 
                             return Some((desc_base, desc_first, desc_second, ty.to_string()));
                         },
@@ -1761,20 +1761,22 @@ 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 {
+    fn describe_field(&self, base: &Place<'tcx>, field: Field) -> String {
         match *base {
             Place::Base(PlaceBase::Local(local)) => {
                 let local = &self.mir.local_decls[local];
-                self.describe_field_from_ty(&local.ty, field)
+                self.describe_field_from_ty(&local.ty, field, None)
             }
             Place::Base(PlaceBase::Static(ref static_)) =>
-                self.describe_field_from_ty(&static_.ty, field),
+                self.describe_field_from_ty(&static_.ty, field, None),
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Deref => self.describe_field(&proj.base, field),
-                ProjectionElem::Downcast(def, variant_index) =>
-                    def.variants[variant_index].fields[field.index()].ident.to_string(),
+                ProjectionElem::Downcast(_, variant_index) => {
+                    let base_ty = base.ty(self.mir, self.infcx.tcx).ty;
+                    self.describe_field_from_ty(&base_ty, field, Some(variant_index))
+                }
                 ProjectionElem::Field(_, field_type) => {
-                    self.describe_field_from_ty(&field_type, field)
+                    self.describe_field_from_ty(&field_type, field, None)
                 }
                 ProjectionElem::Index(..)
                 | ProjectionElem::ConstantIndex { .. }
@@ -1786,24 +1788,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     }
 
     /// End-user visible description of the `field_index`nth field of `ty`
-    fn describe_field_from_ty(&self, ty: &ty::Ty<'_>, field: Field) -> String {
+    fn describe_field_from_ty(
+        &self,
+        ty: &ty::Ty<'_>,
+        field: Field,
+        variant_index: Option<VariantIdx>
+    ) -> String {
         if ty.is_box() {
             // If the type is a box, the field is described from the boxed type
-            self.describe_field_from_ty(&ty.boxed_ty(), field)
+            self.describe_field_from_ty(&ty.boxed_ty(), field, variant_index)
         } else {
             match ty.sty {
-                ty::Adt(def, _) => if def.is_enum() {
-                    field.index().to_string()
-                } else {
-                    def.non_enum_variant().fields[field.index()]
+                ty::Adt(def, _) => {
+                    let variant = if let Some(idx) = variant_index {
+                        assert!(def.is_enum());
+                        &def.variants[idx]
+                    } else {
+                        def.non_enum_variant()
+                    };
+                    variant.fields[field.index()]
                         .ident
                         .to_string()
                 },
                 ty::Tuple(_) => field.index().to_string(),
                 ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
-                    self.describe_field_from_ty(&ty, field)
+                    self.describe_field_from_ty(&ty, field, variant_index)
                 }
-                ty::Array(ty, _) | ty::Slice(ty) => self.describe_field_from_ty(&ty, field),
+                ty::Array(ty, _) | ty::Slice(ty) =>
+                    self.describe_field_from_ty(&ty, field, variant_index),
                 ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
                     // Convert the def-id into a node-id. node-ids are only valid for
                     // the local code in the current crate, so this returns an `Option` in case
@@ -1861,7 +1873,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         StorageDeadOrDrop::LocalStorageDead
                         | StorageDeadOrDrop::BoxedStorageDead => {
                             assert!(
-                                base.ty(self.mir, tcx).to_ty(tcx).is_box(),
+                                base.ty(self.mir, tcx).ty.is_box(),
                                 "Drop of value behind a reference or raw pointer"
                             );
                             StorageDeadOrDrop::BoxedStorageDead
@@ -1869,7 +1881,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                         StorageDeadOrDrop::Destructor(_) => base_access,
                     },
                     ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
-                        let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
+                        let base_ty = base.ty(self.mir, tcx).ty;
                         match base_ty.sty {
                             ty::Adt(def, _) if def.has_dtor(tcx) => {
                                 // Report the outermost adt with a destructor
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 820a990c633..d9764288283 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -616,8 +616,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                 let drop_place_ty = drop_place.ty(self.mir, self.infcx.tcx);
 
                 // Erase the regions.
-                let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty)
-                    .to_ty(self.infcx.tcx);
+                let drop_place_ty = self.infcx.tcx.erase_regions(&drop_place_ty).ty;
 
                 // "Lift" into the gcx -- once regions are erased, this type should be in the
                 // global arenas; this "lift" operation basically just asserts that is true, but
@@ -1641,7 +1640,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             // assigning to `P.f` requires `P` itself
                             // be already initialized
                             let tcx = self.infcx.tcx;
-                            match base.ty(self.mir, tcx).to_ty(tcx).sty {
+                            match base.ty(self.mir, tcx).ty.sty {
                                 ty::Adt(def, _) if def.has_dtor(tcx) => {
                                     self.check_if_path_or_subpath_is_moved(
                                         context, InitializationRequiringAction::Assignment,
@@ -1746,7 +1745,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
-                if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).to_ty(tcx).sty {
+                if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).ty.sty {
                     if def.is_union() {
                         if this.move_data.path_map[mpi].iter().any(|moi| {
                             this.move_data.moves[*moi].source.is_predecessor_of(
@@ -2007,7 +2006,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             Place::Projection(ref proj) => {
                 match proj.elem {
                     ProjectionElem::Deref => {
-                        let base_ty = proj.base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let base_ty = proj.base.ty(self.mir, self.infcx.tcx).ty;
 
                         // Check the kind of deref to decide
                         match base_ty.sty {
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index bd4bf67d0b1..b6e7996586e 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -266,7 +266,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                         // Inspect the type of the content behind the
                         // borrow to provide feedback about why this
                         // was a move rather than a copy.
-                        let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = place.ty(self.mir, self.infcx.tcx).ty;
                         let is_upvar_field_projection =
                             self.prefixes(&original_path, PrefixSet::All)
                             .any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
@@ -530,7 +530,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     // We're only interested in assignments (in particular, where the
                     // assignment came from - was it an `Rc` or `Arc`?).
                     if let StatementKind::Assign(_, box Rvalue::Ref(_, _, source)) = &stmt.kind {
-                        let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = source.ty(self.mir, self.infcx.tcx).ty;
                         let ty = match ty.sty {
                             ty::TyKind::Ref(_, ty, _) => ty,
                             _ => ty,
@@ -555,7 +555,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                             _ => continue,
                         };
 
-                        let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = source.ty(self.mir, self.infcx.tcx).ty;
                         let ty = match ty.sty {
                             ty::TyKind::Ref(_, ty, _) => ty,
                             _ => ty,
@@ -581,7 +581,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
             base,
             elem: ProjectionElem::Deref,
         }) = place {
-            if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
+            if base.ty(self.mir, self.infcx.tcx).ty.is_unsafe_ptr() {
                 return BorrowedContentSource::DerefRawPointer;
             }
         }
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index f351212e9d5..8a55a59b15b 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 elem: ProjectionElem::Field(upvar_index, _),
             }) => {
                 debug_assert!(is_closure_or_generator(
-                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
+                    base.ty(self.mir, self.infcx.tcx).ty
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
@@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     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(
-                        the_place_err.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
+                        the_place_err.ty(self.mir, self.infcx.tcx).ty
                     ));
 
                     reason = if access_place.is_upvar_field_projection(self.mir,
@@ -110,7 +110,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     reason = ", as it is immutable for the pattern guard".to_string();
                 } else {
                     let pointer_type =
-                        if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_region_ptr() {
+                        if base.ty(self.mir, self.infcx.tcx).ty.is_region_ptr() {
                             "`&` reference"
                         } else {
                             "`*const` pointer"
@@ -232,7 +232,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
                 if let Some((span, message)) = annotate_struct_field(
                     self.infcx.tcx,
-                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx),
+                    base.ty(self.mir, self.infcx.tcx).ty,
                     field,
                 ) {
                     err.span_suggestion(
@@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 elem: ProjectionElem::Field(upvar_index, _),
             }) => {
                 debug_assert!(is_closure_or_generator(
-                    base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx)
+                    base.ty(self.mir, self.infcx.tcx).ty
                 ));
 
                 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 375dd6e97f1..bf9cff1e4ae 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -174,7 +174,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         &mut self,
         _place: &Place<'tcx>,
         _variance: &ty::Variance,
-        _user_ty: &UserTypeProjection<'tcx>,
+        _user_ty: &UserTypeProjection,
         _location: Location,
     ) {
     }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 5041a7ffee2..b06ebbdbf34 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -450,9 +450,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
         let place_ty = match place {
-            Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
-                ty: self.mir.local_decls[*index].ty,
-            },
+            Place::Base(PlaceBase::Local(index)) =>
+                PlaceTy::from_ty(self.mir.local_decls[*index].ty),
             Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
                 let sty = self.sanitize_type(place, sty);
                 let check_err =
@@ -493,7 +492,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                         check_err(self, place, ty, sty);
                     }
                 }
-                PlaceTy::Ty { ty: sty }
+                PlaceTy::from_ty(sty)
             }
             Place::Projection(ref proj) => {
                 let base_context = if context.is_mutating_use() {
@@ -502,12 +501,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                     PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
                 };
                 let base_ty = self.sanitize_place(&proj.base, location, base_context);
-                if let PlaceTy::Ty { ty } = base_ty {
-                    if ty.references_error() {
+                if base_ty.variant_index.is_none() {
+                    if base_ty.ty.references_error() {
                         assert!(self.errors_reported);
-                        return PlaceTy::Ty {
-                            ty: self.tcx().types.err,
-                        };
+                        return PlaceTy::from_ty(self.tcx().types.err);
                     }
                 }
                 self.sanitize_projection(base_ty, &proj.elem, place, location)
@@ -517,7 +514,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             let tcx = self.tcx();
             let trait_ref = ty::TraitRef {
                 def_id: tcx.lang_items().copy_trait().unwrap(),
-                substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]),
+                substs: tcx.mk_substs_trait(place_ty.ty, &[]),
             };
 
             // In order to have a Copy operand, the type T of the
@@ -615,40 +612,40 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
         let tcx = self.tcx();
-        let base_ty = base.to_ty(tcx);
+        let base_ty = base.ty;
         match *pi {
             ProjectionElem::Deref => {
                 let deref_ty = base_ty.builtin_deref(true);
-                PlaceTy::Ty {
-                    ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| {
+                PlaceTy::from_ty(
+                    deref_ty.map(|t| t.ty).unwrap_or_else(|| {
                         span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
-                    }),
-                }
+                    })
+                )
             }
             ProjectionElem::Index(i) => {
-                let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).to_ty(tcx);
+                let index_ty = Place::Base(PlaceBase::Local(i)).ty(self.mir, tcx).ty;
                 if index_ty != tcx.types.usize {
-                    PlaceTy::Ty {
-                        ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
-                    }
+                    PlaceTy::from_ty(
+                        span_mirbug_and_err!(self, i, "index by non-usize {:?}", i),
+                    )
                 } else {
-                    PlaceTy::Ty {
-                        ty: base_ty.builtin_index().unwrap_or_else(|| {
+                    PlaceTy::from_ty(
+                        base_ty.builtin_index().unwrap_or_else(|| {
                             span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
                         }),
-                    }
+                    )
                 }
             }
             ProjectionElem::ConstantIndex { .. } => {
                 // consider verifying in-bounds
-                PlaceTy::Ty {
-                    ty: base_ty.builtin_index().unwrap_or_else(|| {
+                PlaceTy::from_ty(
+                    base_ty.builtin_index().unwrap_or_else(|| {
                         span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
                     }),
-                }
+                )
             }
-            ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
-                ty: match base_ty.sty {
+            ProjectionElem::Subslice { from, to } => PlaceTy::from_ty(
+                match base_ty.sty {
                     ty::Array(inner, size) => {
                         let size = size.unwrap_usize(tcx);
                         let min_size = (from as u64) + (to as u64);
@@ -666,35 +663,39 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                     ty::Slice(..) => base_ty,
                     _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
                 },
-            },
-            ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
-                ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => {
+            ),
+            ProjectionElem::Downcast(maybe_name, index) => match base_ty.sty {
+                ty::Adt(adt_def, _substs) if adt_def.is_enum() => {
                     if index.as_usize() >= adt_def.variants.len() {
-                        PlaceTy::Ty {
-                            ty: span_mirbug_and_err!(
+                        PlaceTy::from_ty(
+                            span_mirbug_and_err!(
                                 self,
                                 place,
                                 "cast to variant #{:?} but enum only has {:?}",
                                 index,
                                 adt_def.variants.len()
                             ),
-                        }
+                        )
                     } else {
-                        PlaceTy::Downcast {
-                            adt_def,
-                            substs,
-                            variant_index: index,
+                        PlaceTy {
+                            ty: base_ty,
+                            variant_index: Some(index),
                         }
                     }
                 }
-                _ => PlaceTy::Ty {
-                    ty: span_mirbug_and_err!(
-                        self,
-                        place,
-                        "can't downcast {:?} as {:?}",
-                        base_ty,
-                        adt_def1
-                    ),
+                _ => {
+                    let ty = if let Some(name) = maybe_name {
+                        span_mirbug_and_err!(
+                            self,
+                            place,
+                            "can't downcast {:?} as {:?}",
+                            base_ty,
+                            name
+                        )
+                    } else {
+                        span_mirbug_and_err!(self, place, "can't downcast {:?}", base_ty)
+                    };
+                    PlaceTy::from_ty(ty)
                 },
             },
             ProjectionElem::Field(field, fty) => {
@@ -723,7 +724,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                         field_count
                     ),
                 }
-                PlaceTy::Ty { ty: fty }
+                PlaceTy::from_ty(fty)
             }
         }
     }
@@ -743,12 +744,13 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         let tcx = self.tcx();
 
         let (variant, substs) = match base_ty {
-            PlaceTy::Downcast {
-                adt_def,
-                substs,
-                variant_index,
-            } => (&adt_def.variants[variant_index], substs),
-            PlaceTy::Ty { ty } => match ty.sty {
+            PlaceTy { ty, variant_index: Some(variant_index) } => {
+                match ty.sty {
+                    ty::TyKind::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
+                    _ => bug!("can't have downcast of non-adt type"),
+                }
+            }
+            PlaceTy { ty, variant_index: None } => match ty.sty {
                 ty::Adt(adt_def, substs) if !adt_def.is_enum() =>
                     (&adt_def.variants[VariantIdx::new(0)], substs),
                 ty::Closure(def_id, substs) => {
@@ -1161,7 +1163,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         a: Ty<'tcx>,
         v: ty::Variance,
-        user_ty: &UserTypeProjection<'tcx>,
+        user_ty: &UserTypeProjection,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
@@ -1185,7 +1187,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
                 user_ty.base, annotated_type, user_ty.projs, curr_projected_ty);
 
-        let ty = curr_projected_ty.to_ty(tcx);
+        let ty = curr_projected_ty.ty;
         self.relate_types(a, v, ty, locations, category)?;
 
         Ok(())
@@ -1333,7 +1335,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     _ => ConstraintCategory::Assignment,
                 };
 
-                let place_ty = place.ty(mir, tcx).to_ty(tcx);
+                let place_ty = place.ty(mir, tcx).ty;
                 let rv_ty = rv.ty(mir, tcx);
                 if let Err(terr) =
                     self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
@@ -1385,7 +1387,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 ref place,
                 variant_index,
             } => {
-                let place_type = place.ty(mir, tcx).to_ty(tcx);
+                let place_type = place.ty(mir, tcx).ty;
                 let adt = match place_type.sty {
                     TyKind::Adt(adt, _) if adt.is_enum() => adt,
                     _ => {
@@ -1407,7 +1409,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 };
             }
             StatementKind::AscribeUserType(ref place, variance, box ref projection) => {
-                let place_ty = place.ty(mir, tcx).to_ty(tcx);
+                let place_ty = place.ty(mir, tcx).ty;
                 if let Err(terr) = self.relate_type_and_user_type(
                     place_ty,
                     variance,
@@ -1463,7 +1465,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 target: _,
                 unwind: _,
             } => {
-                let place_ty = location.ty(mir, tcx).to_ty(tcx);
+                let place_ty = location.ty(mir, tcx).ty;
                 let rv_ty = value.ty(mir, tcx);
 
                 let locations = term_location.to_locations();
@@ -1611,7 +1613,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         let tcx = self.tcx();
         match *destination {
             Some((ref dest, _target_block)) => {
-                let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
+                let dest_ty = dest.ty(mir, tcx).ty;
                 let category = match *dest {
                     Place::Base(PlaceBase::Local(RETURN_PLACE)) => {
                         if let Some(BorrowCheckContext {
@@ -2370,7 +2372,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             match *elem {
                 ProjectionElem::Deref => {
                     let tcx = self.infcx.tcx;
-                    let base_ty = base.ty(mir, tcx).to_ty(tcx);
+                    let base_ty = base.ty(mir, tcx).ty;
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs
index 6bc56ab721f..8269b7b95f4 100644
--- a/src/librustc_mir/borrow_check/place_ext.rs
+++ b/src/librustc_mir/borrow_check/place_ext.rs
@@ -63,7 +63,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
                     tcx, mir, locals_state_at_exit),
 
                 ProjectionElem::Deref => {
-                    let ty = proj.base.ty(mir, tcx).to_ty(tcx);
+                    let ty = proj.base.ty(mir, tcx).ty;
                     match ty.sty {
                         // For both derefs of raw pointers and `&T`
                         // references, the original path is `Copy` and
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index 52119d6b19b..fbe8b8485dd 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -191,7 +191,7 @@ fn place_components_conflict<'gcx, 'tcx>(
                     Place::Projection(box Projection { base, elem }) => (base, elem),
                     _ => bug!("place has no base?"),
                 };
-                let base_ty = base.ty(mir, tcx).to_ty(tcx);
+                let base_ty = base.ty(mir, tcx).ty;
 
                 match (elem, &base_ty.sty, access) {
                     (_, _, Shallow(Some(ArtificialField::ArrayLength)))
@@ -427,7 +427,7 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                         debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
                         Overlap::EqualOrDisjoint
                     } else {
-                        let ty = pi1.base.ty(mir, tcx).to_ty(tcx);
+                        let ty = pi1.base.ty(mir, tcx).ty;
                         match ty.sty {
                             ty::Adt(def, _) if def.is_union() => {
                                 // Different fields of a union, we are basically stuck.
diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs
index e70c9e81ebd..866f1cf994e 100644
--- a/src/librustc_mir/borrow_check/prefixes.rs
+++ b/src/librustc_mir/borrow_check/prefixes.rs
@@ -139,7 +139,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for Prefixes<'cx, 'gcx, 'tcx> {
             // derefs, except we stop at the deref of a shared
             // reference.
 
-            let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+            let ty = proj.base.ty(self.mir, self.tcx).ty;
             match ty.sty {
                 ty::RawPtr(_) |
                 ty::Ref(
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index cba5039122a..7469aceee3a 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // Then, the block may have an optional trailing expression which is a “return” value
         // of the block, which is stored into `destination`.
         let tcx = this.hir.tcx();
-        let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
+        let destination_ty = destination.ty(&this.local_decls, tcx).ty;
         if let Some(expr) = expr {
             let tail_result_is_ignored = destination_ty.is_unit() ||
                 this.block_context.currently_ignores_tail_results();
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index be3d730c61a..566f1790f8f 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -374,7 +374,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let ty_source_info = self.source_info(user_ty_span);
                 let user_ty = box pat_ascription_ty.user_ty(
                     &mut self.canonical_user_type_annotations,
-                    place.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+                    place.ty(&self.local_decls, self.hir.tcx()).ty,
                     ty_source_info.span,
                 );
                 self.cfg.push(
@@ -575,7 +575,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub(super) fn visit_bindings(
         &mut self,
         pattern: &Pattern<'tcx>,
-        pattern_user_ty: UserTypeProjections<'tcx>,
+        pattern_user_ty: UserTypeProjections,
         f: &mut impl FnMut(
             &mut Self,
             Mutability,
@@ -584,7 +584,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             HirId,
             Span,
             Ty<'tcx>,
-            UserTypeProjections<'tcx>,
+            UserTypeProjections,
         ),
     ) {
         debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
@@ -1293,7 +1293,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
 
         all_fake_borrows.into_iter().map(|matched_place| {
-            let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).to_ty(tcx);
+            let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
             let fake_borrow_ty = tcx.mk_imm_ref(tcx.types.re_erased, fake_borrow_deref_ty);
             let fake_borrow_temp = self.local_decls.push(
                 LocalDecl::new_temp(fake_borrow_ty, temp_span)
@@ -1587,7 +1587,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
             let user_ty = box ascription.user_ty.clone().user_ty(
                 &mut self.canonical_user_type_annotations,
-                ascription.source.ty(&self.local_decls, self.hir.tcx()).to_ty(self.hir.tcx()),
+                ascription.source.ty(&self.local_decls, self.hir.tcx()).ty,
                 source_info.span
             );
             self.cfg.push(
@@ -1701,7 +1701,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         mode: BindingMode,
         var_id: HirId,
         var_ty: Ty<'tcx>,
-        user_ty: UserTypeProjections<'tcx>,
+        user_ty: UserTypeProjections,
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
         pat_span: Span,
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 0c93984fda8..b0602219610 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -693,7 +693,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
         // we want to create a set of derived match-patterns like
         // `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
-        let elem = ProjectionElem::Downcast(adt_def, variant_index);
+        let elem = ProjectionElem::Downcast(
+            Some(adt_def.variants[variant_index].ident.name), variant_index);
         let downcast_place = match_pair.place.elem(elem); // `(x as Variant)`
         let consequent_match_pairs =
             subpatterns.iter()
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index d76d3765ac7..d71a13dec5a 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -70,7 +70,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
     pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
         let tcx = self.hir.tcx();
-        let ty = place.ty(&self.local_decls, tcx).to_ty(tcx);
+        let ty = place.ty(&self.local_decls, tcx).ty;
         if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {
             Operand::Move(place)
         } else {
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index f78c82a9302..aae4590a387 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -49,7 +49,7 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
 fn place_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                                             mir: &Mir<'tcx>,
                                                             place: &mir::Place<'tcx>) -> bool {
-    let ty = place.ty(mir, tcx).to_ty(tcx);
+    let ty = place.ty(mir, tcx).ty;
     match ty.sty {
         ty::Array(..) => {
             debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false",
@@ -141,7 +141,7 @@ pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
 {
     on_all_children_bits(tcx, mir, &ctxt.move_data, path, |child| {
         let place = &ctxt.move_data.move_paths[path].place;
-        let ty = place.ty(mir, tcx).to_ty(tcx);
+        let ty = place.ty(mir, tcx).ty;
         debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, place, ty);
 
         let gcx = tcx.global_tcx();
diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
index 6dcc0325ec1..b26547c4ff7 100644
--- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs
+++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
@@ -18,8 +18,7 @@ use rustc::ty::Ty;
 pub struct AbstractOperand;
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct AbstractType;
-pub type AbstractElem<'tcx> =
-    ProjectionElem<'tcx, AbstractOperand, AbstractType>;
+pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
 
 pub trait Lift {
     type Abstract;
@@ -38,7 +37,7 @@ impl<'tcx> Lift for Ty<'tcx> {
     fn lift(&self) -> Self::Abstract { AbstractType }
 }
 impl<'tcx> Lift for PlaceElem<'tcx> {
-    type Abstract = AbstractElem<'tcx>;
+    type Abstract = AbstractElem;
     fn lift(&self) -> Self::Abstract {
         match *self {
             ProjectionElem::Deref =>
@@ -56,7 +55,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
                     from_end,
                 },
             ProjectionElem::Downcast(a, u) =>
-                ProjectionElem::Downcast(a.clone(), u.clone()),
+                ProjectionElem::Downcast(a, u.clone()),
         }
     }
 }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 71805fd02b8..20a306a3ef7 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -120,7 +120,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
         let base = self.move_path_for(&proj.base)?;
         let mir = self.builder.mir;
         let tcx = self.builder.tcx;
-        let place_ty = proj.base.ty(mir, tcx).to_ty(tcx);
+        let place_ty = proj.base.ty(mir, tcx).ty;
         match place_ty.sty {
             ty::Ref(..) | ty::RawPtr(..) =>
                 return Err(MoveError::cannot_move_out_of(
@@ -424,7 +424,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
             Place::Projection(box Projection {
                 base,
                 elem: ProjectionElem::Field(_, _),
-            }) if match base.ty(self.builder.mir, self.builder.tcx).to_ty(self.builder.tcx).sty {
+            }) if match base.ty(self.builder.mir, self.builder.tcx).ty.sty {
                     ty::TyKind::Adt(def, _) if def.is_union() => true,
                     _ => false,
             } => base,
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 7eef68e5f80..5806a01c687 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -148,7 +148,7 @@ pub struct MoveData<'tcx> {
     /// particular path being moved.)
     pub loc_map: LocationMap<SmallVec<[MoveOutIndex; 4]>>,
     pub path_map: IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
-    pub rev_lookup: MovePathLookup<'tcx>,
+    pub rev_lookup: MovePathLookup,
     pub inits: IndexVec<InitIndex, Init>,
     /// Each Location `l` is mapped to the Inits that are effects
     /// of executing the code at `l`.
@@ -258,7 +258,7 @@ impl Init {
 
 /// Tables mapping from a place to its MovePathIndex.
 #[derive(Debug)]
-pub struct MovePathLookup<'tcx> {
+pub struct MovePathLookup {
     locals: IndexVec<Local, MovePathIndex>,
 
     /// projections are made from a base-place and a projection
@@ -267,7 +267,7 @@ pub struct MovePathLookup<'tcx> {
     /// subsequent search so that it is solely relative to that
     /// base-place). For the remaining lookup, we map the projection
     /// elem to the associated MovePathIndex.
-    projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
+    projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>
 }
 
 mod builder;
@@ -278,7 +278,7 @@ pub enum LookupResult {
     Parent(Option<MovePathIndex>)
 }
 
-impl<'tcx> MovePathLookup<'tcx> {
+impl MovePathLookup {
     // Unlike the builder `fn move_path_for` below, this lookup
     // alternative will *not* create a MovePath on the fly for an
     // unknown place, but will rather return the nearest available
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 622cf00ed86..fc12443c092 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -74,7 +74,7 @@ impl<'tcx> PatternTypeProjection<'tcx> {
         annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
         inferred_ty: Ty<'tcx>,
         span: Span,
-    ) -> UserTypeProjection<'tcx> {
+    ) -> UserTypeProjection {
         UserTypeProjection {
             base: annotations.push(CanonicalUserTypeAnnotation {
                 span,
@@ -1094,7 +1094,7 @@ CloneImpls!{ <'tcx>
     Span, Field, Mutability, ast::Name, hir::HirId, usize, ty::Const<'tcx>,
     Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
     SubstsRef<'tcx>, &'tcx Kind<'tcx>, UserType<'tcx>,
-    UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
+    UserTypeProjection, PatternTypeProjection<'tcx>
 }
 
 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 4d51772d5ea..4f7b59a5a9a 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -558,7 +558,7 @@ where
     pub fn place_projection(
         &mut self,
         base: PlaceTy<'tcx, M::PointerTag>,
-        proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
+        proj_elem: &mir::ProjectionElem<mir::Local, Ty<'tcx>>,
     ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::ProjectionElem::*;
         Ok(match *proj_elem {
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 45b346b6413..af875c2f9e8 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -625,8 +625,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             }
             mir::TerminatorKind::Drop { ref location, .. } |
             mir::TerminatorKind::DropAndReplace { ref location, .. } => {
-                let ty = location.ty(self.mir, self.tcx)
-                    .to_ty(self.tcx);
+                let ty = location.ty(self.mir, self.tcx).ty;
                 let ty = tcx.subst_and_normalize_erasing_regions(
                     self.param_substs,
                     ty::ParamEnv::reveal_all(),
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 e8528eee0bc..b6436ec70ee 100644
--- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs
+++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs
@@ -106,7 +106,7 @@ fn add_move_for_packed_drop<'a, 'tcx>(
     };
 
     let source_info = terminator.source_info;
-    let ty = location.ty(mir, tcx).to_ty(tcx);
+    let ty = location.ty(mir, tcx).ty;
     let temp = patch.new_temp(ty, terminator.source_info.span);
 
     let storage_dead_block = patch.new_block(BasicBlockData {
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index b13a5fd2fd1..9b9e6594296 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -87,7 +87,7 @@ impl MirPass for AddRetag {
         let needs_retag = |place: &Place<'tcx>| {
             // FIXME: Instead of giving up for unstable places, we should introduce
             // a temporary and retag on that.
-            is_stable(place) && may_have_reference(place.ty(&*local_decls, tcx).to_ty(tcx), tcx)
+            is_stable(place) && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx)
         };
 
         // PART 1
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 0e31515e4af..93f3afe1aea 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -227,7 +227,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 }
                 let is_borrow_of_interior_mut = context.is_borrow() && !base
                     .ty(self.mir, self.tcx)
-                    .to_ty(self.tcx)
+                    .ty
                     .is_freeze(self.tcx, self.param_env, self.source_info.span);
                 // prevent
                 // * `&mut x.field`
@@ -249,7 +249,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                         self.source_info = self.mir.local_decls[local].source_info;
                     }
                 }
-                let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                let base_ty = base.ty(self.mir, self.tcx).ty;
                 match base_ty.sty {
                     ty::RawPtr(..) => {
                         self.require_unsafe("dereference of raw pointer",
@@ -420,7 +420,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         }) = place {
             match *elem {
                 ProjectionElem::Field(..) => {
-                    let ty = base.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
+                    let ty = base.ty(&self.mir.local_decls, self.tcx).ty;
                     match ty.sty {
                         ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) {
                             (Bound::Unbounded, Bound::Unbounded) => {},
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 0d43602d899..e0ff71cbe52 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -556,7 +556,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
         if let StatementKind::Assign(ref place, ref rval) = statement.kind {
             let place_ty: ty::Ty<'tcx> = place
                 .ty(&self.mir.local_decls, self.tcx)
-                .to_ty(self.tcx);
+                .ty;
             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::Base(PlaceBase::Local(local)) = *place {
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 1063381d6aa..027ae70b06a 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -319,8 +319,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     work_list.push(target);
                     // If the location doesn't actually need dropping, treat it like
                     // a regular goto.
-                    let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs);
-                    let ty = ty.to_ty(tcx);
+                    let ty = location.ty(callee_mir, tcx).subst(tcx, callsite.substs).ty;
                     if ty.needs_drop(tcx, param_env) {
                         cost += CALL_PENALTY;
                         if let Some(unwind) = unwind {
@@ -563,7 +562,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             assert!(args.next().is_none());
 
             let tuple = Place::Base(PlaceBase::Local(tuple));
-            let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).to_ty(tcx).sty {
+            let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_mir, tcx).ty.sty {
                 s
             } else {
                 bug!("Closure arguments are not passed as a tuple");
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index e0e64fd1f9b..7e925f65ee2 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -82,14 +82,14 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         if let Rvalue::Ref(_, _, Place::Projection(ref projection)) = *rvalue {
             if let ProjectionElem::Deref = projection.elem {
-                if projection.base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() {
+                if projection.base.ty(self.mir, self.tcx).ty.is_region_ptr() {
                     self.optimizations.and_stars.insert(location);
                 }
             }
         }
 
         if let Rvalue::Len(ref place) = *rvalue {
-            let place_ty = place.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
+            let place_ty = place.ty(&self.mir.local_decls, self.tcx).ty;
             if let TyKind::Array(_, len) = place_ty.sty {
                 let span = self.mir.source_info(location).span;
                 let ty = self.tcx.types.usize;
diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs
index 54fc63f3057..dda9457cc8c 100644
--- a/src/librustc_mir/transform/lower_128bit.rs
+++ b/src/librustc_mir/transform/lower_128bit.rs
@@ -135,7 +135,7 @@ fn check_lang_item_type<'a, 'tcx, D>(
     let sig = poly_sig.no_bound_vars().unwrap();
     let lhs_ty = lhs.ty(local_decls, tcx);
     let rhs_ty = rhs.ty(local_decls, tcx);
-    let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
+    let place_ty = place.ty(local_decls, tcx).ty;
     let expected = [lhs_ty, rhs_ty, place_ty];
     assert_eq!(sig.inputs_and_output[..], expected,
         "lang item `{}`", tcx.def_path_str(did));
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 73b88e9904b..43723aaf568 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -310,7 +310,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                                 place = &mut proj.base;
                             };
 
-                            let ty = place.ty(local_decls, self.tcx).to_ty(self.tcx);
+                            let ty = place.ty(local_decls, self.tcx).ty;
                             let span = statement.source_info.span;
 
                             Operand::Move(mem::replace(place, promoted_place(ty, span)))
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index e533066e6b9..5adcbf84da5 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -168,7 +168,7 @@ trait Qualif {
             cx,
             proj.base.ty(cx.mir, cx.tcx)
                 .projection_ty(cx.tcx, &proj.elem)
-                .to_ty(cx.tcx),
+                .ty,
         );
         match proj.elem {
             ProjectionElem::Deref |
@@ -245,7 +245,7 @@ trait Qualif {
                 // Special-case reborrows to be more like a copy of the reference.
                 if let Place::Projection(ref proj) = *place {
                     if let ProjectionElem::Deref = proj.elem {
-                        let base_ty = proj.base.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
+                        let base_ty = proj.base.ty(cx.mir, cx.tcx).ty;
                         if let ty::Ref(..) = base_ty.sty {
                             return Self::in_place(cx, &proj.base);
                         }
@@ -301,7 +301,7 @@ impl Qualif for HasMutInterior {
             // allowed in constants (and the `Checker` will error), and/or it
             // won't be promoted, due to `&mut ...` or interior mutability.
             Rvalue::Ref(_, kind, ref place) => {
-                let ty = place.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
+                let ty = place.ty(cx.mir, cx.tcx).ty;
 
                 if let BorrowKind::Mut { .. } = kind {
                     // In theory, any zero-sized value could be borrowed
@@ -398,7 +398,7 @@ impl Qualif for IsNotConst {
 
             ProjectionElem::Field(..) => {
                 if cx.mode == Mode::Fn {
-                    let base_ty = proj.base.ty(cx.mir, cx.tcx).to_ty(cx.tcx);
+                    let base_ty = proj.base.ty(cx.mir, cx.tcx).ty;
                     if let Some(def) = base_ty.ty_adt_def() {
                         if def.is_union() {
                             return true;
@@ -988,7 +988,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                             // `not_const` errors out in const contexts
                             self.not_const()
                         }
-                        let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                        let base_ty = proj.base.ty(self.mir, self.tcx).ty;
                         match self.mode {
                             Mode::Fn => {},
                             _ => {
@@ -1012,7 +1012,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                     ProjectionElem::Subslice {..} |
                     ProjectionElem::Field(..) |
                     ProjectionElem::Index(_) => {
-                        let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                        let base_ty = proj.base.ty(self.mir, self.tcx).ty;
                         if let Some(def) = base_ty.ty_adt_def() {
                             if def.is_union() {
                                 match self.mode {
@@ -1069,7 +1069,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
             let mut is_reborrow = false;
             if let Place::Projection(ref proj) = *place {
                 if let ProjectionElem::Deref = proj.elem {
-                    let base_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                    let base_ty = proj.base.ty(self.mir, self.tcx).ty;
                     if let ty::Ref(..) = base_ty.sty {
                         is_reborrow = true;
                     }
@@ -1193,7 +1193,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                 self.assign(dest, ValueSource::Call {
                     callee: func,
                     args,
-                    return_ty: dest.ty(self.mir, self.tcx).to_ty(self.tcx),
+                    return_ty: dest.ty(self.mir, self.tcx).ty,
                 }, location);
             }
 
@@ -1367,7 +1367,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
 
                 if let Some(span) = needs_drop {
                     // Double-check the type being dropped, to minimize false positives.
-                    let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
+                    let ty = place.ty(self.mir, self.tcx).ty;
                     if ty.needs_drop(self.tcx, self.param_env) {
                         struct_span_err!(self.tcx.sess, span, E0493,
                                          "destructors cannot be evaluated at compile-time")
diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs
index b1d898bb5b0..616944dd7ef 100644
--- a/src/librustc_mir/transform/uniform_array_move_out.rs
+++ b/src/librustc_mir/transform/uniform_array_move_out.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
                                                      from_end: false} = proj.elem {
                     // no need to transformation
                 } else {
-                    let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                    let place_ty = proj.base.ty(self.mir, self.tcx).ty;
                     if let ty::Array(item_ty, const_size) = place_ty.sty {
                         if let Some(size) = const_size.assert_usize(self.tcx) {
                             assert!(size <= u32::max_value() as u64,
@@ -195,7 +195,7 @@ impl MirPass for RestoreSubsliceArrayMoveOut {
 
                         let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
                         let opt_size = opt_src_place.and_then(|src_place| {
-                            let src_ty = src_place.ty(mir, tcx).to_ty(tcx);
+                            let src_ty = src_place.ty(mir, tcx).ty;
                             if let ty::Array(_, ref size_o) = src_ty.sty {
                                 size_o.assert_usize(tcx)
                             } else {
diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs
index 7be34d001df..788b7fdaaf9 100644
--- a/src/librustc_mir/util/alignment.rs
+++ b/src/librustc_mir/util/alignment.rs
@@ -17,7 +17,7 @@ pub fn is_disaligned<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return false
     }
 
-    let ty = place.ty(local_decls, tcx).to_ty(tcx);
+    let ty = place.ty(local_decls, tcx).ty;
     match tcx.layout_raw(param_env.and(ty)) {
         Ok(layout) if layout.align.abi.bytes() == 1 => {
             // if the alignment is 1, the type can't be further
@@ -46,7 +46,7 @@ fn is_within_packed<'a, 'tcx, L>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             // encountered a Deref, which is ABI-aligned
             ProjectionElem::Deref => break,
             ProjectionElem::Field(..) => {
-                let ty = base.ty(local_decls, tcx).to_ty(tcx);
+                let ty = base.ty(local_decls, tcx).ty;
                 match ty.sty {
                     ty::Adt(def, _) if def.repr.packed() => {
                         return true
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 37b38338ab9..2d275c9a137 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -122,7 +122,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
     where D: DropElaborator<'b, 'tcx>
 {
     fn place_ty(&self, place: &Place<'tcx>) -> Ty<'tcx> {
-        place.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
+        place.ty(self.elaborator.mir(), self.tcx()).ty
     }
 
     fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
@@ -412,8 +412,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 self.path, variant_index);
             if let Some(variant_path) = subpath {
                 let base_place = self.place.clone().elem(
-                    ProjectionElem::Downcast(adt, variant_index)
-                        );
+                    ProjectionElem::Downcast(Some(adt.variants[variant_index].ident.name),
+                                             variant_index));
                 let fields = self.move_paths_for_fields(
                     &base_place,
                     variant_path,