]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/ty/sty.rs
generate GeneratorSubsts from SubstsRef
[rust.git] / src / librustc / ty / sty.rs
index e73a51e6f78e5272eee86659d566340f87a7567d..ff20996df56ff52e59b597275d1053f9082125d1 100644 (file)
@@ -8,12 +8,12 @@
 use crate::mir::interpret::ConstValue;
 use crate::middle::region;
 use polonius_engine::Atom;
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_index::vec::Idx;
 use rustc_macros::HashStable;
-use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, Kind, UnpackedKind};
+use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind};
 use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
-use crate::ty::layout::VariantIdx;
+use crate::ty::layout::{Size, Integer, IntegerExt, VariantIdx};
 use crate::util::captures::Captures;
 use crate::mir::interpret::{Scalar, GlobalId};
 
@@ -24,6 +24,7 @@
 use std::ops::Range;
 use rustc_target::spec::abi;
 use syntax::ast::{self, Ident};
+use syntax::attr::{SignedInt, UnsignedInt};
 use syntax::symbol::{kw, InternedString};
 
 use self::InferTy::*;
@@ -86,7 +87,7 @@ pub fn assert_bound_var(&self) -> BoundVar {
 /// AST structure in `libsyntax/ast.rs` as well.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
          RustcEncodable, RustcDecodable, HashStable, Debug)]
-#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")]
+#[rustc_diagnostic_item = "TyKind"]
 pub enum TyKind<'tcx> {
     /// The primitive boolean type. Written as `bool`.
     Bool,
@@ -158,11 +159,11 @@ pub enum TyKind<'tcx> {
 
     /// The anonymous type of a closure. Used to represent the type of
     /// `|a| a`.
-    Closure(DefId, ClosureSubsts<'tcx>),
+    Closure(DefId, SubstsRef<'tcx>),
 
     /// The anonymous type of a generator. Used to represent the type of
     /// `|a| yield a`.
-    Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
+    Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability),
 
     /// A type representin the types stored inside a generator.
     /// This should only appear in GeneratorInteriors.
@@ -304,8 +305,8 @@ pub enum TyKind<'tcx> {
 /// type parameters is similar, but the role of CK and CS are
 /// different. CK represents the "yield type" and CS represents the
 /// "return type" of the generator.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
-         Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug,
+         RustcEncodable, RustcDecodable, HashStable)]
 pub struct ClosureSubsts<'tcx> {
     /// Lifetime and type parameters from the enclosing function,
     /// concatenated with the types of the upvars.
@@ -320,7 +321,7 @@ pub struct ClosureSubsts<'tcx> {
 struct SplitClosureSubsts<'tcx> {
     closure_kind_ty: Ty<'tcx>,
     closure_sig_ty: Ty<'tcx>,
-    upvar_kinds: &'tcx [Kind<'tcx>],
+    upvar_kinds: &'tcx [GenericArg<'tcx>],
 }
 
 impl<'tcx> ClosureSubsts<'tcx> {
@@ -345,7 +346,7 @@ pub fn upvar_tys(
     ) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
         let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
         upvar_kinds.iter().map(|t| {
-            if let UnpackedKind::Type(ty) = t.unpack() {
+            if let GenericArgKind::Type(ty) = t.unpack() {
                 ty
             } else {
                 bug!("upvar should be type")
@@ -356,7 +357,7 @@ pub fn upvar_tys(
     /// Returns the closure kind for this closure; may return a type
     /// variable during inference. To get the closure kind during
     /// inference, use `infcx.closure_kind(def_id, substs)`.
-    pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
+    pub fn kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
         self.split(def_id, tcx).closure_kind_ty
     }
 
@@ -364,7 +365,7 @@ pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
     /// closure; may contain type variables during inference. To get
     /// the closure signature during inference, use
     /// `infcx.fn_sig(def_id)`.
-    pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
+    pub fn sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
         self.split(def_id, tcx).closure_sig_ty
     }
 
@@ -373,7 +374,7 @@ pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
     /// there are no type variables.
     ///
     /// If you have an inference context, use `infcx.closure_kind()`.
-    pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
+    pub fn kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
         self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
     }
 
@@ -382,11 +383,11 @@ pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
     /// there are no type variables.
     ///
     /// If you have an inference context, use `infcx.closure_sig()`.
-    pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
-        let ty = self.closure_sig_ty(def_id, tcx);
-        match ty.sty {
+    pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
+        let ty = self.sig_ty(def_id, tcx);
+        match ty.kind {
             ty::FnPtr(sig) => sig,
-            _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.sty),
+            _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind),
         }
     }
 }
@@ -402,7 +403,7 @@ struct SplitGeneratorSubsts<'tcx> {
     yield_ty: Ty<'tcx>,
     return_ty: Ty<'tcx>,
     witness: Ty<'tcx>,
-    upvar_kinds: &'tcx [Kind<'tcx>],
+    upvar_kinds: &'tcx [GenericArg<'tcx>],
 }
 
 impl<'tcx> GeneratorSubsts<'tcx> {
@@ -434,7 +435,7 @@ pub fn upvar_tys(
     ) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
         let SplitGeneratorSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
         upvar_kinds.iter().map(|t| {
-            if let UnpackedKind::Type(ty) = t.unpack() {
+            if let GenericArgKind::Type(ty) = t.unpack() {
                 ty
             } else {
                 bug!("upvar should be type")
@@ -568,7 +569,7 @@ pub fn prefix_tys(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> impl Iterator<Item
 
 #[derive(Debug, Copy, Clone)]
 pub enum UpvarSubsts<'tcx> {
-    Closure(ClosureSubsts<'tcx>),
+    Closure(SubstsRef<'tcx>),
     Generator(GeneratorSubsts<'tcx>),
 }
 
@@ -577,14 +578,14 @@ impl<'tcx> UpvarSubsts<'tcx> {
     pub fn upvar_tys(
         self,
         def_id: DefId,
-        tcx: TyCtxt<'_>,
+        tcx: TyCtxt<'tcx>,
     ) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
         let upvar_kinds = match self {
-            UpvarSubsts::Closure(substs) => substs.split(def_id, tcx).upvar_kinds,
+            UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds,
             UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds,
         };
         upvar_kinds.iter().map(|t| {
-            if let UnpackedKind::Type(ty) = t.unpack() {
+            if let GenericArgKind::Type(ty) = t.unpack() {
                 ty
             } else {
                 bug!("upvar should be type")
@@ -1165,7 +1166,7 @@ pub fn to_const(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
     }
 }
 
-newtype_index! {
+rustc_index::newtype_index! {
     /// A [De Bruijn index][dbi] is a standard means of representing
     /// regions (and perhaps later types) in a higher-ranked setting. In
     /// particular, imagine a type like this:
@@ -1349,7 +1350,7 @@ pub struct FloatVid {
     pub index: u32,
 }
 
-newtype_index! {
+rustc_index::newtype_index! {
     pub struct RegionVid {
         DEBUG_FORMAT = custom,
     }
@@ -1376,7 +1377,7 @@ pub enum InferTy {
     FreshFloatTy(u32),
 }
 
-newtype_index! {
+rustc_index::newtype_index! {
     pub struct BoundVar { .. }
 }
 
@@ -1678,7 +1679,7 @@ pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_>) -> DefId {
 impl<'tcx> TyS<'tcx> {
     #[inline]
     pub fn is_unit(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Tuple(ref tys) => tys.is_empty(),
             _ => false,
         }
@@ -1686,7 +1687,7 @@ pub fn is_unit(&self) -> bool {
 
     #[inline]
     pub fn is_never(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Never => true,
             _ => false,
         }
@@ -1701,7 +1702,7 @@ pub fn is_never(&self) -> bool {
     pub fn conservative_is_privately_uninhabited(&self, tcx: TyCtxt<'tcx>) -> bool {
         // FIXME(varkor): we can make this less conversative by substituting concrete
         // type arguments.
-        match self.sty {
+        match self.kind {
             ty::Never => true,
             ty::Adt(def, _) if def.is_union() => {
                 // For now, `union`s are never considered uninhabited.
@@ -1741,7 +1742,7 @@ pub fn conservative_is_privately_uninhabited(&self, tcx: TyCtxt<'tcx>) -> bool {
 
     #[inline]
     pub fn is_primitive(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Bool | Char | Int(_) | Uint(_) | Float(_) => true,
             _ => false,
         }
@@ -1749,7 +1750,7 @@ pub fn is_primitive(&self) -> bool {
 
     #[inline]
     pub fn is_ty_var(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Infer(TyVar(_)) => true,
             _ => false,
         }
@@ -1757,7 +1758,7 @@ pub fn is_ty_var(&self) -> bool {
 
     #[inline]
     pub fn is_ty_infer(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Infer(_) => true,
             _ => false,
         }
@@ -1765,7 +1766,7 @@ pub fn is_ty_infer(&self) -> bool {
 
     #[inline]
     pub fn is_phantom_data(&self) -> bool {
-        if let Adt(def, _) = self.sty {
+        if let Adt(def, _) = self.kind {
             def.is_phantom_data()
         } else {
             false
@@ -1773,11 +1774,11 @@ pub fn is_phantom_data(&self) -> bool {
     }
 
     #[inline]
-    pub fn is_bool(&self) -> bool { self.sty == Bool }
+    pub fn is_bool(&self) -> bool { self.kind == Bool }
 
     #[inline]
     pub fn is_param(&self, index: u32) -> bool {
-        match self.sty {
+        match self.kind {
             ty::Param(ref data) => data.index == index,
             _ => false,
         }
@@ -1785,8 +1786,8 @@ pub fn is_param(&self, index: u32) -> bool {
 
     #[inline]
     pub fn is_slice(&self) -> bool {
-        match self.sty {
-            RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty {
+        match self.kind {
+            RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.kind {
                 Slice(_) | Str => true,
                 _ => false,
             },
@@ -1796,14 +1797,14 @@ pub fn is_slice(&self) -> bool {
 
     #[inline]
     pub fn is_simd(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Adt(def, _) => def.repr.simd(),
             _ => false,
         }
     }
 
     pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        match self.sty {
+        match self.kind {
             Array(ty, _) | Slice(ty) => ty,
             Str => tcx.mk_mach_uint(ast::UintTy::U8),
             _ => bug!("sequence_element_type called on non-sequence value: {}", self),
@@ -1811,7 +1812,7 @@ pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
     }
 
     pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        match self.sty {
+        match self.kind {
             Adt(def, substs) => {
                 def.non_enum_variant().fields[0].ty(tcx, substs)
             }
@@ -1820,7 +1821,7 @@ pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
     }
 
     pub fn simd_size(&self, _cx: TyCtxt<'_>) -> usize {
-        match self.sty {
+        match self.kind {
             Adt(def, _) => def.non_enum_variant().fields.len(),
             _ => bug!("simd_size called on invalid type")
         }
@@ -1828,7 +1829,7 @@ pub fn simd_size(&self, _cx: TyCtxt<'_>) -> usize {
 
     #[inline]
     pub fn is_region_ptr(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Ref(..) => true,
             _ => false,
         }
@@ -1836,7 +1837,7 @@ pub fn is_region_ptr(&self) -> bool {
 
     #[inline]
     pub fn is_mutable_ptr(&self) -> bool {
-        match self.sty {
+        match self.kind {
             RawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) |
             Ref(_, _, hir::Mutability::MutMutable) => true,
             _ => false
@@ -1845,7 +1846,7 @@ pub fn is_mutable_ptr(&self) -> bool {
 
     #[inline]
     pub fn is_unsafe_ptr(&self) -> bool {
-        match self.sty {
+        match self.kind {
             RawPtr(_) => return true,
             _ => return false,
         }
@@ -1860,7 +1861,7 @@ pub fn is_any_ptr(&self) -> bool {
     /// Returns `true` if this type is an `Arc<T>`.
     #[inline]
     pub fn is_arc(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Adt(def, _) => def.is_arc(),
             _ => false,
         }
@@ -1869,7 +1870,7 @@ pub fn is_arc(&self) -> bool {
     /// Returns `true` if this type is an `Rc<T>`.
     #[inline]
     pub fn is_rc(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Adt(def, _) => def.is_rc(),
             _ => false,
         }
@@ -1877,7 +1878,7 @@ pub fn is_rc(&self) -> bool {
 
     #[inline]
     pub fn is_box(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Adt(def, _) => def.is_box(),
             _ => false,
         }
@@ -1885,7 +1886,7 @@ pub fn is_box(&self) -> bool {
 
     /// panics if called on any type other than `Box<T>`
     pub fn boxed_ty(&self) -> Ty<'tcx> {
-        match self.sty {
+        match self.kind {
             Adt(def, substs) if def.is_box() => substs.type_at(0),
             _ => bug!("`boxed_ty` is called on non-box type {:?}", self),
         }
@@ -1896,7 +1897,7 @@ pub fn boxed_ty(&self) -> Ty<'tcx> {
     /// contents are abstract to rustc.)
     #[inline]
     pub fn is_scalar(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Bool | Char | Int(_) | Float(_) | Uint(_) |
             Infer(IntVar(_)) | Infer(FloatVar(_)) |
             FnDef(..) | FnPtr(_) | RawPtr(_) => true,
@@ -1907,7 +1908,7 @@ pub fn is_scalar(&self) -> bool {
     /// Returns `true` if this type is a floating point type.
     #[inline]
     pub fn is_floating_point(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Float(_) |
             Infer(FloatVar(_)) => true,
             _ => false,
@@ -1916,7 +1917,7 @@ pub fn is_floating_point(&self) -> bool {
 
     #[inline]
     pub fn is_trait(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Dynamic(..) => true,
             _ => false,
         }
@@ -1924,7 +1925,7 @@ pub fn is_trait(&self) -> bool {
 
     #[inline]
     pub fn is_enum(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Adt(adt_def, _) => {
                 adt_def.is_enum()
             }
@@ -1934,7 +1935,7 @@ pub fn is_enum(&self) -> bool {
 
     #[inline]
     pub fn is_closure(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Closure(..) => true,
             _ => false,
         }
@@ -1942,7 +1943,7 @@ pub fn is_closure(&self) -> bool {
 
     #[inline]
     pub fn is_generator(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Generator(..) => true,
             _ => false,
         }
@@ -1950,7 +1951,7 @@ pub fn is_generator(&self) -> bool {
 
     #[inline]
     pub fn is_integral(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Infer(IntVar(_)) | Int(_) | Uint(_) => true,
             _ => false
         }
@@ -1958,7 +1959,7 @@ pub fn is_integral(&self) -> bool {
 
     #[inline]
     pub fn is_fresh_ty(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Infer(FreshTy(_)) => true,
             _ => false,
         }
@@ -1966,7 +1967,7 @@ pub fn is_fresh_ty(&self) -> bool {
 
     #[inline]
     pub fn is_fresh(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Infer(FreshTy(_)) => true,
             Infer(FreshIntTy(_)) => true,
             Infer(FreshFloatTy(_)) => true,
@@ -1976,7 +1977,7 @@ pub fn is_fresh(&self) -> bool {
 
     #[inline]
     pub fn is_char(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Char => true,
             _ => false,
         }
@@ -1989,7 +1990,7 @@ pub fn is_numeric(&self) -> bool {
 
     #[inline]
     pub fn is_signed(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Int(_) => true,
             _ => false,
         }
@@ -1997,7 +1998,7 @@ pub fn is_signed(&self) -> bool {
 
     #[inline]
     pub fn is_ptr_sized_integral(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => true,
             _ => false,
         }
@@ -2005,7 +2006,7 @@ pub fn is_ptr_sized_integral(&self) -> bool {
 
     #[inline]
     pub fn is_machine(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Int(..) | Uint(..) | Float(..) => true,
             _ => false,
         }
@@ -2013,7 +2014,7 @@ pub fn is_machine(&self) -> bool {
 
     #[inline]
     pub fn has_concrete_skeleton(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Param(_) | Infer(_) | Error => false,
             _ => true,
         }
@@ -2024,7 +2025,7 @@ pub fn has_concrete_skeleton(&self) -> bool {
     /// The parameter `explicit` indicates if this is an *explicit* dereference.
     /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
     pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
-        match self.sty {
+        match self.kind {
             Adt(def, _) if def.is_box() => {
                 Some(TypeAndMut {
                     ty: self.boxed_ty(),
@@ -2039,14 +2040,14 @@ pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
 
     /// Returns the type of `ty[i]`.
     pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
-        match self.sty {
+        match self.kind {
             Array(ty, _) | Slice(ty) => Some(ty),
             _ => None,
         }
     }
 
     pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
-        match self.sty {
+        match self.kind {
             FnDef(def_id, substs) => {
                 tcx.fn_sig(def_id).subst(tcx, substs)
             }
@@ -2063,7 +2064,7 @@ pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
 
     #[inline]
     pub fn is_fn(&self) -> bool {
-        match self.sty {
+        match self.kind {
             FnDef(..) | FnPtr(_) => true,
             _ => false,
         }
@@ -2071,7 +2072,7 @@ pub fn is_fn(&self) -> bool {
 
     #[inline]
     pub fn is_fn_ptr(&self) -> bool {
-        match self.sty {
+        match self.kind {
             FnPtr(_) => true,
             _ => false,
         }
@@ -2079,7 +2080,7 @@ pub fn is_fn_ptr(&self) -> bool {
 
     #[inline]
     pub fn is_impl_trait(&self) -> bool {
-        match self.sty {
+        match self.kind {
             Opaque(..) => true,
             _ => false,
         }
@@ -2087,7 +2088,7 @@ pub fn is_impl_trait(&self) -> bool {
 
     #[inline]
     pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
-        match self.sty {
+        match self.kind {
             Adt(adt, _) => Some(adt),
             _ => None,
         }
@@ -2096,7 +2097,7 @@ pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
     /// Iterates over tuple fields.
     /// Panics when called on anything but a tuple.
     pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
-        match self.sty {
+        match self.kind {
             Tuple(substs) => substs.iter().map(|field| field.expect_ty()),
             _ => bug!("tuple_fields called on non-tuple"),
         }
@@ -2106,9 +2107,10 @@ pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
     /// FIXME This requires the optimized MIR in the case of generators.
     #[inline]
     pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
-        match self.sty {
+        match self.kind {
             TyKind::Adt(adt, _) => Some(adt.variant_range()),
-            TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)),
+            TyKind::Generator(def_id, substs, _) =>
+                Some(substs.assert_generator().variant_range(def_id, tcx)),
             _ => None,
         }
     }
@@ -2122,10 +2124,10 @@ pub fn discriminant_for_variant(
         tcx: TyCtxt<'tcx>,
         variant_index: VariantIdx,
     ) -> Option<Discr<'tcx>> {
-        match self.sty {
+        match self.kind {
             TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)),
             TyKind::Generator(def_id, substs, _) =>
-                Some(substs.discriminant_for_variant(def_id, tcx, variant_index)),
+                Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)),
             _ => None,
         }
     }
@@ -2134,7 +2136,7 @@ pub fn discriminant_for_variant(
     /// types reachable from this type via `walk_tys`). This ignores late-bound
     /// regions binders.
     pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) {
-        match self.sty {
+        match self.kind {
             Ref(region, _, _) => {
                 out.push(region);
             }
@@ -2147,8 +2149,8 @@ pub fn discriminant_for_variant(
             Adt(_, substs) | Opaque(_, substs) => {
                 out.extend(substs.regions())
             }
-            Closure(_, ClosureSubsts { ref substs }) |
-            Generator(_, GeneratorSubsts { ref substs }, _) => {
+            Closure(_, ref substs ) |
+            Generator(_, ref substs, _) => {
                 out.extend(substs.regions())
             }
             Projection(ref data) | UnnormalizedProjection(ref data) => {
@@ -2190,7 +2192,7 @@ pub fn discriminant_for_variant(
     /// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`)
     /// is complete, that type variable will be unified.
     pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
-        match self.sty {
+        match self.kind {
             Int(int_ty) => match int_ty {
                 ast::IntTy::I8 => Some(ty::ClosureKind::Fn),
                 ast::IntTy::I16 => Some(ty::ClosureKind::FnMut),
@@ -2211,7 +2213,7 @@ pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
     /// Returning true means the type is known to be sized. Returning
     /// `false` means nothing -- could be sized, might not be.
     pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
-        match self.sty {
+        match self.kind {
             ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
             ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
             ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) |
@@ -2298,8 +2300,21 @@ pub fn try_eval_bits(
         ty: Ty<'tcx>,
     ) -> Option<u128> {
         assert_eq!(self.ty, ty);
+        // This is purely an optimization -- layout_of is a pretty expensive operation,
+        // but if we can determine the size without calling it, we don't need all that complexity
+        // (hashing, caching, etc.). As such, try to skip it.
+        let size = match ty.kind {
+            ty::Bool => Size::from_bytes(1),
+            ty::Char => Size::from_bytes(4),
+            ty::Int(ity) => {
+                Integer::from_attr(&tcx, SignedInt(ity)).size()
+            }
+            ty::Uint(uty) => {
+                Integer::from_attr(&tcx, UnsignedInt(uty)).size()
+            }
+            _ => tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size,
+        };
         // if `ty` does not depend on generic parameters, use an empty param_env
-        let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
         self.eval(tcx, param_env).val.try_to_bits(size)
     }