about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2019-03-28 18:00:17 -0700
committerTyler Mandry <tmandry@gmail.com>2019-04-02 12:02:17 -0700
commitac29ca75e025a101000596f2c68318d86098cf92 (patch)
treefcc94f104e5d4f8d0517be4c6cb6888ff4137d93
parentf694222887cf31f51e68927716c25736e62f037f (diff)
downloadrust-ac29ca75e025a101000596f2c68318d86098cf92.tar.gz
rust-ac29ca75e025a101000596f2c68318d86098cf92.zip
Replace adt_def with name in mir::ProjectionElem::Downcast
-rw-r--r--src/librustc/mir/mod.rs69
-rw-r--r--src/librustc/mir/tcx.rs5
-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_mir/borrow_check/error_reporting.rs41
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs27
-rw-r--r--src/librustc_mir/build/matches/mod.rs6
-rw-r--r--src/librustc_mir/build/matches/test.rs3
-rw-r--r--src/librustc_mir/dataflow/move_paths/abs_domain.rs7
-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/util/elaborate_drops.rs4
15 files changed, 124 insertions, 98 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 7b419e306db..d051b424d9a 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..c464d64e336 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -86,7 +86,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
@@ -124,12 +124,11 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
                     }
                 }
             }
-            ProjectionElem::Downcast(adt_def1, index) =>
+            ProjectionElem::Downcast(_name, 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 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 54e5bfc4397..213d24cb709 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_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 95701204cab..cfcbcfc2a21 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;
@@ -1765,20 +1766,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).to_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 { .. }
@@ -1790,24 +1793,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
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 3b559b28f12..d3941f3013c 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -667,8 +667,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                     _ => 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!(
@@ -687,14 +687,19 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                         }
                     }
                 }
-                _ => 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::Ty { ty }
                 },
             },
             ProjectionElem::Field(field, fty) => {
@@ -1161,7 +1166,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<()> {
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index be3d730c61a..eab131d780c 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -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);
@@ -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/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/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/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 37b38338ab9..ad561bcce7d 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -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,