about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-05-02 13:14:30 +0200
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-05-08 16:21:58 +0200
commit710b4ad2a5cc8e70b42d6d85ebe4eacc5b65548b (patch)
treeb0745808d96d623dbf514493d315518744a62b64
parent0edc8f4270589002fe12b9de9a2bd2b1220feb4d (diff)
downloadrust-710b4ad2a5cc8e70b42d6d85ebe4eacc5b65548b.tar.gz
rust-710b4ad2a5cc8e70b42d6d85ebe4eacc5b65548b.zip
Store the GeneratorInterior in the new GeneratorSubsts
-rw-r--r--src/librustc/ich/impls_mir.rs3
-rw-r--r--src/librustc/ich/impls_ty.rs12
-rw-r--r--src/librustc/mir/mod.rs16
-rw-r--r--src/librustc/mir/tcx.rs6
-rw-r--r--src/librustc/mir/visit.rs18
-rw-r--r--src/librustc/traits/mod.rs6
-rw-r--r--src/librustc/traits/project.rs2
-rw-r--r--src/librustc/traits/select.rs24
-rw-r--r--src/librustc/traits/structural_impls.rs10
-rw-r--r--src/librustc/ty/context.rs18
-rw-r--r--src/librustc/ty/fast_reject.rs2
-rw-r--r--src/librustc/ty/flags.rs3
-rw-r--r--src/librustc/ty/instance.rs9
-rw-r--r--src/librustc/ty/item_path.rs2
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/ty/outlives.rs2
-rw-r--r--src/librustc/ty/relate.rs23
-rw-r--r--src/librustc/ty/structural_impls.rs21
-rw-r--r--src/librustc/ty/sty.rs148
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc/ty/walk.rs3
-rw-r--r--src/librustc/util/ppaux.rs13
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs2
-rw-r--r--src/librustc_mir/borrow_check/mod.rs13
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs9
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/annotation.rs7
-rw-r--r--src/librustc_mir/borrow_check/nll/renumber.rs16
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs6
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs30
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs40
-rw-r--r--src/librustc_mir/build/mod.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs10
-rw-r--r--src/librustc_mir/hair/mod.rs6
-rw-r--r--src/librustc_mir/monomorphize/item.rs8
-rw-r--r--src/librustc_mir/monomorphize/mod.rs3
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs2
-rw-r--r--src/librustc_mir/transform/erase_regions.rs6
-rw-r--r--src/librustc_mir/transform/generator.rs10
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs7
-rw-r--r--src/librustc_mir/util/pretty.rs3
-rw-r--r--src/librustc_traits/dropck_outlives.rs2
-rw-r--r--src/librustc_trans/common.rs4
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs2
-rw-r--r--src/librustc_trans/mir/mod.rs9
-rw-r--r--src/librustc_typeck/check/closure.rs18
-rw-r--r--src/librustc_typeck/check/generator_interior.rs6
-rw-r--r--src/librustc_typeck/check/mod.rs9
-rw-r--r--src/librustc_typeck/check/upvar.rs34
-rw-r--r--src/librustc_typeck/collect.rs50
51 files changed, 357 insertions, 308 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 29a0632511c..c71b10ce142 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -483,10 +483,9 @@ for mir::AggregateKind<'gcx> {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            mir::AggregateKind::Generator(def_id, ref substs, ref interior, movability) => {
+            mir::AggregateKind::Generator(def_id, ref substs, movability) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
-                interior.hash_stable(hcx, hasher);
                 movability.hash_stable(hcx, hasher);
             }
         }
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 96ef8591645..42fde0a1903 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -517,8 +517,7 @@ for ::middle::const_val::ErrKind<'gcx> {
 }
 
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
-
-impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
+impl_stable_hash_for!(struct ty::GeneratorSubsts<'tcx> { substs });
 
 impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
     parent,
@@ -908,10 +907,9 @@ for ty::TypeVariants<'gcx>
                 def_id.hash_stable(hcx, hasher);
                 closure_substs.hash_stable(hcx, hasher);
             }
-            TyGenerator(def_id, closure_substs, interior, movability) => {
+            TyGenerator(def_id, generator_substs, movability) => {
                 def_id.hash_stable(hcx, hasher);
-                closure_substs.hash_stable(hcx, hasher);
-                interior.hash_stable(hcx, hasher);
+                generator_substs.hash_stable(hcx, hasher);
                 movability.hash_stable(hcx, hasher);
             }
             TyGeneratorWitness(types) => {
@@ -1316,11 +1314,11 @@ for traits::VtableGeneratorData<'gcx, N> where N: HashStable<StableHashingContex
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
         let traits::VtableGeneratorData {
-            closure_def_id,
+            generator_def_id,
             substs,
             ref nested,
         } = *self;
-        closure_def_id.hash_stable(hcx, hasher);
+        generator_def_id.hash_stable(hcx, hasher);
         substs.hash_stable(hcx, hasher);
         nested.hash_stable(hcx, hasher);
     }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 907ffc67606..cc9c5cadc93 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -27,7 +27,7 @@ use hir::def_id::DefId;
 use mir::visit::MirVisitable;
 use mir::interpret::{Value, PrimVal, EvalErrorKind};
 use ty::subst::{Subst, Substs};
-use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
+use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::TypeAndMut;
 use util::ppaux;
@@ -1641,7 +1641,7 @@ pub enum AggregateKind<'tcx> {
     Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<usize>),
 
     Closure(DefId, ClosureSubsts<'tcx>),
-    Generator(DefId, ClosureSubsts<'tcx>, GeneratorInterior<'tcx>, hir::GeneratorMovability),
+    Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
@@ -1804,7 +1804,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                         }
                     }),
 
-                    AggregateKind::Generator(def_id, _, _, _) => ty::tls::with(|tcx| {
+                    AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
                         if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
                             let name = format!("[generator@{:?}]", tcx.hir.span(node_id));
                             let mut struct_fmt = fmt.debug_struct(&name);
@@ -2375,11 +2375,8 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
                         AggregateKind::Adt(def, v, substs.fold_with(folder), n),
                     AggregateKind::Closure(id, substs) =>
                         AggregateKind::Closure(id, substs.fold_with(folder)),
-                    AggregateKind::Generator(id, substs, interior, movablity) =>
-                        AggregateKind::Generator(id,
-                                                 substs.fold_with(folder),
-                                                 interior.fold_with(folder),
-                                                 movablity),
+                    AggregateKind::Generator(id, substs, movablity) =>
+                        AggregateKind::Generator(id, substs.fold_with(folder), movablity),
                 };
                 Aggregate(kind, fields.fold_with(folder))
             }
@@ -2406,8 +2403,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
                     AggregateKind::Tuple => false,
                     AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
                     AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
-                    AggregateKind::Generator(_, substs, interior, _) => substs.visit_with(visitor) ||
-                        interior.visit_with(visitor),
+                    AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
                 }) || fields.visit_with(visitor)
             }
         }
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 33af199d758..6a9ff39c5f5 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -184,10 +184,10 @@ impl<'tcx> Rvalue<'tcx> {
                         tcx.type_of(def.did).subst(tcx, substs)
                     }
                     AggregateKind::Closure(did, substs) => {
-                        tcx.mk_closure_from_closure_substs(did, substs)
+                        tcx.mk_closure(did, substs)
                     }
-                    AggregateKind::Generator(did, substs, interior, movability) => {
-                        tcx.mk_generator(did, substs, interior, movability)
+                    AggregateKind::Generator(did, substs, movability) => {
+                        tcx.mk_generator(did, substs, movability)
                     }
                 }
             }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 6aed5076c1f..b647ba553dd 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -10,7 +10,7 @@
 
 use hir::def_id::DefId;
 use ty::subst::Substs;
-use ty::{CanonicalTy, ClosureSubsts, Region, Ty, GeneratorInterior};
+use ty::{CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty};
 use mir::*;
 use syntax_pos::Span;
 
@@ -243,10 +243,10 @@ macro_rules! make_mir_visitor {
                 self.super_closure_substs(substs);
             }
 
-            fn visit_generator_interior(&mut self,
-                                    interior: & $($mutability)* GeneratorInterior<'tcx>,
+            fn visit_generator_substs(&mut self,
+                                      substs: & $($mutability)* GeneratorSubsts<'tcx>,
                                     _: Location) {
-                self.super_generator_interior(interior);
+                self.super_generator_substs(substs);
             }
 
             fn visit_local_decl(&mut self,
@@ -595,12 +595,10 @@ macro_rules! make_mir_visitor {
                                 self.visit_closure_substs(closure_substs, location);
                             }
                             AggregateKind::Generator(ref $($mutability)* def_id,
-                                                     ref $($mutability)* closure_substs,
-                                                     ref $($mutability)* interior,
+                                                     ref $($mutability)* generator_substs,
                                                      _movability) => {
                                 self.visit_def_id(def_id, location);
-                                self.visit_closure_substs(closure_substs, location);
-                                self.visit_generator_interior(interior, location);
+                                self.visit_generator_substs(generator_substs, location);
                             }
                         }
 
@@ -787,8 +785,8 @@ macro_rules! make_mir_visitor {
             fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
             }
 
-            fn super_generator_interior(&mut self,
-                                    _interior: & $($mutability)* GeneratorInterior<'tcx>) {
+            fn super_generator_substs(&mut self,
+                                      _substs: & $($mutability)* GeneratorSubsts<'tcx>) {
             }
 
             fn super_closure_substs(&mut self,
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index dd5208e908e..26adbd82672 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -480,8 +480,8 @@ pub struct VtableImplData<'tcx, N> {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub struct VtableGeneratorData<'tcx, N> {
-    pub closure_def_id: DefId,
-    pub substs: ty::ClosureSubsts<'tcx>,
+    pub generator_def_id: DefId,
+    pub substs: ty::GeneratorSubsts<'tcx>,
     /// Nested obligations. This can be non-empty if the generator
     /// signature contains associated types.
     pub nested: Vec<N>
@@ -989,7 +989,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
                 nested: p.nested.into_iter().map(f).collect(),
             }),
             VtableGenerator(c) => VtableGenerator(VtableGeneratorData {
-                closure_def_id: c.closure_def_id,
+                generator_def_id: c.generator_def_id,
                 substs: c.substs,
                 nested: c.nested.into_iter().map(f).collect(),
             }),
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 45fa588bbf5..bfa32f8e7fa 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1288,7 +1288,7 @@ fn confirm_generator_candidate<'cx, 'gcx, 'tcx>(
     vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>)
     -> Progress<'tcx>
 {
-    let gen_sig = vtable.substs.generator_poly_sig(vtable.closure_def_id, selcx.tcx());
+    let gen_sig = vtable.substs.poly_sig(vtable.generator_def_id, selcx.tcx());
     let Normalized {
         value: gen_sig,
         obligations
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 82643c315b9..e73e11075d4 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2280,8 +2280,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 substs.upvar_tys(def_id, self.tcx()).collect()
             }
 
-            ty::TyGenerator(def_id, ref substs, interior, _) => {
-                substs.upvar_tys(def_id, self.tcx()).chain(iter::once(interior.witness)).collect()
+            ty::TyGenerator(def_id, ref substs, _) => {
+                let witness = substs.witness(def_id, self.tcx());
+                substs.upvar_tys(def_id, self.tcx()).chain(iter::once(witness)).collect()
             }
 
             ty::TyGeneratorWitness(types) => {
@@ -2755,18 +2756,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         // touch bound regions, they just capture the in-scope
         // type/region parameters
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
-        let (closure_def_id, substs) = match self_ty.sty {
-            ty::TyGenerator(id, substs, _, _) => (id, substs),
+        let (generator_def_id, substs) = match self_ty.sty {
+            ty::TyGenerator(id, substs, _) => (id, substs),
             _ => bug!("closure candidate for non-closure {:?}", obligation)
         };
 
         debug!("confirm_generator_candidate({:?},{:?},{:?})",
                obligation,
-               closure_def_id,
+               generator_def_id,
                substs);
 
         let trait_ref =
-            self.generator_trait_ref_unnormalized(obligation, closure_def_id, substs);
+            self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs);
         let Normalized {
             value: trait_ref,
             mut obligations
@@ -2776,8 +2777,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                  obligation.recursion_depth+1,
                                  &trait_ref);
 
-        debug!("confirm_generator_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
-               closure_def_id,
+        debug!("confirm_generator_candidate(generator_def_id={:?}, \
+                trait_ref={:?}, obligations={:?})",
+               generator_def_id,
                trait_ref,
                obligations);
 
@@ -2788,7 +2790,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                         trait_ref)?);
 
         Ok(VtableGeneratorData {
-            closure_def_id: closure_def_id,
+            generator_def_id: generator_def_id,
             substs: substs.clone(),
             nested: obligations
         })
@@ -3294,10 +3296,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn generator_trait_ref_unnormalized(&mut self,
                                       obligation: &TraitObligation<'tcx>,
                                       closure_def_id: DefId,
-                                      substs: ty::ClosureSubsts<'tcx>)
+                                      substs: ty::GeneratorSubsts<'tcx>)
                                       -> ty::PolyTraitRef<'tcx>
     {
-        let gen_sig = substs.generator_poly_sig(closure_def_id, self.tcx());
+        let gen_sig = substs.poly_sig(closure_def_id, self.tcx());
 
         // (1) Feels icky to skip the binder here, but OTOH we know
         // that the self-type is an generator type and hence is
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index d7e42655bbb..822ea17009b 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -83,8 +83,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableImplData<'tcx, N> {
 
 impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableGeneratorData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "VtableGenerator(closure_def_id={:?}, substs={:?}, nested={:?})",
-               self.closure_def_id,
+        write!(f, "VtableGenerator(generator_def_id={:?}, substs={:?}, nested={:?})",
+               self.generator_def_id,
                self.substs,
                self.nested)
     }
@@ -294,13 +294,13 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
             }
             traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
             traits::VtableGenerator(traits::VtableGeneratorData {
-                closure_def_id,
+                generator_def_id,
                 substs,
                 nested
             }) => {
                 tcx.lift(&substs).map(|substs| {
                     traits::VtableGenerator(traits::VtableGeneratorData {
-                        closure_def_id: closure_def_id,
+                        generator_def_id: generator_def_id,
                         substs: substs,
                         nested: nested
                     })
@@ -373,7 +373,7 @@ BraceStructTypeFoldableImpl! {
 
 BraceStructTypeFoldableImpl! {
     impl<'tcx, N> TypeFoldable<'tcx> for traits::VtableGeneratorData<'tcx, N> {
-        closure_def_id, substs, nested
+        generator_def_id, substs, nested
     } where N: TypeFoldable<'tcx>
 }
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6ed243361c0..139b2359119 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -41,7 +41,7 @@ use traits;
 use traits::{Clause, Clauses, Goal, Goals};
 use ty::{self, Ty, TypeAndMut};
 use ty::{TyS, TypeVariants, Slice};
-use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region, Const};
+use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
 use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
 use ty::RegionKind;
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
@@ -2436,27 +2436,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }))
         }
 
-    pub fn mk_closure(self,
-                      closure_id: DefId,
-                      substs: ClosureSubsts<'tcx>)
-                      -> Ty<'tcx> {
-        self.mk_closure_from_closure_substs(closure_id, substs)
-    }
-
-    pub fn mk_closure_from_closure_substs(self,
-                                          closure_id: DefId,
-                                          closure_substs: ClosureSubsts<'tcx>)
+    pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>)
                                           -> Ty<'tcx> {
         self.mk_ty(TyClosure(closure_id, closure_substs))
     }
 
     pub fn mk_generator(self,
                         id: DefId,
-                        closure_substs: ClosureSubsts<'tcx>,
-                        interior: GeneratorInterior<'tcx>,
+                        generator_substs: GeneratorSubsts<'tcx>,
                         movability: hir::GeneratorMovability)
                         -> Ty<'tcx> {
-        self.mk_ty(TyGenerator(id, closure_substs, interior, movability))
+        self.mk_ty(TyGenerator(id, generator_substs, movability))
     }
 
     pub fn mk_generator_witness(self, types: ty::Binder<&'tcx Slice<Ty<'tcx>>>) -> Ty<'tcx> {
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 2b6901f74de..31b3ca44700 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -90,7 +90,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyClosure(def_id, _) => {
             Some(ClosureSimplifiedType(def_id))
         }
-        ty::TyGenerator(def_id, _, _, _) => {
+        ty::TyGenerator(def_id, _, _) => {
             Some(GeneratorSimplifiedType(def_id))
         }
         ty::TyGeneratorWitness(ref tys) => {
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index acc17a08a80..bb707c556c0 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -87,11 +87,10 @@ impl FlagComputation {
                 }
             }
 
-            &ty::TyGenerator(_, ref substs, ref interior, _) => {
+            &ty::TyGenerator(_, ref substs, _) => {
                 self.add_flags(TypeFlags::HAS_TY_CLOSURE);
                 self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
                 self.add_substs(&substs.substs);
-                self.add_ty(interior.witness);
             }
 
             &ty::TyGeneratorWitness(ref ts) => {
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index ecd415c4bc4..e7b71ca2b22 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -270,10 +270,10 @@ fn resolve_associated_item<'a, 'tcx>(
             let substs = tcx.erase_regions(&substs);
             Some(ty::Instance::new(def_id, substs))
         }
-        traits::VtableGenerator(closure_data) => {
+        traits::VtableGenerator(generator_data) => {
             Some(Instance {
-                def: ty::InstanceDef::Item(closure_data.closure_def_id),
-                substs: closure_data.substs.substs
+                def: ty::InstanceDef::Item(generator_data.generator_def_id),
+                substs: generator_data.substs.substs
             })
         }
         traits::VtableClosure(closure_data) => {
@@ -356,8 +356,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
         .unwrap().def_id;
     let def = ty::InstanceDef::ClosureOnceShim { call_once };
 
-    let self_ty = tcx.mk_closure_from_closure_substs(
-        closure_did, substs);
+    let self_ty = tcx.mk_closure(closure_did, substs);
 
     let sig = substs.closure_sig(closure_did, tcx);
     let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index b58c4138597..752b7f69a6a 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -369,7 +369,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
 
         ty::TyFnDef(def_id, _) |
         ty::TyClosure(def_id, _) |
-        ty::TyGenerator(def_id, _, _, _) |
+        ty::TyGenerator(def_id, _, _) |
         ty::TyForeign(def_id) => Some(def_id),
 
         ty::TyBool |
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 7b91040b8e7..02c4b73efa1 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -599,7 +599,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             }
 
             // Tuples, generators and closures.
-            ty::TyGenerator(def_id, ref substs, _, _) => {
+            ty::TyGenerator(def_id, ref substs, _) => {
                 let tys = substs.field_tys(def_id, tcx);
                 univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
                     &ReprOptions::default(),
@@ -1603,7 +1603,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                 substs.upvar_tys(def_id, tcx).nth(i).unwrap()
             }
 
-            ty::TyGenerator(def_id, ref substs, _, _) => {
+            ty::TyGenerator(def_id, ref substs, _) => {
                 substs.field_tys(def_id, tcx).nth(i).unwrap()
             }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index c4fe112a9e9..3bca65ec818 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -63,7 +63,7 @@ use hir;
 pub use self::sty::{Binder, CanonicalVar, DebruijnIndex};
 pub use self::sty::{FnSig, GenSig, PolyFnSig, PolyGenSig};
 pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
-pub use self::sty::{ClosureSubsts, GeneratorInterior, TypeAndMut};
+pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
 pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
 pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
 pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 4eb736789f3..ff99a4b7ff6 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -79,7 +79,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 }
             }
 
-            ty::TyGenerator(def_id, ref substs, _, _) => {
+            ty::TyGenerator(def_id, ref substs, _) => {
                 // Same as the closure case
                 for upvar_ty in substs.upvar_tys(def_id, *self) {
                     self.compute_components(upvar_ty, out);
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index ed0835418a4..8c3779b0c1e 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -415,16 +415,15 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
         }
 
-        (&ty::TyGenerator(a_id, a_substs, a_interior, movability),
-         &ty::TyGenerator(b_id, b_substs, b_interior, _))
+        (&ty::TyGenerator(a_id, a_substs, movability),
+         &ty::TyGenerator(b_id, b_substs, _))
             if a_id == b_id =>
         {
             // All TyGenerator types with the same id represent
             // the (anonymous) type of the same generator expression. So
             // all of their regions should be equated.
             let substs = relation.relate(&a_substs, &b_substs)?;
-            let interior = relation.relate(&a_interior, &b_interior)?;
-            Ok(tcx.mk_generator(a_id, substs, interior, movability))
+            Ok(tcx.mk_generator(a_id, substs, movability))
         }
 
         (&ty::TyGeneratorWitness(a_types), &ty::TyGeneratorWitness(b_types)) =>
@@ -446,7 +445,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             // the (anonymous) type of the same closure expression. So
             // all of their regions should be equated.
             let substs = relation.relate(&a_substs, &b_substs)?;
-            Ok(tcx.mk_closure_from_closure_substs(a_id, substs))
+            Ok(tcx.mk_closure(a_id, substs))
         }
 
         (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) =>
@@ -607,19 +606,19 @@ impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> {
         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
     {
         let substs = relate_substs(relation, None, a.substs, b.substs)?;
-        Ok(ty::ClosureSubsts { substs: substs })
+        Ok(ty::ClosureSubsts { substs })
     }
 }
 
-impl<'tcx> Relate<'tcx> for ty::GeneratorInterior<'tcx> {
+impl<'tcx> Relate<'tcx> for ty::GeneratorSubsts<'tcx> {
     fn relate<'a, 'gcx, R>(relation: &mut R,
-                           a: &ty::GeneratorInterior<'tcx>,
-                           b: &ty::GeneratorInterior<'tcx>)
-                           -> RelateResult<'tcx, ty::GeneratorInterior<'tcx>>
+                           a: &ty::GeneratorSubsts<'tcx>,
+                           b: &ty::GeneratorSubsts<'tcx>)
+                           -> RelateResult<'tcx, ty::GeneratorSubsts<'tcx>>
         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
     {
-        let witness = relation.relate(&a.witness, &b.witness)?;
-        Ok(ty::GeneratorInterior { witness })
+        let substs = relate_substs(relation, None, a.substs, b.substs)?;
+        Ok(ty::GeneratorSubsts { substs })
     }
 }
 
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 6df3b5dc2bd..933756dcd3d 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -304,16 +304,16 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ClosureSubsts<'a> {
     type Lifted = ty::ClosureSubsts<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&self.substs).map(|substs| {
-            ty::ClosureSubsts { substs: substs }
+            ty::ClosureSubsts { substs }
         })
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for ty::GeneratorInterior<'a> {
-    type Lifted = ty::GeneratorInterior<'tcx>;
+impl<'a, 'tcx> Lift<'tcx> for ty::GeneratorSubsts<'a> {
+    type Lifted = ty::GeneratorSubsts<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.witness).map(|witness| {
-            ty::GeneratorInterior { witness }
+        tcx.lift(&self.substs).map(|substs| {
+            ty::GeneratorSubsts { substs }
         })
     }
 }
@@ -867,11 +867,10 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::TyRef(ref r, tm) => {
                 ty::TyRef(r.fold_with(folder), tm.fold_with(folder))
             }
-            ty::TyGenerator(did, substs, interior, movability) => {
+            ty::TyGenerator(did, substs, movability) => {
                 ty::TyGenerator(
                     did,
                     substs.fold_with(folder),
-                    interior.fold_with(folder),
                     movability)
             }
             ty::TyGeneratorWitness(types) => ty::TyGeneratorWitness(types.fold_with(folder)),
@@ -906,8 +905,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::TyFnDef(_, substs) => substs.visit_with(visitor),
             ty::TyFnPtr(ref f) => f.visit_with(visitor),
             ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
-            ty::TyGenerator(_did, ref substs, ref interior, _) => {
-                substs.visit_with(visitor) || interior.visit_with(visitor)
+            ty::TyGenerator(_did, ref substs, _) => {
+                substs.visit_with(visitor)
             }
             ty::TyGeneratorWitness(ref types) => types.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
@@ -984,8 +983,8 @@ BraceStructTypeFoldableImpl! {
 }
 
 BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorInterior<'tcx> {
-        witness,
+    impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorSubsts<'tcx> {
+        substs,
     }
 }
 
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index b2c715bf7b9..c7e67c974dd 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -139,7 +139,7 @@ pub enum TypeVariants<'tcx> {
 
     /// The anonymous type of a generator. Used to represent the type of
     /// `|a| yield a`.
-    TyGenerator(DefId, ClosureSubsts<'tcx>, GeneratorInterior<'tcx>, hir::GeneratorMovability),
+    TyGenerator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
 
     /// A type representin the types stored inside a generator.
     /// This should only appear in GeneratorInteriors.
@@ -328,37 +328,6 @@ impl<'tcx> ClosureSubsts<'tcx> {
         self.split(def_id, tcx).closure_sig_ty
     }
 
-    /// Returns the type representing the yield type of the generator.
-    pub fn generator_yield_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
-        self.closure_kind_ty(def_id, tcx)
-    }
-
-    /// Returns the type representing the return type of the generator.
-    pub fn generator_return_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
-        self.closure_sig_ty(def_id, tcx)
-    }
-
-    /// Return the "generator signature", which consists of its yield
-    /// and return types.
-    ///
-    /// NB. Some bits of the code prefers to see this wrapped in a
-    /// binder, but it never contains bound regions. Probably this
-    /// function should be removed.
-    pub fn generator_poly_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> PolyGenSig<'tcx> {
-        ty::Binder::dummy(self.generator_sig(def_id, tcx))
-    }
-
-    /// Return the "generator signature", which consists of its yield
-    /// and return types.
-    pub fn generator_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> GenSig<'tcx> {
-        ty::GenSig {
-            yield_ty: self.generator_yield_ty(def_id, tcx),
-            return_ty: self.generator_return_ty(def_id, tcx),
-        }
-    }
-}
-
-impl<'tcx> ClosureSubsts<'tcx> {
     /// Returns the closure kind for this closure; only usable outside
     /// of an inference context, because in that context we know that
     /// there are no type variables.
@@ -381,7 +350,84 @@ impl<'tcx> ClosureSubsts<'tcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> ClosureSubsts<'tcx> {
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct GeneratorSubsts<'tcx> {
+    pub substs: &'tcx Substs<'tcx>,
+}
+
+struct SplitGeneratorSubsts<'tcx> {
+    yield_ty: Ty<'tcx>,
+    return_ty: Ty<'tcx>,
+    witness: Ty<'tcx>,
+    upvar_kinds: &'tcx [Kind<'tcx>],
+}
+
+impl<'tcx> GeneratorSubsts<'tcx> {
+    fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitGeneratorSubsts<'tcx> {
+        let generics = tcx.generics_of(def_id);
+        let parent_len = generics.parent_count();
+        SplitGeneratorSubsts {
+            yield_ty: self.substs.type_at(parent_len),
+            return_ty: self.substs.type_at(parent_len + 1),
+            witness: self.substs.type_at(parent_len + 2),
+            upvar_kinds: &self.substs[parent_len + 3..],
+        }
+    }
+
+    /// This describes the types that can be contained in a generator.
+    /// It will be a type variable initially and unified in the last stages of typeck of a body.
+    /// It contains a tuple of all the types that could end up on a generator frame.
+    /// The state transformation MIR pass may only produce layouts which mention types
+    /// in this tuple. Upvars are not counted here.
+    pub fn witness(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
+        self.split(def_id, tcx).witness
+    }
+
+    #[inline]
+    pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) ->
+        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() {
+                ty
+            } else {
+                bug!("upvar should be type")
+            }
+        })
+    }
+
+    /// Returns the type representing the yield type of the generator.
+    pub fn yield_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
+        self.split(def_id, tcx).yield_ty
+    }
+
+    /// Returns the type representing the return type of the generator.
+    pub fn return_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
+        self.split(def_id, tcx).return_ty
+    }
+
+    /// Return the "generator signature", which consists of its yield
+    /// and return types.
+    ///
+    /// NB. Some bits of the code prefers to see this wrapped in a
+    /// binder, but it never contains bound regions. Probably this
+    /// function should be removed.
+    pub fn poly_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> PolyGenSig<'tcx> {
+        ty::Binder::dummy(self.sig(def_id, tcx))
+    }
+
+    /// Return the "generator signature", which consists of its yield
+    /// and return types.
+    pub fn sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> GenSig<'tcx> {
+        ty::GenSig {
+            yield_ty: self.yield_ty(def_id, tcx),
+            return_ty: self.return_ty(def_id, tcx),
+        }
+    }
+}
+
+impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
     /// This returns the types of the MIR locals which had to be stored across suspension points.
     /// It is calculated in rustc_mir::transform::generator::StateTransform.
     /// All the types here must be in the tuple in GeneratorInterior.
@@ -412,14 +458,29 @@ impl<'a, 'gcx, 'tcx> ClosureSubsts<'tcx> {
     }
 }
 
-/// This describes the types that can be contained in a generator.
-/// It will be a type variable initially and unified in the last stages of typeck of a body.
-/// It contains a tuple of all the types that could end up on a generator frame.
-/// The state transformation MIR pass may only produce layouts which mention types in this tuple.
-/// Upvars are not counted here.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct GeneratorInterior<'tcx> {
-    pub witness: Ty<'tcx>,
+#[derive(Debug, Copy, Clone)]
+pub enum UpvarSubsts<'tcx> {
+    Closure(ClosureSubsts<'tcx>),
+    Generator(GeneratorSubsts<'tcx>),
+}
+
+impl<'tcx> UpvarSubsts<'tcx> {
+    #[inline]
+    pub fn upvar_tys(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) ->
+        impl Iterator<Item=Ty<'tcx>> + 'tcx
+    {
+        let upvar_kinds = match self {
+            UpvarSubsts::Closure(substs) => substs.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() {
+                ty
+            } else {
+                bug!("upvar should be type")
+            }
+        })
+    }
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@@ -1604,8 +1665,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
             TyAdt(_, substs) | TyAnon(_, substs) => {
                 substs.regions().collect()
             }
-            TyClosure(_, ref substs) | TyGenerator(_, ref substs, _, _) => {
-                substs.substs.regions().collect()
+            TyClosure(_, ClosureSubsts { ref substs }) |
+            TyGenerator(_, GeneratorSubsts { ref substs }, _) => {
+                substs.regions().collect()
             }
             TyProjection(ref data) => {
                 data.substs.regions().collect()
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 12421715ed5..4aa70e1f7e0 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -667,7 +667,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
             TyRawPtr(m) |
             TyRef(_, m) => self.hash(m.mutbl),
             TyClosure(def_id, _) |
-            TyGenerator(def_id, _, _, _) |
+            TyGenerator(def_id, _, _) |
             TyAnon(def_id, _) |
             TyFnDef(def_id, _) => self.def_id(def_id),
             TyAdt(d, _) => self.def_id(d.did),
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index d3fa376d6a8..4567baf5ef4 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -118,8 +118,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyClosure(_, ref substs) => {
             stack.extend(substs.substs.types().rev());
         }
-        ty::TyGenerator(_, ref substs, ref interior, _) => {
-            stack.push(interior.witness);
+        ty::TyGenerator(_, ref substs, _) => {
             stack.extend(substs.substs.types().rev());
         }
         ty::TyGeneratorWitness(ts) => {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 770357e549d..15e91404f6d 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -996,14 +996,6 @@ define_print! {
 }
 
 define_print! {
-    ('tcx) ty::GeneratorInterior<'tcx>, (self, f, cx) {
-        display {
-            self.witness.print(f, cx)
-        }
-    }
-}
-
-define_print! {
     ('tcx) ty::TypeVariants<'tcx>, (self, f, cx) {
         display {
             match *self {
@@ -1110,8 +1102,9 @@ define_print! {
                     })
                 }
                 TyStr => write!(f, "str"),
-                TyGenerator(did, substs, interior, movability) => ty::tls::with(|tcx| {
+                TyGenerator(did, substs, movability) => ty::tls::with(|tcx| {
                     let upvar_tys = substs.upvar_tys(did, tcx);
+                    let witness = substs.witness(did, tcx);
                     if movability == hir::GeneratorMovability::Movable {
                         write!(f, "[generator")?;
                     } else {
@@ -1145,7 +1138,7 @@ define_print! {
                         }
                     }
 
-                    print!(f, cx, write(" "), print(interior), write("]"))
+                    print!(f, cx, write(" "), print(witness), write("]"))
                 }),
                 TyGeneratorWitness(types) => {
                     ty::tls::with(|tcx| cx.in_binder(f, tcx, &types, tcx.lift(&types)))
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index f68c164751d..db2e078586e 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -777,7 +777,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     self.describe_field_from_ty(&tnm.ty, field)
                 }
                 ty::TyArray(ty, _) | ty::TySlice(ty) => self.describe_field_from_ty(&ty, field),
-                ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _, _) => {
+                ty::TyClosure(def_id, _) | ty::TyGenerator(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
                     // the closure comes from another crate. But in that case we wouldn't
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 3e3f510e308..953238a7218 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -835,10 +835,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 tys.iter().cloned().enumerate()
                     .for_each(|field| drop_field(self, field));
             }
-            // Closures and generators also have disjoint fields, but they are only
-            // directly accessed in the body of the closure/generator.
+            // Closures also have disjoint fields, but they are only
+            // directly accessed in the body of the closure.
             ty::TyClosure(def, substs)
-            | ty::TyGenerator(def, substs, ..)
+                if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
+            => {
+                substs.upvar_tys(def, self.tcx).enumerate()
+                    .for_each(|field| drop_field(self, field));
+            }
+            // Generators also have disjoint fields, but they are only
+            // directly accessed in the body of the generator.
+            ty::TyGenerator(def, substs, _)
                 if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty()
             => {
                 substs.upvar_tys(def, self.tcx).enumerate()
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index d34e9434fbf..1191ee9f9fb 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -20,7 +20,7 @@ use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
 use rustc::mir::{Local, PlaceProjection, ProjectionElem, Statement, Terminator};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, CanonicalTy, ClosureSubsts};
+use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts};
 
 use super::region_infer::{Cause, RegionInferenceContext};
 use super::ToRegionVid;
@@ -97,6 +97,13 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         self.super_ty(ty);
     }
 
+    /// We sometimes have `generator_substs` within an rvalue, or within a
+    /// call. Make them live at the location where they appear.
+    fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
+        self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
+        self.super_generator_substs(substs);
+    }
+
     /// We sometimes have `closure_substs` within an rvalue, or within a
     /// call. Make them live at the location where they appear.
     fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
index 664d4214ca8..fbff17e5898 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
@@ -30,12 +30,11 @@ impl<'gcx, 'tcx> RegionInferenceContext<'tcx> {
                     &substs.substs[..]
                 ));
             }
-            DefiningTy::Generator(def_id, substs, interior, _) => {
+            DefiningTy::Generator(def_id, substs, _) => {
                 err.note(&format!(
-                    "defining type: {:?} with closure substs {:#?} and interior {:?}",
+                    "defining type: {:?} with generator substs {:#?}",
                     def_id,
-                    &substs.substs[..],
-                    interior
+                    &substs.substs[..]
                 ));
             }
             DefiningTy::FnDef(def_id, substs) => {
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 04c206b5c0c..7edee42b78f 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
+use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
 use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -90,19 +90,19 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
         *constant = self.renumber_regions(ty_context, &*constant);
     }
 
-    fn visit_generator_interior(&mut self,
-                                interior: &mut GeneratorInterior<'tcx>,
-                                location: Location) {
+    fn visit_generator_substs(&mut self,
+                              substs: &mut GeneratorSubsts<'tcx>,
+                              location: Location) {
         debug!(
-            "visit_generator_interior(interior={:?}, location={:?})",
-            interior,
+            "visit_generator_substs(substs={:?}, location={:?})",
+            substs,
             location,
         );
 
         let ty_context = TyContext::Location(location);
-        *interior = self.renumber_regions(ty_context, interior);
+        *substs = self.renumber_regions(ty_context, substs);
 
-        debug!("visit_generator_interior: interior={:?}", interior);
+        debug!("visit_generator_substs: substs={:?}", substs);
     }
 
     fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, 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 6c4c4a171ef..42a1745addf 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -528,7 +528,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                         }),
                     }
                 }
-                ty::TyGenerator(def_id, substs, _, _) => {
+                ty::TyGenerator(def_id, substs, _) => {
                     // Try pre-transform fields first (upvars and current state)
                     if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) {
                         return Ok(ty);
@@ -1254,7 +1254,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     }),
                 }
             }
-            AggregateKind::Generator(def_id, substs, _, _) => {
+            AggregateKind::Generator(def_id, substs, _) => {
                 // Try pre-transform fields first (upvars and current state)
                 if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field_index) {
                     Ok(ty)
@@ -1497,7 +1497,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
             }
 
-            AggregateKind::Generator(def_id, substs, _, _) => {
+            AggregateKind::Generator(def_id, substs, _) => {
                 tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
             }
 
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 0e519a37e57..52ebf38c668 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -28,7 +28,7 @@ use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 use rustc::infer::region_constraints::GenericKind;
 use rustc::infer::outlives::bounds::{self, OutlivesBound};
 use rustc::infer::outlives::free_region_map::FreeRegionRelations;
-use rustc::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc::ty::{self, RegionVid, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::FxHashMap;
@@ -116,10 +116,7 @@ pub enum DefiningTy<'tcx> {
     /// The MIR is a generator. The signature is that generators take
     /// no parameters and return the result of
     /// `ClosureSubsts::generator_return_ty`.
-    Generator(DefId,
-              ty::ClosureSubsts<'tcx>,
-              ty::GeneratorInterior<'tcx>,
-              hir::GeneratorMovability),
+    Generator(DefId, ty::GeneratorSubsts<'tcx>, hir::GeneratorMovability),
 
     /// The MIR is a fn item with the given def-id and substs. The signature
     /// of the function can be bound then with the `fn_sig` query.
@@ -511,8 +508,8 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
         );
 
         let yield_ty = match defining_ty {
-            DefiningTy::Generator(def_id, substs, _, _) => {
-                Some(substs.generator_yield_ty(def_id, self.infcx.tcx))
+            DefiningTy::Generator(def_id, substs, _) => {
+                Some(substs.yield_ty(def_id, self.infcx.tcx))
             }
             _ => None,
         };
@@ -553,8 +550,8 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
 
                 match defining_ty.sty  {
                     ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs),
-                    ty::TyGenerator(def_id, substs, interior, movability) => {
-                        DefiningTy::Generator(def_id, substs, interior, movability)
+                    ty::TyGenerator(def_id, substs, movability) => {
+                        DefiningTy::Generator(def_id, substs, movability)
                     }
                     ty::TyFnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs),
                     _ => span_bug!(
@@ -590,7 +587,8 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
         let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
         let identity_substs = Substs::identity_for_item(gcx, closure_base_def_id);
         let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, substs) | DefiningTy::Generator(_, substs, _, _) => {
+            DefiningTy::Closure(_, ClosureSubsts { ref substs }) |
+            DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => {
                 // In the case of closures, we rely on the fact that
                 // the first N elements in the ClosureSubsts are
                 // inherited from the `closure_base_def_id`.
@@ -598,9 +596,9 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
                 // `identity_substs`, we will get only those regions
                 // that correspond to early-bound regions declared on
                 // the `closure_base_def_id`.
-                assert!(substs.substs.len() >= identity_substs.len());
-                assert_eq!(substs.substs.regions().count(), identity_substs.regions().count());
-                substs.substs
+                assert!(substs.len() >= identity_substs.len());
+                assert_eq!(substs.regions().count(), identity_substs.regions().count());
+                substs
             }
 
             DefiningTy::FnDef(_, substs) | DefiningTy::Const(_, substs) => substs,
@@ -651,10 +649,10 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
                 )
             }
 
-            DefiningTy::Generator(def_id, substs, interior, movability) => {
+            DefiningTy::Generator(def_id, substs, movability) => {
                 assert_eq!(self.mir_def_id, def_id);
-                let output = substs.generator_return_ty(def_id, tcx);
-                let generator_ty = tcx.mk_generator(def_id, substs, interior, movability);
+                let output = substs.return_ty(def_id, tcx);
+                let generator_ty = tcx.mk_generator(def_id, substs, movability);
                 let inputs_and_output = self.infcx.tcx.intern_type_list(&[generator_ty, output]);
                 ty::Binder::dummy(inputs_and_output)
             }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 593c43e1ab4..648746b6e90 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -18,7 +18,7 @@ use build::expr::category::{Category, RvalueFunc};
 use hair::*;
 use rustc::middle::const_val::ConstVal;
 use rustc::middle::region;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, UpvarSubsts};
 use rustc::mir::*;
 use rustc::mir::interpret::{Value, PrimVal, EvalErrorKind};
 use syntax_pos::Span;
@@ -185,28 +185,32 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
                 block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
             }
-            ExprKind::Closure { closure_id, substs, upvars, interior } => {
+            ExprKind::Closure { closure_id, substs, upvars, movability } => {
                 // see (*) above
                 let mut operands: Vec<_> =
                     upvars.into_iter()
                           .map(|upvar| unpack!(block = this.as_operand(block, scope, upvar)))
                           .collect();
-                let result = if let Some((interior, movability)) = interior {
-                    // Add the state operand since it follows the upvars in the generator
-                    // struct. See librustc_mir/transform/generator.rs for more details.
-                    operands.push(Operand::Constant(box Constant {
-                        span: expr_span,
-                        ty: this.hir.tcx().types.u32,
-                        literal: Literal::Value {
-                            value: this.hir.tcx().mk_const(ty::Const {
-                                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
-                                ty: this.hir.tcx().types.u32
-                            }),
-                        },
-                    }));
-                    box AggregateKind::Generator(closure_id, substs, interior, movability)
-                } else {
-                    box AggregateKind::Closure(closure_id, substs)
+                let result = match substs {
+                    UpvarSubsts::Generator(substs) => {
+                        let movability = movability.unwrap();
+                        // Add the state operand since it follows the upvars in the generator
+                        // struct. See librustc_mir/transform/generator.rs for more details.
+                        operands.push(Operand::Constant(box Constant {
+                            span: expr_span,
+                            ty: this.hir.tcx().types.u32,
+                            literal: Literal::Value {
+                                value: this.hir.tcx().mk_const(ty::Const {
+                                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
+                                    ty: this.hir.tcx().types.u32
+                                }),
+                            },
+                        }));
+                        box AggregateKind::Generator(closure_id, substs, movability)
+                    }
+                    UpvarSubsts::Closure(substs) => {
+                        box AggregateKind::Closure(closure_id, substs)
+                    }
                 };
                 block.and(Rvalue::Aggregate(result, operands))
             }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index dd2a336af41..afbcf100b05 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -130,7 +130,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
             let (yield_ty, return_ty) = if body.is_generator {
                 let gen_sig = match ty.sty {
                     ty::TyGenerator(gen_def_id, gen_substs, ..) =>
-                        gen_substs.generator_sig(gen_def_id, tcx),
+                        gen_substs.sig(gen_def_id, tcx),
                     _ =>
                         span_bug!(tcx.hir.span(id), "generator w/o generator type: {:?}", ty),
                 };
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 966092ac5df..24949753821 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -470,10 +470,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         hir::ExprClosure(..) => {
             let closure_ty = cx.tables().expr_ty(expr);
-            let (def_id, substs, interior) = match closure_ty.sty {
-                ty::TyClosure(def_id, substs) => (def_id, substs, None),
-                ty::TyGenerator(def_id, substs, interior, movability) =>{
-                    (def_id, substs, Some((interior, movability)))
+            let (def_id, substs, movability) = match closure_ty.sty {
+                ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None),
+                ty::TyGenerator(def_id, substs, movability) => {
+                    (def_id, UpvarSubsts::Generator(substs), Some(movability))
                 }
                 _ => {
                     span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
@@ -489,7 +489,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 closure_id: def_id,
                 substs,
                 upvars,
-                interior,
+                movability,
             }
         }
 
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 0b6a1e3f52d..c27250267bb 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -18,7 +18,7 @@ use rustc::mir::{BinOp, BorrowKind, Field, Literal, UnOp};
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
 use rustc::ty::subst::Substs;
-use rustc::ty::{AdtDef, ClosureSubsts, Region, Ty, GeneratorInterior};
+use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty};
 use rustc::hir;
 use syntax::ast;
 use syntax_pos::Span;
@@ -266,9 +266,9 @@ pub enum ExprKind<'tcx> {
     },
     Closure {
         closure_id: DefId,
-        substs: ClosureSubsts<'tcx>,
+        substs: UpvarSubsts<'tcx>,
         upvars: Vec<ExprRef<'tcx>>,
-        interior: Option<(GeneratorInterior<'tcx>, hir::GeneratorMovability)>,
+        movability: Option<hir::GeneratorMovability>,
     },
     Literal {
         literal: Literal<'tcx>,
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 7b152bc1286..44f9542e733 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -18,7 +18,7 @@ use monomorphize::Instance;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::session::config::OptLevel;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
 use rustc::ty::subst::Substs;
 use syntax::ast;
 use syntax::attr::InlineAttr;
@@ -376,11 +376,11 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
                     self.push_type_name(sig.output(), output);
                 }
             },
-            ty::TyGenerator(def_id, ref closure_substs, _, _) |
-            ty::TyClosure(def_id, ref closure_substs) => {
+            ty::TyGenerator(def_id, GeneratorSubsts { ref substs }, _) |
+            ty::TyClosure(def_id, ClosureSubsts { ref substs }) => {
                 self.push_def_path(def_id, output);
                 let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
-                let substs = closure_substs.substs.truncate_to(self.tcx, generics);
+                let substs = substs.truncate_to(self.tcx, generics);
                 self.push_type_params(substs, iter::empty(), output);
             }
             ty::TyError |
diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs
index 020dce62c38..04d4f7a3968 100644
--- a/src/librustc_mir/monomorphize/mod.rs
+++ b/src/librustc_mir/monomorphize/mod.rs
@@ -84,8 +84,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
         .unwrap().def_id;
     let def = ty::InstanceDef::ClosureOnceShim { call_once };
 
-    let self_ty = tcx.mk_closure_from_closure_substs(
-        closure_did, substs);
+    let self_ty = tcx.mk_closure(closure_did, substs);
 
     let sig = substs.closure_sig(closure_did, tcx);
     let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index a86e077927c..699a5b17435 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -166,7 +166,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
 
     // Check if this is a generator, if so, return the drop glue for it
-    if let Some(&ty::TyS { sty: ty::TyGenerator(gen_def_id, substs, _, _), .. }) = ty {
+    if let Some(&ty::TyS { sty: ty::TyGenerator(gen_def_id, substs, _), .. }) = ty {
         let mir = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap();
         return mir.subst(tcx, substs.substs);
     }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 32d68962a0d..2bf5a49c97e 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -127,7 +127,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 &AggregateKind::Tuple |
                 &AggregateKind::Adt(..) => {}
                 &AggregateKind::Closure(def_id, _) |
-                &AggregateKind::Generator(def_id, _, _, _) => {
+                &AggregateKind::Generator(def_id, _, _) => {
                     let UnsafetyCheckResult {
                         violations, unsafe_blocks
                     } = self.tcx.unsafety_check_result(def_id);
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index dfa048e2e4b..cd5ebae2d9d 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -54,12 +54,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
         *substs = self.tcx.erase_regions(substs);
     }
 
-    fn visit_closure_substs(&mut self,
-                            substs: &mut ty::ClosureSubsts<'tcx>,
-                            _: Location) {
-        *substs = self.tcx.erase_regions(substs);
-    }
-
     fn visit_statement(&mut self,
                        block: BasicBlock,
                        statement: &mut Statement<'tcx>,
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 168f24f2cee..c4e700cdd1f 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -64,7 +64,7 @@ use rustc::hir::def_id::DefId;
 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::{self, TyCtxt, AdtDef, Ty};
 use rustc::ty::subst::Substs;
 use util::dump_mir;
 use util::liveness::{self, LivenessMode};
@@ -464,7 +464,7 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             source: MirSource,
                             upvars: Vec<Ty<'tcx>>,
-                            interior: GeneratorInterior<'tcx>,
+                            interior: Ty<'tcx>,
                             movable: bool,
                             mir: &mut Mir<'tcx>)
     -> (HashMap<Local, (Ty<'tcx>, usize)>,
@@ -479,7 +479,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Erase regions from the types passed in from typeck so we can compare them with
     // MIR types
     let allowed_upvars = tcx.erase_regions(&upvars);
-    let allowed = match interior.witness.sty {
+    let allowed = match interior.sty {
         ty::TyGeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
         _ => bug!(),
     };
@@ -855,9 +855,9 @@ impl MirPass for StateTransform {
 
         // Get the interior types and substs which typeck computed
         let (upvars, interior, movable) = match gen_ty.sty {
-            ty::TyGenerator(_, substs, interior, movability) => {
+            ty::TyGenerator(_, substs, movability) => {
                 (substs.upvar_tys(def_id, tcx).collect(),
-                 interior,
+                 substs.witness(def_id, tcx),
                  movability == hir::GeneratorMovability::Movable)
             }
             _ => bug!(),
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 1c04fe170a1..a641cf3d93e 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -780,14 +780,17 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
     fn open_drop<'a>(&mut self) -> BasicBlock {
         let ty = self.place_ty(self.place);
         match ty.sty {
-            ty::TyClosure(def_id, substs) |
+            ty::TyClosure(def_id, substs) => {
+                let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
+                self.open_drop_for_tuple(&tys)
+            }
             // Note that `elaborate_drops` only drops the upvars of a generator,
             // and this is ok because `open_drop` here can only be reached
             // within that own generator's resume function.
             // This should only happen for the self argument on the resume function.
             // It effetively only contains upvars until the generator transformation runs.
             // See librustc_mir/transform/generator.rs for more details.
-            ty::TyGenerator(def_id, substs, _, _) => {
+            ty::TyGenerator(def_id, substs, _) => {
                 let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
                 self.open_drop_for_tuple(&tys)
             }
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index ddee5558c0f..71012ca6d5f 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -418,11 +418,10 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
                     self.push(&format!("+ substs: {:#?}", substs));
                 }
 
-                AggregateKind::Generator(def_id, substs, interior, movability) => {
+                AggregateKind::Generator(def_id, substs, movability) => {
                     self.push(&format!("generator"));
                     self.push(&format!("+ def_id: {:?}", def_id));
                     self.push(&format!("+ substs: {:#?}", substs));
-                    self.push(&format!("+ interior: {:?}", interior));
                     self.push(&format!("+ movability: {:?}", movability));
                 }
 
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 8e4f82d2e1e..ce5707276ee 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -193,7 +193,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
 
-        ty::TyGenerator(def_id, substs, _interior, _movability) => {
+        ty::TyGenerator(def_id, substs, _movability) => {
             // rust-lang/rust#49918: types can be constructed, stored
             // in the interior, and sit idle when generator yields
             // (and is subsequently dropped).
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 004fb0f08f9..75b56be3c16 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -421,9 +421,9 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 sig.abi
             ))
         }
-        ty::TyGenerator(def_id, substs, _, _) => {
+        ty::TyGenerator(def_id, substs, _) => {
             let tcx = cx.tcx;
-            let sig = substs.generator_poly_sig(def_id, cx.tcx);
+            let sig = substs.poly_sig(def_id, cx.tcx);
 
             let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
             let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index a025057faaf..17a8196484f 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -591,7 +591,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                                    unique_type_id,
                                    usage_site_span).finalize(cx)
         }
-        ty::TyGenerator(def_id, substs, _, _) => {
+        ty::TyGenerator(def_id, substs,  _) => {
             let upvar_tys : Vec<_> = substs.field_tys(def_id, cx.tcx).map(|t| {
                 cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
             }).collect();
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index ab01984aa0f..599fca9ffdd 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -12,7 +12,7 @@ use common::{C_i32, C_null};
 use libc::c_uint;
 use llvm::{self, ValueRef, BasicBlockRef};
 use llvm::debuginfo::DIScope;
-use rustc::ty::{self, Ty, TypeFoldable};
+use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc::mir::{self, Mir};
 use rustc::ty::subst::Substs;
@@ -575,11 +575,12 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                 _ => (arg.layout, false)
             };
 
-            let upvar_tys = match closure_layout.ty.sty {
-                ty::TyClosure(def_id, substs) |
-                ty::TyGenerator(def_id, substs, _, _) => substs.upvar_tys(def_id, tcx),
+            let (def_id, upvar_substs) = match closure_layout.ty.sty {
+                ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
+                ty::TyGenerator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
                 _ => bug!("upvar_decls with non-closure arg0 type `{}`", closure_layout.ty)
             };
+            let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
 
             // Store the pointer to closure data in an alloca for debuginfo
             // because that's what the llvm.dbg.declare intrinsic expects.
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index cbe66746a29..94ef040d80a 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -113,23 +113,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     .next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span))
             },
         );
-        let substs = ty::ClosureSubsts { substs };
-        let closure_type = self.tcx.mk_closure(expr_def_id, substs);
-
         if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types {
+            let substs = ty::GeneratorSubsts { substs };
             self.demand_eqtype(
                 expr.span,
                 yield_ty,
-                substs.generator_yield_ty(expr_def_id, self.tcx),
+                substs.yield_ty(expr_def_id, self.tcx),
             );
             self.demand_eqtype(
                 expr.span,
                 liberated_sig.output(),
-                substs.generator_return_ty(expr_def_id, self.tcx),
+                substs.return_ty(expr_def_id, self.tcx),
             );
-            return self.tcx.mk_generator(expr_def_id, substs, interior, movability);
+            self.demand_eqtype(
+                expr.span,
+                interior,
+                substs.witness(expr_def_id, self.tcx),
+            );
+            return self.tcx.mk_generator(expr_def_id, substs, movability);
         }
 
+        let substs = ty::ClosureSubsts { substs };
+        let closure_type = self.tcx.mk_closure(expr_def_id, substs);
+
         debug!(
             "check_closure: expr.id={:?} closure_type={:?}",
             expr.id, closure_type
diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs
index 7bae5fe4fd1..b3d2a09a72c 100644
--- a/src/librustc_typeck/check/generator_interior.rs
+++ b/src/librustc_typeck/check/generator_interior.rs
@@ -17,7 +17,7 @@ use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::{self, Pat, PatKind, Expr};
 use rustc::middle::region;
-use rustc::ty::{self, Ty, GeneratorInterior};
+use rustc::ty::{self, Ty};
 use rustc_data_structures::sync::Lrc;
 use syntax_pos::Span;
 use super::FnCtxt;
@@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> {
 pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
                                         def_id: DefId,
                                         body_id: hir::BodyId,
-                                        interior: GeneratorInterior<'tcx>) {
+                                        interior: Ty<'tcx>) {
     let body = fcx.tcx.hir.body(body_id);
     let mut visitor = InteriorVisitor {
         fcx,
@@ -135,7 +135,7 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
             witness, body.value.span);
 
     // Unify the type variable inside the generator with the new witness
-    match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior.witness, witness) {
+    match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior, witness) {
         Ok(ok) => fcx.register_infer_ok_obligations(ok),
         _ => bug!(),
     }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 25c226e4591..0cc1b62e83e 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -208,7 +208,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
     deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
 
-    deferred_generator_interiors: RefCell<Vec<(hir::BodyId, ty::GeneratorInterior<'tcx>)>>,
+    deferred_generator_interiors: RefCell<Vec<(hir::BodyId, Ty<'tcx>)>>,
 
     // Anonymized types found in explicit return types and their
     // associated fresh inference variable. Writeback resolves these
@@ -1009,7 +1009,7 @@ struct GeneratorTypes<'tcx> {
     yield_ty: ty::Ty<'tcx>,
 
     /// Types that are captured (see `GeneratorInterior` for more).
-    interior: ty::GeneratorInterior<'tcx>,
+    interior: ty::Ty<'tcx>,
 
     /// Indicates if the generator is movable or static (immovable)
     movability: hir::GeneratorMovability,
@@ -1087,12 +1087,11 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     // This ensures that all nested generators appear before the entry of this generator.
     // resolve_generator_interiors relies on this property.
     let gen_ty = if can_be_generator.is_some() && body.is_generator {
-        let witness = fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span));
-        let interior = ty::GeneratorInterior { witness };
+        let interior = fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span));
         fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior));
         Some(GeneratorTypes {
             yield_ty: fcx.yield_ty.unwrap(),
-            interior: interior,
+            interior,
             movability: can_be_generator.unwrap(),
         })
     } else {
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 5008b5d79bf..6bede52b239 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -46,7 +46,7 @@ use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Categorization;
 use rustc::hir::def_id::DefId;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
 use rustc::infer::UpvarRegion;
 use syntax::ast;
 use syntax_pos::Span;
@@ -74,11 +74,11 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> {
 
     fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
         match expr.node {
-            hir::ExprClosure(cc, _, body_id, _, gen) => {
+            hir::ExprClosure(cc, _, body_id, _, _) => {
                 let body = self.fcx.tcx.hir.body(body_id);
                 self.visit_body(body);
                 self.fcx
-                    .analyze_closure(expr.id, expr.hir_id, expr.span, body, cc, gen);
+                    .analyze_closure(expr.id, expr.hir_id, expr.span, body, cc);
             }
 
             _ => {}
@@ -96,7 +96,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         span: Span,
         body: &hir::Body,
         capture_clause: hir::CaptureClause,
-        gen: Option<hir::GeneratorMovability>,
     ) {
         /*!
          * Analysis starting point.
@@ -109,9 +108,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         );
 
         // Extract the type of the closure.
-        let (closure_def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
-            ty::TyClosure(def_id, substs) |
-            ty::TyGenerator(def_id, substs, _, _) => (def_id, substs),
+        let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty {
+            ty::TyClosure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
+            ty::TyGenerator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
             ref t => {
                 span_bug!(
                     span,
@@ -122,10 +121,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
         };
 
-        let infer_kind = if gen.is_some() {
-            false
+        let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs{
+            if self.closure_kind(closure_def_id, closure_substs).is_none() {
+                Some(closure_substs)
+            } else {
+                None
+            }
         } else {
-            self.closure_kind(closure_def_id, closure_substs).is_none()
+            None
         };
 
         self.tcx.with_freevars(closure_node_id, |freevars| {
@@ -173,7 +176,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             &self.tables.borrow(),
         ).consume_body(body);
 
-        if infer_kind {
+        if let Some(closure_substs) = infer_kind {
             // Unify the (as yet unbound) type variable in the closure
             // substs with the kind we inferred.
             let inferred_kind = delegate.current_closure_kind;
@@ -209,14 +212,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // Equate the type variables for the upvars with the actual types.
         let final_upvar_tys = self.final_upvar_tys(closure_node_id);
         debug!(
-            "analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}",
+            "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}",
             closure_node_id,
-            closure_substs,
+            substs,
             final_upvar_tys
         );
-        for (upvar_ty, final_upvar_ty) in closure_substs
-            .upvar_tys(closure_def_id, self.tcx)
-            .zip(final_upvar_tys)
+        for (upvar_ty, final_upvar_ty) in substs.upvar_tys(closure_def_id, self.tcx)
+                                                .zip(final_upvar_tys)
         {
             self.demand_suptype(span, upvar_ty, final_upvar_ty);
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 1b8f2e661c3..f0f392a2458 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -933,38 +933,36 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // provide junk type parameter defs - the only place that
     // cares about anything but the length is instantiation,
     // and we don't do that for closures.
-    if let NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) = node {
-        // add a dummy parameter for the closure kind
-        types.push(ty::TypeParameterDef {
-            index: type_start,
-            name: Symbol::intern("<closure_kind>").as_interned_str(),
-            def_id,
-            has_default: false,
-            object_lifetime_default: rl::Set1::Empty,
-            pure_wrt_drop: false,
-            synthetic: None,
-        });
-
-        // add a dummy parameter for the closure signature
-        types.push(ty::TypeParameterDef {
-            index: type_start + 1,
-            name: Symbol::intern("<closure_signature>").as_interned_str(),
-            def_id,
-            has_default: false,
-            object_lifetime_default: rl::Set1::Empty,
-            pure_wrt_drop: false,
-            synthetic: None,
-        });
+    if let NodeExpr(&hir::Expr { node: hir::ExprClosure(.., gen), .. }) = node {
+        let dummy_args = if gen.is_some() {
+            &["<yield_ty>", "<return_ty>", "<witness>"][..]
+        } else {
+            &["<closure_kind>", "<closure_signature>"][..]
+        };
 
-        tcx.with_freevars(node_id, |fv| {
-            types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef {
-                index: type_start + i,
-                name: Symbol::intern("<upvar>").as_interned_str(),
+        for (i, &arg) in dummy_args.iter().enumerate() {
+            types.push(ty::TypeParameterDef {
+                index: type_start + i as u32,
+                name: Symbol::intern(arg).as_interned_str(),
                 def_id,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
                 pure_wrt_drop: false,
                 synthetic: None,
+            });
+        }
+
+        tcx.with_freevars(node_id, |fv| {
+            types.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
+                ty::TypeParameterDef {
+                    index: type_start + i,
+                    name: Symbol::intern("<upvar>").as_interned_str(),
+                    def_id,
+                    has_default: false,
+                    object_lifetime_default: rl::Set1::Empty,
+                    pure_wrt_drop: false,
+                    synthetic: None,
+                }
             }));
         });
     }