about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ich/impls_ty.rs15
-rw-r--r--src/librustc/infer/anon_types/mod.rs7
-rw-r--r--src/librustc/traits/select.rs4
-rw-r--r--src/librustc/ty/instance.rs5
-rw-r--r--src/librustc/ty/relate.rs16
-rw-r--r--src/librustc/ty/sty.rs19
-rw-r--r--src/librustc/ty/subst.rs172
-rw-r--r--src/librustc/ty/util.rs28
-rw-r--r--src/librustc_const_eval/_match.rs2
-rw-r--r--src/librustc_driver/test.rs8
-rw-r--r--src/librustc_mir/interpret/eval_context.rs4
-rw-r--r--src/librustc_mir/monomorphize/mod.rs4
-rw-r--r--src/librustc_mir/transform/generator.rs6
-rw-r--r--src/librustc_trans/common.rs5
-rw-r--r--src/librustc_typeck/astconv.rs7
-rw-r--r--src/librustc_typeck/check/dropck.rs9
-rw-r--r--src/librustc_typeck/variance/constraints.rs15
17 files changed, 173 insertions, 153 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index d1e431597e7..71a57dbf32f 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -56,8 +56,19 @@ for ty::subst::Kind<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        self.as_type().hash_stable(hcx, hasher);
-        self.as_region().hash_stable(hcx, hasher);
+        self.unpack().hash_stable(hcx, hasher);
+    }
+}
+
+impl<'gcx> HashStable<StableHashingContext<'gcx>>
+for ty::subst::UnpackedKind<'gcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        match self {
+            ty::subst::UnpackedKind::Lifetime(lt) => lt.hash_stable(hcx, hasher),
+            ty::subst::UnpackedKind::Type(ty) => ty.hash_stable(hcx, hasher),
+        }
     }
 }
 
diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/anon_types/mod.rs
index f5b88dbc2a9..a749d0dddd7 100644
--- a/src/librustc/infer/anon_types/mod.rs
+++ b/src/librustc/infer/anon_types/mod.rs
@@ -17,7 +17,7 @@ use traits::{self, PredicateObligation};
 use ty::{self, Ty};
 use ty::fold::{BottomUpFolder, TypeFoldable};
 use ty::outlives::Component;
-use ty::subst::{Kind, Substs};
+use ty::subst::{Kind, UnpackedKind, Substs};
 use util::nodemap::DefIdMap;
 
 pub type AnonTypeMap<'tcx> = DefIdMap<AnonTypeDecl<'tcx>>;
@@ -321,7 +321,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             let index = region_def.index as usize;
 
             // Get the value supplied for this region from the substs.
-            let subst_arg = anon_defn.substs[index].as_region().unwrap();
+            let subst_arg = anon_defn.substs.region_at(index);
 
             // Compute the least upper bound of it with the other regions.
             debug!("constrain_anon_types: least_region={:?}", least_region);
@@ -466,7 +466,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 // All other regions, we map them appropriately to their adjusted
                 // indices, erroring if we find any lifetimes that were not mapped
                 // into the new set.
-                _ => if let Some(r1) = map.get(&Kind::from(r)).and_then(|k| k.as_region()) {
+                _ => if let Some(UnpackedKind::Lifetime(r1)) = map.get(&r.into())
+                                                                  .map(|k| k.unpack()) {
                     r1
                 } else {
                     // No mapping was found. This means that
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index fca7c3bcb8e..9a3738c163d 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -584,7 +584,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     let trait_ref = &mut trait_pred.trait_ref;
                     let unit_substs = trait_ref.substs;
                     let mut never_substs = Vec::with_capacity(unit_substs.len());
-                    never_substs.push(From::from(tcx.types.never));
+                    never_substs.push(tcx.types.never.into());
                     never_substs.extend(&unit_substs[1..]);
                     trait_ref.substs = tcx.intern_substs(&never_substs);
                 }
@@ -2997,7 +2997,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 // unsized parameters is equal to the target.
                 let params = substs_a.iter().enumerate().map(|(i, &k)| {
                     if ty_params.contains(i) {
-                        Kind::from(substs_b.type_at(i))
+                        substs_b.type_at(i).into()
                     } else {
                         k
                     }
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 63bf52a9bdf..f4b5ffbb7dc 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -355,10 +355,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     let sig = substs.closure_sig(closure_did, tcx);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     assert_eq!(sig.inputs().len(), 1);
-    let substs = tcx.mk_substs([
-                               Kind::from(self_ty),
-                               Kind::from(sig.inputs()[0]),
-    ].iter().cloned());
+    let substs = tcx.mk_substs([Kind::from(self_ty), sig.inputs()[0].into()].iter().cloned());
 
     debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
     Instance { def, substs }
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index a6c72728a51..b9927c7eeb2 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -16,7 +16,7 @@
 use hir::def_id::DefId;
 use middle::const_val::ConstVal;
 use traits::Reveal;
-use ty::subst::{Kind, Substs};
+use ty::subst::{UnpackedKind, Substs};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::{TypeVisitor, TypeFolder};
 use ty::error::{ExpectedFound, TypeError};
@@ -142,12 +142,14 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
 
     let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| {
         let variance = variances.map_or(ty::Invariant, |v| v[i]);
-        if let (Some(a_ty), Some(b_ty)) = (a.as_type(), b.as_type()) {
-            Ok(Kind::from(relation.relate_with_variance(variance, &a_ty, &b_ty)?))
-        } else if let (Some(a_r), Some(b_r)) = (a.as_region(), b.as_region()) {
-            Ok(Kind::from(relation.relate_with_variance(variance, &a_r, &b_r)?))
-        } else {
-            bug!()
+        match (a.unpack(), b.unpack()) {
+            (UnpackedKind::Lifetime(a_lt), UnpackedKind::Lifetime(b_lt)) => {
+                Ok(relation.relate_with_variance(variance, &a_lt, &b_lt)?.into())
+            }
+            (UnpackedKind::Type(a_ty), UnpackedKind::Type(b_ty)) => {
+                Ok(relation.relate_with_variance(variance, &a_ty, &b_ty)?.into())
+            }
+            (UnpackedKind::Lifetime(_), _) | (UnpackedKind::Type(_), _) => bug!()
         }
     });
 
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 503418b044f..a18e8f57836 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -15,10 +15,9 @@ use hir::def_id::DefId;
 use middle::const_val::ConstVal;
 use middle::region;
 use rustc_data_structures::indexed_vec::Idx;
-use ty::subst::{Substs, Subst};
+use ty::subst::{Substs, Subst, Kind, UnpackedKind};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
-use ty::subst::Kind;
 
 use std::iter;
 use std::cmp::Ordering;
@@ -297,8 +296,8 @@ impl<'tcx> ClosureSubsts<'tcx> {
         let generics = tcx.generics_of(def_id);
         let parent_len = generics.parent_count();
         SplitClosureSubsts {
-            closure_kind_ty: self.substs[parent_len].as_type().expect("CK should be a type"),
-            closure_sig_ty: self.substs[parent_len + 1].as_type().expect("CS should be a type"),
+            closure_kind_ty: self.substs.type_at(parent_len),
+            closure_sig_ty: self.substs.type_at(parent_len + 1),
             upvar_kinds: &self.substs[parent_len + 2..],
         }
     }
@@ -308,7 +307,13 @@ impl<'tcx> ClosureSubsts<'tcx> {
         impl Iterator<Item=Ty<'tcx>> + 'tcx
     {
         let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
-        upvar_kinds.iter().map(|t| t.as_type().expect("upvar should be type"))
+        upvar_kinds.iter().map(|t| {
+            if let UnpackedKind::Type(ty) = t.unpack() {
+                ty
+            } else {
+                bug!("upvar should be type")
+            }
+        })
     }
 
     /// Returns the closure kind for this closure; may return a type
@@ -620,7 +625,7 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
         ty::TraitRef {
             def_id: self.def_id,
             substs: tcx.mk_substs(
-                iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned()))
+                iter::once(self_ty.into()).chain(self.substs.iter().cloned()))
         }
     }
 }
@@ -1127,7 +1132,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
             projection_ty: ty::ProjectionTy {
                 item_def_id: self.item_def_id,
                 substs: tcx.mk_substs(
-                iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())),
+                iter::once(self_ty.into()).chain(self.substs.iter().cloned())),
             },
             ty: self.ty,
         }
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 80b113dfdf5..5e3417e98c2 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -18,6 +18,7 @@ use serialize::{self, Encodable, Encoder, Decodable, Decoder};
 use syntax_pos::{Span, DUMMY_SP};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
+use core::intrinsics;
 use core::nonzero::NonZero;
 use std::fmt;
 use std::iter;
@@ -39,15 +40,29 @@ const TAG_MASK: usize = 0b11;
 const TYPE_TAG: usize = 0b00;
 const REGION_TAG: usize = 0b01;
 
-impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
-    fn from(ty: Ty<'tcx>) -> Kind<'tcx> {
-        // Ensure we can use the tag bits.
-        assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0);
+pub enum UnpackedKind<'tcx> {
+    Lifetime(ty::Region<'tcx>),
+    Type(Ty<'tcx>),
+}
+
+impl<'tcx> UnpackedKind<'tcx> {
+    fn pack(self) -> Kind<'tcx> {
+        let (tag, ptr) = match self {
+            UnpackedKind::Lifetime(lt) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(lt) & TAG_MASK, 0);
+                (REGION_TAG, lt as *const _ as usize)
+            }
+            UnpackedKind::Type(ty) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0);
+                (TYPE_TAG, ty as *const _ as usize)
+            }
+        };
 
-        let ptr = ty as *const _ as usize;
         Kind {
             ptr: unsafe {
-                NonZero::new_unchecked(ptr | TYPE_TAG)
+                NonZero::new_unchecked(ptr | tag)
             },
             marker: PhantomData
         }
@@ -56,88 +71,60 @@ impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
 
 impl<'tcx> From<ty::Region<'tcx>> for Kind<'tcx> {
     fn from(r: ty::Region<'tcx>) -> Kind<'tcx> {
-        // Ensure we can use the tag bits.
-        assert_eq!(mem::align_of_val(r) & TAG_MASK, 0);
+        UnpackedKind::Lifetime(r).pack()
+    }
+}
 
-        let ptr = r as *const _ as usize;
-        Kind {
-            ptr: unsafe {
-                NonZero::new_unchecked(ptr | REGION_TAG)
-            },
-            marker: PhantomData
-        }
+impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
+    fn from(ty: Ty<'tcx>) -> Kind<'tcx> {
+        UnpackedKind::Type(ty).pack()
     }
 }
 
 impl<'tcx> Kind<'tcx> {
     #[inline]
-    unsafe fn downcast<T>(self, tag: usize) -> Option<&'tcx T> {
+    pub fn unpack(self) -> UnpackedKind<'tcx> {
         let ptr = self.ptr.get();
-        if ptr & TAG_MASK == tag {
-            Some(&*((ptr & !TAG_MASK) as *const _))
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    pub fn as_type(self) -> Option<Ty<'tcx>> {
-        unsafe {
-            self.downcast(TYPE_TAG)
-        }
-    }
-
-    #[inline]
-    pub fn as_region(self) -> Option<ty::Region<'tcx>> {
         unsafe {
-            self.downcast(REGION_TAG)
+            match ptr & TAG_MASK {
+                REGION_TAG => UnpackedKind::Lifetime(&*((ptr & !TAG_MASK) as *const _)),
+                TYPE_TAG => UnpackedKind::Type(&*((ptr & !TAG_MASK) as *const _)),
+                _ => intrinsics::unreachable()
+            }
         }
     }
 }
 
 impl<'tcx> fmt::Debug for Kind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let Some(ty) = self.as_type() {
-            write!(f, "{:?}", ty)
-        } else if let Some(r) = self.as_region() {
-            write!(f, "{:?}", r)
-        } else {
-            write!(f, "<unknown @ {:p}>", self.ptr.get() as *const ())
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => write!(f, "{:?}", lt),
+            UnpackedKind::Type(ty) => write!(f, "{:?}", ty),
         }
     }
 }
 
 impl<'tcx> fmt::Display for Kind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let Some(ty) = self.as_type() {
-            write!(f, "{}", ty)
-        } else if let Some(r) = self.as_region() {
-            write!(f, "{}", r)
-        } else {
-            // FIXME(RFC 2000): extend this if/else chain when we support const generic.
-            unimplemented!();
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => write!(f, "{}", lt),
+            UnpackedKind::Type(ty) => write!(f, "{}", ty),
         }
     }
 }
 
 impl<'tcx> TypeFoldable<'tcx> for Kind<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        if let Some(ty) = self.as_type() {
-            Kind::from(ty.fold_with(folder))
-        } else if let Some(r) = self.as_region() {
-            Kind::from(r.fold_with(folder))
-        } else {
-            bug!()
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => lt.fold_with(folder).into(),
+            UnpackedKind::Type(ty) => ty.fold_with(folder).into(),
         }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        if let Some(ty) = self.as_type() {
-            ty.visit_with(visitor)
-        } else if let Some(r) = self.as_region() {
-            r.visit_with(visitor)
-        } else {
-            bug!()
+        match self.unpack() {
+            UnpackedKind::Lifetime(lt) => lt.visit_with(visitor),
+            UnpackedKind::Type(ty) => ty.visit_with(visitor),
         }
     }
 }
@@ -145,16 +132,17 @@ impl<'tcx> TypeFoldable<'tcx> for Kind<'tcx> {
 impl<'tcx> Encodable for Kind<'tcx> {
     fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_enum("Kind", |e| {
-            if let Some(ty) = self.as_type() {
-                e.emit_enum_variant("Ty", TYPE_TAG, 1, |e| {
-                    e.emit_enum_variant_arg(0, |e| ty.encode(e))
-                })
-            } else if let Some(r) = self.as_region() {
-                e.emit_enum_variant("Region", REGION_TAG, 1, |e| {
-                    e.emit_enum_variant_arg(0, |e| r.encode(e))
-                })
-            } else {
-                bug!()
+            match self.unpack() {
+                UnpackedKind::Lifetime(lt) => {
+                    e.emit_enum_variant("Region", REGION_TAG, 1, |e| {
+                        e.emit_enum_variant_arg(0, |e| lt.encode(e))
+                    })
+                }
+                UnpackedKind::Type(ty) => {
+                    e.emit_enum_variant("Ty", TYPE_TAG, 1, |e| {
+                        e.emit_enum_variant_arg(0, |e| ty.encode(e))
+                    })
+                }
             }
         })
     }
@@ -247,7 +235,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
             let def = types.next().unwrap();
             let ty = mk_type(def, substs);
             assert_eq!(def.index as usize, substs.len());
-            substs.push(Kind::from(ty));
+            substs.push(ty.into());
         }
 
         for def in &defs.regions {
@@ -269,26 +257,42 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
 
     #[inline]
     pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
-        self.iter().filter_map(|k| k.as_type())
+        self.iter().filter_map(|k| {
+            if let UnpackedKind::Type(ty) = k.unpack() {
+                Some(ty)
+            } else {
+                None
+            }
+        })
     }
 
     #[inline]
     pub fn regions(&'a self) -> impl DoubleEndedIterator<Item=ty::Region<'tcx>> + 'a {
-        self.iter().filter_map(|k| k.as_region())
+        self.iter().filter_map(|k| {
+            if let UnpackedKind::Lifetime(lt) = k.unpack() {
+                Some(lt)
+            } else {
+                None
+            }
+        })
     }
 
     #[inline]
     pub fn type_at(&self, i: usize) -> Ty<'tcx> {
-        self[i].as_type().unwrap_or_else(|| {
+        if let UnpackedKind::Type(ty) = self[i].unpack() {
+            ty
+        } else {
             bug!("expected type for param #{} in {:?}", i, self);
-        })
+        }
     }
 
     #[inline]
     pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
-        self[i].as_region().unwrap_or_else(|| {
+        if let UnpackedKind::Lifetime(lt) = self[i].unpack() {
+            lt
+        } else {
             bug!("expected region for param #{} in {:?}", i, self);
-        })
+        }
     }
 
     #[inline]
@@ -413,13 +417,12 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
         // the specialized routine `ty::replace_late_regions()`.
         match *r {
             ty::ReEarlyBound(data) => {
-                let r = self.substs.get(data.index as usize)
-                            .and_then(|k| k.as_region());
+                let r = self.substs.get(data.index as usize).map(|k| k.unpack());
                 match r {
-                    Some(r) => {
-                        self.shift_region_through_binders(r)
+                    Some(UnpackedKind::Lifetime(lt)) => {
+                        self.shift_region_through_binders(lt)
                     }
-                    None => {
+                    _ => {
                         let span = self.span.unwrap_or(DUMMY_SP);
                         span_bug!(
                             span,
@@ -470,11 +473,10 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
 impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
     fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
         // Look up the type in the substitutions. It really should be in there.
-        let opt_ty = self.substs.get(p.idx as usize)
-                         .and_then(|k| k.as_type());
+        let opt_ty = self.substs.get(p.idx as usize).map(|k| k.unpack());
         let ty = match opt_ty {
-            Some(t) => t,
-            None => {
+            Some(UnpackedKind::Type(ty)) => ty,
+            _ => {
                 let span = self.span.unwrap_or(DUMMY_SP);
                 span_bug!(
                     span,
@@ -600,7 +602,7 @@ impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> {
             ty::TraitRef {
                 def_id: trait_ref.def_id,
                 substs: tcx.mk_substs(
-                    iter::once(Kind::from(self_ty)).chain(trait_ref.substs.iter().cloned()))
+                    iter::once(self_ty.into()).chain(trait_ref.substs.iter().cloned()))
             }
         })
     }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 34f05232adc..110808919e9 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -19,7 +19,7 @@ use middle::const_val::ConstVal;
 use traits::{self, Reveal};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::TypeVisitor;
-use ty::subst::{Subst, Kind};
+use ty::subst::{Subst, UnpackedKind};
 use ty::TypeVariants::*;
 use util::common::ErrorReported;
 use middle::lang_items;
@@ -509,16 +509,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         let result = item_substs.iter().zip(impl_substs.iter())
             .filter(|&(_, &k)| {
-                if let Some(&ty::RegionKind::ReEarlyBound(ref ebr)) = k.as_region() {
-                    !impl_generics.region_param(ebr, self).pure_wrt_drop
-                } else if let Some(&ty::TyS {
-                    sty: ty::TypeVariants::TyParam(ref pt), ..
-                }) = k.as_type() {
-                    !impl_generics.type_param(pt, self).pure_wrt_drop
-                } else {
-                    // not a type or region param - this should be reported
-                    // as an error.
-                    false
+                match k.unpack() {
+                    UnpackedKind::Lifetime(&ty::RegionKind::ReEarlyBound(ref ebr)) => {
+                        !impl_generics.region_param(ebr, self).pure_wrt_drop
+                    }
+                    UnpackedKind::Type(&ty::TyS {
+                        sty: ty::TypeVariants::TyParam(ref pt), ..
+                    }) => {
+                        !impl_generics.type_param(pt, self).pure_wrt_drop
+                    }
+                    UnpackedKind::Lifetime(_) | UnpackedKind::Type(_) => {
+                        // not a type or region param - this should be reported
+                        // as an error.
+                        false
+                    }
                 }
             }).map(|(&item_param, _)| item_param).collect();
         debug!("destructor_constraint({:?}) = {:?}", def.did, result);
@@ -596,7 +600,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             // Objects must be alive in order for their destructor
             // to be called.
             ty::TyDynamic(..) => Ok(ty::DtorckConstraint {
-                outlives: vec![Kind::from(ty)],
+                outlives: vec![ty.into()],
                 dtorck_types: vec![],
             }),
 
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index e30f5cb4f12..54e3418d4f0 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -878,7 +878,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
         ty::TyAdt(adt, substs) => {
             if adt.is_box() {
                 // Use T as the sub pattern type of Box<T>.
-                vec![substs[0].as_type().unwrap()]
+                vec![substs.type_at(0)]
             } else {
                 adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
                     let is_visible = adt.is_enum()
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 306e7e9c16d..35d2205cf33 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -17,7 +17,7 @@ use driver;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
 use rustc::middle::region;
-use rustc::ty::subst::{Kind, Subst};
+use rustc::ty::subst::Subst;
 use rustc::traits::{ObligationCause, Reveal};
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::maps::OnDiskCache;
@@ -468,7 +468,7 @@ fn subst_ty_renumber_bound() {
             env.t_fn(&[t_param], env.t_nil())
         };
 
-        let substs = env.infcx.tcx.intern_substs(&[Kind::from(t_rptr_bound1)]);
+        let substs = env.infcx.tcx.intern_substs(&[t_rptr_bound1.into()]);
         let t_substituted = t_source.subst(env.infcx.tcx, substs);
 
         // t_expected = fn(&'a isize)
@@ -503,7 +503,7 @@ fn subst_ty_renumber_some_bounds() {
             env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil()))
         };
 
-        let substs = env.infcx.tcx.intern_substs(&[Kind::from(t_rptr_bound1)]);
+        let substs = env.infcx.tcx.intern_substs(&[t_rptr_bound1.into()]);
         let t_substituted = t_source.subst(env.infcx.tcx, substs);
 
         // t_expected = (&'a isize, fn(&'a isize))
@@ -565,7 +565,7 @@ fn subst_region_renumber_region() {
             env.t_fn(&[env.t_rptr(re_early)], env.t_nil())
         };
 
-        let substs = env.infcx.tcx.intern_substs(&[Kind::from(re_bound1)]);
+        let substs = env.infcx.tcx.intern_substs(&[re_bound1.into()]);
         let t_substituted = t_source.subst(env.infcx.tcx, substs);
 
         // t_expected = fn(&'a isize)
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 3578164feb7..08c16fed5dd 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -7,7 +7,7 @@ use rustc::middle::const_val::ConstVal;
 use rustc::mir;
 use rustc::traits::Reveal;
 use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
-use rustc::ty::subst::{Subst, Substs, Kind};
+use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax::codemap::{self, DUMMY_SP};
@@ -1663,6 +1663,6 @@ pub fn resolve_drop_in_place<'a, 'tcx>(
     ty: Ty<'tcx>,
 ) -> ty::Instance<'tcx> {
     let def_id = tcx.require_lang_item(::rustc::middle::lang_items::DropInPlaceFnLangItem);
-    let substs = tcx.intern_substs(&[Kind::from(ty)]);
+    let substs = tcx.intern_substs(&[ty.into()]);
     ty::Instance::resolve(tcx, ty::ParamEnv::empty(Reveal::All), def_id, substs).unwrap()
 }
diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs
index 95ebb6c970a..2ca6c76a800 100644
--- a/src/librustc_mir/monomorphize/mod.rs
+++ b/src/librustc_mir/monomorphize/mod.rs
@@ -92,7 +92,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     assert_eq!(sig.inputs().len(), 1);
     let substs = tcx.mk_substs([
         Kind::from(self_ty),
-        Kind::from(sig.inputs()[0]),
+        sig.inputs()[0].into(),
     ].iter().cloned());
 
     debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
@@ -153,7 +153,7 @@ pub fn resolve_drop_in_place<'a, 'tcx>(
     -> ty::Instance<'tcx>
 {
     let def_id = tcx.require_lang_item(DropInPlaceFnLangItem);
-    let substs = tcx.intern_substs(&[Kind::from(ty)]);
+    let substs = tcx.intern_substs(&[ty.into()]);
     Instance::resolve(tcx, ty::ParamEnv::empty(traits::Reveal::All), def_id, substs).unwrap()
 }
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 812665f5fa4..04ebaa031fe 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -65,7 +65,7 @@ use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior};
-use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::subst::Substs;
 use util::dump_mir;
 use util::liveness::{self, LivenessMode};
 use rustc_const_math::ConstInt;
@@ -858,8 +858,8 @@ impl MirPass for StateTransform {
         // Compute GeneratorState<yield_ty, return_ty>
         let state_did = tcx.lang_items().gen_state().unwrap();
         let state_adt_ref = tcx.adt_def(state_did);
-        let state_substs = tcx.mk_substs([Kind::from(yield_ty),
-            Kind::from(mir.return_ty())].iter());
+        let state_substs = tcx.mk_substs([yield_ty.into(),
+            mir.return_ty().into()].iter());
         let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
 
         // We rename RETURN_PLACE which has type mir.return_ty to new_ret_local
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 9e745c3a1f5..37bd225a7d9 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -28,7 +28,6 @@ use value::Value;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{HasDataLayout, LayoutOf};
-use rustc::ty::subst::Kind;
 use rustc::hir;
 
 use libc::{c_uint, c_char};
@@ -413,8 +412,8 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             sig.map_bound(|sig| {
                 let state_did = tcx.lang_items().gen_state().unwrap();
                 let state_adt_ref = tcx.adt_def(state_did);
-                let state_substs = tcx.mk_substs([Kind::from(sig.yield_ty),
-                    Kind::from(sig.return_ty)].iter());
+                let state_substs = tcx.mk_substs([sig.yield_ty.into(),
+                    sig.return_ty.into()].iter());
                 let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
 
                 tcx.mk_fn_sig(iter::once(env_ty),
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 1139ea5fbd3..650e5305198 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -19,7 +19,7 @@ use hir::def::Def;
 use hir::def_id::DefId;
 use middle::resolve_lifetime as rl;
 use namespace::Namespace;
-use rustc::ty::subst::{Kind, Subst, Substs};
+use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
@@ -1136,7 +1136,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
             // Replace all lifetimes with 'static
             for subst in &mut substs {
-                if let Some(_) = subst.as_region() {
+                if let UnpackedKind::Lifetime(_) = subst.unpack() {
                     *subst = Kind::from(&RegionKind::ReStatic);
                 }
             }
@@ -1146,8 +1146,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
         // Fill in our own generics with the resolved lifetimes
         assert_eq!(lifetimes.len(), generics.own_count());
-        substs.extend(lifetimes.iter().map(|lt|
-            Kind::from(self.ast_region_to_region(lt, None))));
+        substs.extend(lifetimes.iter().map(|lt| Kind::from(self.ast_region_to_region(lt, None))));
 
         debug!("impl_trait_ty_to_ty: final substs = {:?}", substs);
 
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 4aed688027f..039669a62e1 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -14,7 +14,7 @@ use hir::def_id::DefId;
 use rustc::infer::{self, InferOk};
 use rustc::infer::outlives::env::OutlivesEnvironment;
 use rustc::middle::region;
-use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::traits::{self, Reveal, ObligationCause};
 use util::common::ErrorReported;
@@ -331,10 +331,9 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
         }
 
         for outlive in outlives {
-            if let Some(r) = outlive.as_region() {
-                rcx.sub_regions(origin(), parent_scope, r);
-            } else if let Some(ty) = outlive.as_type() {
-                rcx.type_must_outlive(origin(), ty, parent_scope);
+            match outlive.unpack() {
+                UnpackedKind::Lifetime(lt) => rcx.sub_regions(origin(), parent_scope, lt),
+                UnpackedKind::Type(ty) => rcx.type_must_outlive(origin(), ty, parent_scope),
             }
         }
     }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index f7e10a4a47d..44ac7a10e82 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -14,7 +14,7 @@
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Substs, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt};
 use syntax::ast;
 use rustc::hir;
@@ -381,12 +381,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
                    variance_decl,
                    variance_i);
-            if let Some(ty) = k.as_type() {
-                self.add_constraints_from_ty(current, ty, variance_i);
-            } else if let Some(r) = k.as_region() {
-                self.add_constraints_from_region(current, r, variance_i);
-            } else {
-                bug!();
+            match k.unpack() {
+                UnpackedKind::Lifetime(lt) => {
+                    self.add_constraints_from_region(current, lt, variance_i)
+                }
+                UnpackedKind::Type(ty) => {
+                    self.add_constraints_from_ty(current, ty, variance_i)
+                }
             }
         }
     }