about summary refs log tree commit diff
diff options
context:
space:
mode:
authorcsmoe <csmoe@msn.com>2019-09-26 17:30:44 +0000
committercsmoe <csmoe@msn.com>2019-10-03 19:24:59 +0800
commit9b91bef78b15dfecc5144b0575f40a2d84ea795a (patch)
tree688ca27861a17a0ec4c8418383bc6cdcabfe356c
parent1f8e1d8aea495ec22fa33cefcfacbcb6ba3bad1d (diff)
downloadrust-9b91bef78b15dfecc5144b0575f40a2d84ea795a.tar.gz
rust-9b91bef78b15dfecc5144b0575f40a2d84ea795a.zip
generate ClosureSubsts from SubstsRef
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs4
-rw-r--r--src/librustc/infer/mod.rs8
-rw-r--r--src/librustc/infer/opaque_types/mod.rs4
-rw-r--r--src/librustc/middle/mem_categorization.rs11
-rw-r--r--src/librustc/mir/mod.rs4
-rw-r--r--src/librustc/mir/tcx.rs2
-rw-r--r--src/librustc/mir/visit.rs14
-rw-r--r--src/librustc/traits/mod.rs2
-rw-r--r--src/librustc/traits/project.rs3
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs1
-rw-r--r--src/librustc/traits/select.rs24
-rw-r--r--src/librustc/ty/instance.rs12
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/mod.rs4
-rw-r--r--src/librustc/ty/outlives.rs2
-rw-r--r--src/librustc/ty/print/obsolete.rs9
-rw-r--r--src/librustc/ty/print/pretty.rs6
-rw-r--r--src/librustc/ty/sty.rs33
-rw-r--r--src/librustc/ty/subst.rs78
-rw-r--r--src/librustc/ty/util.rs6
-rw-r--r--src/librustc/ty/wf.rs2
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs4
-rw-r--r--src/librustc_codegen_ssa/mir/mod.rs2
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs5
-rw-r--r--src/librustc_metadata/encoder.rs2
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs3
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs9
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/renumber.rs14
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs12
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs19
-rw-r--r--src/librustc_mir/hair/cx/expr.rs5
-rw-r--r--src/librustc_mir/interpret/cast.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs2
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs2
-rw-r--r--src/librustc_traits/chalk_context/program_clauses/builtin.rs5
-rw-r--r--src/librustc_traits/dropck_outlives.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs4
-rw-r--r--src/librustc_typeck/check/closure.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs7
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/check/upvar.rs9
-rw-r--r--src/librustc_typeck/collect.rs2
45 files changed, 139 insertions, 216 deletions
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 3e4dfccf34d..b89731273f7 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -220,7 +220,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         let ty_msg = match local_visitor.found_ty {
             Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => {
-                let fn_sig = ty::ClosureSubsts::from_ref(substs).closure_sig(*def_id, self.tcx);
+                let fn_sig = substs.as_closure().sig(*def_id, self.tcx);
                 let args = closure_args(&fn_sig);
                 let ret = fn_sig.output().skip_binder().to_string();
                 format!(" for the closure `fn({}) -> {}`", args, ret)
@@ -255,7 +255,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         let suffix = match local_visitor.found_ty {
             Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => {
-                let fn_sig = substs.closure_sig(*def_id, self.tcx);
+                let fn_sig = substs.as_closure().sig(*def_id, self.tcx);
                 let ret = fn_sig.output().skip_binder().to_string();
 
                 if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure {
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 750ca4e32a6..c918df18b2d 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1481,9 +1481,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn closure_kind(
         &self,
         closure_def_id: DefId,
-        closure_substs: ty::ClosureSubsts<'tcx>,
+        closure_substs: SubstsRef<'tcx>,
     ) -> Option<ty::ClosureKind> {
-        let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
+        let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self.tcx);
         let closure_kind_ty = self.shallow_resolve(closure_kind_ty);
         closure_kind_ty.to_opt_closure_kind()
     }
@@ -1495,9 +1495,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn closure_sig(
         &self,
         def_id: DefId,
-        substs: ty::ClosureSubsts<'tcx>,
+        substs: SubstsRef<'tcx>,
     ) -> ty::PolyFnSig<'tcx> {
-        let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx);
+        let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx);
         let closure_sig_ty = self.shallow_resolve(closure_sig_ty);
         closure_sig_ty.fn_sig(self.tcx)
     }
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 8cc7dbb3c5c..e7205dd47a6 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -722,11 +722,11 @@ where
             ty::Closure(def_id, ref substs) => {
                 // Skip lifetime parameters of the enclosing item(s)
 
-                for upvar_ty in ty::ClosureSubsts::from_ref(substs).upvar_tys(def_id, self.tcx) {
+                for upvar_ty in substs.as_closure().upvar_tys(def_id, self.tcx) {
                     upvar_ty.visit_with(self);
                 }
 
-                substs.closure_sig_ty(def_id, self.tcx).visit_with(self);
+                substs.as_closure().sig_ty(def_id, self.tcx).visit_with(self);
             }
 
             ty::Generator(def_id, ref substs, _) => {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 522c0e55b85..355bf97e6ed 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -740,17 +740,18 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         let ty = self.node_ty(fn_hir_id)?;
         let kind = match ty.kind {
             ty::Generator(..) => ty::ClosureKind::FnOnce,
-            ty::Closure(closure_def_id, closure_substs) => {
+            ty::Closure(closure_def_id, substs) => {
                 match self.infcx {
                     // During upvar inference we may not know the
                     // closure kind, just use the LATTICE_BOTTOM value.
                     Some(infcx) =>
-                        infcx.closure_kind(closure_def_id,
-                            ty::ClosureSubsts::from_ref(closure_substs))
-                             .unwrap_or(ty::ClosureKind::LATTICE_BOTTOM),
+                        infcx.closure_kind(
+                            closure_def_id,
+                            substs
+                        ).unwrap_or(ty::ClosureKind::LATTICE_BOTTOM),
 
                     None =>
-                        closure_substs.closure_kind(closure_def_id, self.tcx),
+                        substs.as_closure().kind(closure_def_id, self.tcx),
                 }
             }
             _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty),
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 5e12c4dfe75..74a042d606e 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -15,7 +15,7 @@ use crate::ty::layout::VariantIdx;
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::subst::{Subst, SubstsRef};
 use crate::ty::{
-    self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt,
+    self, AdtDef, CanonicalUserTypeAnnotations, GeneratorSubsts, Region, Ty, TyCtxt,
     UserTypeAnnotationIndex,
 };
 
@@ -2188,7 +2188,7 @@ pub enum AggregateKind<'tcx> {
     /// active field index would identity the field `c`
     Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
 
-    Closure(DefId, ClosureSubsts<'tcx>),
+    Closure(DefId, SubstsRef<'tcx>),
     Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
 }
 
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 44829f670fa..26f718e858d 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -218,7 +218,7 @@ impl<'tcx> Rvalue<'tcx> {
                         tcx.type_of(def.did).subst(tcx, substs)
                     }
                     AggregateKind::Closure(did, substs) => {
-                        tcx.mk_closure(did, &substs.substs)
+                        tcx.mk_closure(did, substs)
                     }
                     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 1e3b9eb29c7..8e68952fc70 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -1,5 +1,5 @@
 use crate::ty::subst::SubstsRef;
-use crate::ty::{CanonicalUserTypeAnnotation, ClosureSubsts, GeneratorSubsts, Ty};
+use crate::ty::{CanonicalUserTypeAnnotation, GeneratorSubsts, Ty};
 use crate::mir::*;
 use syntax_pos::Span;
 
@@ -221,12 +221,6 @@ macro_rules! make_mir_visitor {
                 self.super_substs(substs);
             }
 
-            fn visit_closure_substs(&mut self,
-                                    substs: & $($mutability)? ClosureSubsts<'tcx>,
-                                    _: Location) {
-                self.super_closure_substs(substs);
-            }
-
             fn visit_generator_substs(&mut self,
                                       substs: & $($mutability)? GeneratorSubsts<'tcx>,
                                     _: Location) {
@@ -618,7 +612,7 @@ macro_rules! make_mir_visitor {
                                 _,
                                 closure_substs
                             ) => {
-                                self.visit_closure_substs(closure_substs, location);
+                                self.visit_substs(closure_substs, location);
                             }
                             AggregateKind::Generator(
                                 _,
@@ -838,10 +832,6 @@ macro_rules! make_mir_visitor {
                                       _substs: & $($mutability)? GeneratorSubsts<'tcx>) {
             }
 
-            fn super_closure_substs(&mut self,
-                                    _substs: & $($mutability)? ClosureSubsts<'tcx>) {
-            }
-
             // Convenience methods
 
             fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) {
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index accbbe3643e..7f194c2fbbc 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -619,7 +619,7 @@ pub struct VtableGeneratorData<'tcx, N> {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
 pub struct VtableClosureData<'tcx, N> {
     pub closure_def_id: DefId,
-    pub substs: ty::ClosureSubsts<'tcx>,
+    pub substs: SubstsRef<'tcx>,
     /// Nested obligations. This can be non-empty if the closure
     /// signature contains associated types.
     pub nested: Vec<N>
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 57077bcdffa..a7bb29c699e 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1334,7 +1334,8 @@ fn confirm_closure_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     let tcx = selcx.tcx();
     let infcx = selcx.infcx();
-    let closure_sig_ty = vtable.substs.closure_sig_ty(vtable.closure_def_id, tcx);
+    let closure_sig_ty = vtable.substs
+        .as_closure().sig_ty(vtable.closure_def_id, tcx);
     let closure_sig = infcx.shallow_resolve(closure_sig_ty).fn_sig(tcx);
     let Normalized {
         value: closure_sig,
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index aa30541610e..eaf5971e459 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -213,6 +213,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         // check if *any* of those are trivial.
         ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
         ty::Closure(def_id, ref substs) => substs
+            .as_closure()
             .upvar_tys(def_id, tcx)
             .all(|t| trivial_dropck_outlives(tcx, t)),
 
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 3450f3fc865..9434412b020 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2051,8 +2051,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     "assemble_unboxed_candidates: kind={:?} obligation={:?}",
                     kind, obligation
                 );
-                match self.infcx.closure_kind(closure_def_id,
-                    ty::ClosureSubsts::from_ref(closure_substs)) {
+                match self.infcx.closure_kind(
+                    closure_def_id,
+                    closure_substs
+                ) {
                     Some(closure_kind) => {
                         debug!(
                             "assemble_unboxed_candidates: closure_kind = {:?}",
@@ -2670,7 +2672,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::Closure(def_id, substs) => {
                 // (*) binder moved here
                 Where(ty::Binder::bind(
-                    substs.upvar_tys(def_id, self.tcx()).collect(),
+                    substs.as_closure().upvar_tys(def_id, self.tcx()).collect(),
                 ))
             }
 
@@ -2754,7 +2756,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 tys.iter().map(|k| k.expect_ty()).collect()
             }
 
-            ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, self.tcx()).collect(),
+            ty::Closure(def_id, ref substs) => substs.as_closure()
+                .upvar_tys(def_id, self.tcx())
+                .collect(),
 
             ty::Generator(def_id, ref substs, _) => {
                 let witness = substs.witness(def_id, self.tcx());
@@ -3376,14 +3380,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             obligations.push(Obligation::new(
                 obligation.cause.clone(),
                 obligation.param_env,
-                ty::Predicate::ClosureKind(closure_def_id,
-                    ty::ClosureSubsts::from_ref(substs.clone()), kind),
+                ty::Predicate::ClosureKind(
+                    closure_def_id,
+                    substs,
+                    kind
+                ),
             ));
         }
 
         Ok(VtableClosureData {
             closure_def_id,
-            substs: ty::ClosureSubsts::from_ref(substs),
+            substs: substs,
             nested: obligations,
         })
     }
@@ -3878,8 +3885,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",
             obligation, closure_def_id, substs,
         );
-        let closure_type = self.infcx.closure_sig(closure_def_id,
-            ty::ClosureSubsts::from_ref(substs));
+        let closure_type = self.infcx.closure_sig(closure_def_id, substs);
 
         debug!(
             "closure_trait_ref_unnormalized: closure_type = {:?}",
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index c0cd1fd0614..34f806b15c0 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -59,7 +59,7 @@ impl<'tcx> Instance<'tcx> {
             // Shims currently have type FnPtr. Not sure this should remain.
             ty::FnPtr(_) => ty.fn_sig(tcx),
             ty::Closure(def_id, substs) => {
-                let sig = substs.closure_sig(def_id, tcx);
+                let sig = substs.as_closure().sig(def_id, tcx);
 
                 let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
                 sig.map_bound(|sig| tcx.mk_fn_sig(
@@ -315,14 +315,14 @@ impl<'tcx> Instance<'tcx> {
     pub fn resolve_closure(
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        substs: ty::ClosureSubsts<'tcx>,
+        substs: ty::SubstsRef<'tcx>,
         requested_kind: ty::ClosureKind,
     ) -> Instance<'tcx> {
-        let actual_kind = substs.closure_kind(def_id, tcx);
+        let actual_kind = substs.as_closure().kind(def_id, tcx);
 
         match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
-            Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs.substs),
-            _ => Instance::new(def_id, substs.substs)
+            Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs),
+            _ => Instance::new(def_id, substs)
         }
     }
 
@@ -348,7 +348,7 @@ impl<'tcx> Instance<'tcx> {
 
         let self_ty = tcx.mk_closure(closure_did, substs);
 
-        let sig = substs.closure_sig(closure_did, tcx);
+        let sig = substs.as_closure().sig(closure_did, tcx);
         let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
         assert_eq!(sig.inputs().len(), 1);
         let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 6ab4f4c6112..d142aaeaf83 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -674,7 +674,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, &substs)?,
 
             ty::Closure(def_id, ref substs) => {
-                let tys = substs.upvar_tys(def_id, tcx);
+                let tys = substs.as_closure().upvar_tys(def_id, tcx);
                 univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
                     &ReprOptions::default(),
                     StructKind::AlwaysSized)?
@@ -2147,7 +2147,7 @@ where
 
             // Tuples, generators and closures.
             ty::Closure(def_id, ref substs) => {
-                substs.upvar_tys(def_id, tcx).nth(i).unwrap()
+                substs.as_closure().upvar_tys(def_id, tcx).nth(i).unwrap()
             }
 
             ty::Generator(def_id, ref substs, _) => {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 731aca854a4..20c18c14ead 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1110,7 +1110,7 @@ pub enum Predicate<'tcx> {
     /// No direct syntax. May be thought of as `where T: FnFoo<...>`
     /// for some substitutions `...` and `T` being a closure type.
     /// Satisfied (or refuted) once we know the closure's kind.
-    ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind),
+    ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind),
 
     /// `T1 <: T2`
     Subtype(PolySubtypePredicate<'tcx>),
@@ -1457,7 +1457,7 @@ impl<'tcx> Predicate<'tcx> {
                 WalkTysIter::None
             }
             ty::Predicate::ClosureKind(_closure_def_id, closure_substs, _kind) => {
-                WalkTysIter::Types(closure_substs.substs.types())
+                WalkTysIter::Types(closure_substs.types())
             }
             ty::Predicate::ConstEvaluatable(_, substs) => {
                 WalkTysIter::Types(substs.types())
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 9a2e30f7f45..3ea767d5115 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -62,7 +62,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // projection).
         match ty.kind {
             ty::Closure(def_id, ref substs) => {
-                for upvar_ty in substs.upvar_tys(def_id, *self) {
+                for upvar_ty in substs.as_closure().upvar_tys(def_id, *self) {
                     self.compute_components(upvar_ty, out);
                 }
             }
diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs
index 6f97006c71e..21c018d9ee6 100644
--- a/src/librustc/ty/print/obsolete.rs
+++ b/src/librustc/ty/print/obsolete.rs
@@ -154,13 +154,8 @@ impl DefPathBasedNames<'tcx> {
                     self.push_type_name(sig.output(), output, debug);
                 }
             }
-            ty::Generator(def_id, GeneratorSubsts { 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 = substs.truncate_to(self.tcx, generics);
-                self.push_generic_params(substs, iter::empty(), output, debug);
-            }
-            ty::Closure(def_id, substs) => {
+            ty::Generator(def_id, GeneratorSubsts { substs }, _)
+            | ty::Closure(def_id, substs) => {
                 self.push_def_path(def_id, output);
                 let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
                 let substs = substs.truncate_to(self.tcx, generics);
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 0adb7562697..ad4be788dae 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -649,7 +649,7 @@ pub trait PrettyPrinter<'tcx>:
                 p!(in_binder(&types));
             }
             ty::Closure(did, substs) => {
-                let upvar_tys = substs.upvar_tys(did, self.tcx());
+                let upvar_tys = substs.as_closure().upvar_tys(did, self.tcx());
                 p!(write("[closure"));
 
                 // FIXME(eddyb) should use `def_span`.
@@ -689,8 +689,8 @@ pub trait PrettyPrinter<'tcx>:
                 if self.tcx().sess.verbose() {
                     p!(write(
                         " closure_kind_ty={:?} closure_sig_ty={:?}",
-                        substs.closure_kind_ty(did, self.tcx()),
-                        substs.closure_sig_ty(did, self.tcx())
+                        substs.as_closure().kind(did, self.tcx()),
+                        substs.as_closure().sig_ty(did, self.tcx())
                     ));
                 }
 
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 05c6ec6f97a..c3c48c4d876 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -304,8 +304,8 @@ static_assert_size!(TyKind<'_>, 24);
 /// 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.
@@ -317,18 +317,13 @@ pub struct ClosureSubsts<'tcx> {
 
 /// Struct returned by `split()`. Note that these are subslices of the
 /// parent slice and not canonical substs themselves.
-pub(crate) struct SplitClosureSubsts<'tcx> {
-    pub(crate) closure_kind_ty: Ty<'tcx>,
-    pub(crate) closure_sig_ty: Ty<'tcx>,
-    pub(crate) upvar_kinds: &'tcx [GenericArg<'tcx>],
+struct SplitClosureSubsts<'tcx> {
+    closure_kind_ty: Ty<'tcx>,
+    closure_sig_ty: Ty<'tcx>,
+    upvar_kinds: &'tcx [GenericArg<'tcx>],
 }
 
 impl<'tcx> ClosureSubsts<'tcx> {
-    // FIXME(csmoe): remove this method once the migration is done.
-    pub fn from_ref(substs: SubstsRef<'tcx>) -> Self {
-        Self { substs }
-    }
-
     /// Divides the closure substs into their respective
     /// components. Single source of truth with respect to the
     /// ordering.
@@ -361,7 +356,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// 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
     }
 
@@ -369,7 +364,7 @@ impl<'tcx> ClosureSubsts<'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
     }
 
@@ -378,7 +373,7 @@ impl<'tcx> ClosureSubsts<'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()
     }
 
@@ -387,8 +382,8 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// 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);
+    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.kind),
@@ -573,7 +568,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
 
 #[derive(Debug, Copy, Clone)]
 pub enum UpvarSubsts<'tcx> {
-    Closure(ClosureSubsts<'tcx>),
+    Closure(SubstsRef<'tcx>),
     Generator(GeneratorSubsts<'tcx>),
 }
 
@@ -582,10 +577,10 @@ 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| {
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 05042ccf9a1..537192b0a2e 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -5,7 +5,7 @@ use crate::infer::canonical::Canonical;
 use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::mir::interpret::ConstValue;
-use crate::ty::sty::SplitClosureSubsts;
+use crate::ty::sty::ClosureSubsts;
 
 use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder};
 use syntax_pos::{Span, DUMMY_SP};
@@ -184,6 +184,16 @@ pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
 pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
 
 impl<'a, 'tcx> InternalSubsts<'tcx> {
+    /// Interpret these substitutions as the substitutions of a closure type.
+    /// Closure substitutions have a particular structure controlled by the
+    /// compiler that encodes information like the signature and closure kind;
+    /// see `ty::ClosureSubsts` struct for more comments.
+    pub fn as_closure(&'a self) -> ClosureSubsts<'a> {
+        ClosureSubsts {
+            substs: self,
+        }
+    }
+
     /// Creates a `InternalSubsts` that maps each generic parameter to itself.
     pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
         Self::for_item(tcx, def_id, |param, _| {
@@ -380,72 +390,6 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
     pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> {
         tcx.mk_substs(self.iter().take(generics.count()).cloned())
     }
-
-    /// Divides the closure substs into their respective
-    /// components. Single source of truth with respect to the
-    /// ordering.
-    fn split(&self, def_id: DefId, tcx: TyCtxt<'_>) -> SplitClosureSubsts<'_> {
-        let generics = tcx.generics_of(def_id);
-        let parent_len = generics.parent_count;
-        SplitClosureSubsts {
-            closure_kind_ty: self.type_at(parent_len),
-            closure_sig_ty: self.type_at(parent_len + 1),
-            upvar_kinds: &self[parent_len + 2..],
-        }
-    }
-
-    #[inline]
-    pub fn upvar_tys(
-        &'a self,
-        def_id: DefId,
-        tcx: TyCtxt<'_>,
-    ) -> impl Iterator<Item = Ty<'a>> + 'a {
-        let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
-        upvar_kinds.iter().map(|t| {
-            if let GenericArgKind::Type(ty) = t.unpack() {
-                ty
-            } else {
-                bug!("upvar should be type")
-            }
-        })
-    }
-
-    /// 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(&'a self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'a> {
-        self.split(def_id, tcx).closure_kind_ty
-    }
-
-    /// Returns the type representing the closure signature for this
-    /// 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(&'a self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'a> {
-        self.split(def_id, tcx).closure_sig_ty
-    }
-
-    /// 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.
-    ///
-    /// If you have an inference context, use `infcx.closure_kind()`.
-    pub fn closure_kind(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
-        self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
-    }
-
-    /// Extracts the signature from the closure; only usable outside
-    /// of an inference context, because in that context we know that
-    /// there are no type variables.
-    ///
-    /// If you have an inference context, use `infcx.closure_sig()`.
-    pub fn closure_sig(&'a self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'a> {
-        let ty = self.closure_sig_ty(def_id, tcx);
-        match ty.kind {
-            ty::FnPtr(sig) => sig,
-            _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind),
-        }
-    }
 }
 
 impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 05f0d164cc1..d0e95a18c59 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -647,7 +647,7 @@ impl<'tcx> TyCtxt<'tcx> {
     {
         let closure_ty = self.mk_closure(closure_def_id, closure_substs);
         let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
-        let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self);
+        let closure_kind_ty = closure_substs.as_closure().kind_ty(closure_def_id, self);
         let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
         let env_ty = match closure_kind {
             ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
@@ -1108,7 +1108,9 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
         // Structural recursion.
         ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
 
-        ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop),
+        ty::Closure(def_id, ref substs) => {
+            substs.as_closure().upvar_tys(def_id, tcx).any(needs_drop)
+        }
 
         // Pessimistically assume that all generators will require destructors
         // as we don't know if a destructor is a noop or not until after the MIR
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 020926e7c8d..ecb075e30b1 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -347,7 +347,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     // anyway, except via auto trait matching (which
                     // only inspects the upvar types).
                     subtys.skip_current_subtree(); // subtree handled by compute_projection
-                    for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
+                    for upvar_ty in substs.as_closure().upvar_tys(def_id, self.infcx.tcx) {
                         self.compute(upvar_ty);
                     }
                 }
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 544d6794e21..e69f4b6aca1 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -6,7 +6,7 @@ use super::utils::{debug_context, DIB, span_start,
                    get_namespace_for_item, create_DIArray, is_node_local_to_unit};
 use super::namespace::mangled_name_of_instance;
 use super::type_names::compute_debuginfo_type_name;
-use super::{CrateDebugContext};
+use super::CrateDebugContext;
 use crate::abi;
 use crate::value::Value;
 use rustc_codegen_ssa::traits::*;
@@ -682,7 +682,7 @@ pub fn type_metadata(
 
         }
         ty::Closure(def_id, substs) => {
-            let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect();
+            let upvar_tys : Vec<_> = substs.as_closure().upvar_tys(def_id, cx.tcx).collect();
             let containing_scope = get_namespace_for_item(cx, def_id);
             prepare_tuple_metadata(cx,
                                    t,
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 30d519c8733..378bbd0cc38 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -616,7 +616,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
             let (def_id, upvar_substs) = match closure_layout.ty.kind {
                 ty::Closure(def_id, substs) => (def_id,
-                    UpvarSubsts::Closure(rustc::ty::ClosureSubsts::from_ref(substs))),
+                    UpvarSubsts::Closure(substs)),
                 ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
                 _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
             };
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 9cc21a28b27..6ffa561f3fe 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -201,8 +201,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         match operand.layout.ty.kind {
                             ty::Closure(def_id, substs) => {
                                 let instance = Instance::resolve_closure(
-                                    bx.cx().tcx(), def_id,
-                                    rustc::ty::ClosureSubsts::from_ref(substs),
+                                    bx.cx().tcx(),
+                                    def_id,
+                                    substs,
                                     ty::ClosureKind::FnOnce);
                                 OperandValue::Immediate(bx.cx().get_fn(instance))
                             }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 9beeacbe72d..598f7dcf17d 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1437,7 +1437,7 @@ impl EncodeContext<'tcx> {
             }
 
             ty::Closure(def_id, substs) => {
-                let sig = substs.closure_sig(def_id, self.tcx);
+                let sig = substs.as_closure().sig(def_id, self.tcx);
                 let data = ClosureData { sig: self.lazy(sig) };
                 EntryKind::Closure(self.lazy(data))
             }
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index bf5bddadd16..431361fa5a8 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -341,7 +341,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             ty::Closure(def_id, closure_substs)
                 if def_id == self.mir_def_id && upvar_field.is_some()
             => {
-                let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.infcx.tcx);
+                let closure_kind_ty = closure_substs
+                    .as_closure().kind_ty(def_id, self.infcx.tcx);
                 let closure_kind = closure_kind_ty.to_opt_closure_kind();
                 let capture_description = match closure_kind {
                     Some(ty::ClosureKind::Fn) => {
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 1e5f613aedc..0e22ead62d1 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -12,7 +12,7 @@ use rustc::mir::{
     SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
 };
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
+use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty};
 use rustc::ty::subst::SubstsRef;
 
 pub(super) fn generate_constraints<'cx, 'tcx>(
@@ -98,13 +98,6 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
         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) {
-        self.add_regular_live_constraint(*substs, location);
-        self.super_closure_substs(substs);
-    }
-
     fn visit_statement(
         &mut self,
         statement: &Statement<'tcx>,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index e29e9232012..a386d15c942 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -800,7 +800,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
             if let ty::BoundRegion::BrEnv = free_region.bound_region {
                 if let DefiningTy::Closure(def_id, substs) = self.universal_regions.defining_ty {
-                    let closure_kind_ty = substs.closure_kind_ty(def_id, infcx.tcx);
+                    let closure_kind_ty = substs.as_closure().kind_ty(def_id, infcx.tcx);
                     return Some(ty::ClosureKind::FnMut) == closure_kind_ty.to_opt_closure_kind();
                 }
             }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
index 8b1ba59c6df..6fb976e0d84 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
@@ -300,7 +300,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         };
                         let region_name = self.synthesize_region_name(renctx);
 
-                        let closure_kind_ty = substs.closure_kind_ty(def_id, tcx);
+                        let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx);
                         let note = match closure_kind_ty.to_opt_closure_kind() {
                             Some(ty::ClosureKind::Fn) => {
                                 "closure implements `Fn`, so references to captured variables \
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index c479c38f30c..48c08da7698 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -1,5 +1,5 @@
 use rustc::ty::subst::SubstsRef;
-use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
+use rustc::ty::{self, GeneratorSubsts, Ty, TypeFoldable};
 use rustc::mir::{Location, Body, Promoted};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -96,16 +96,4 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
 
         debug!("visit_generator_substs: substs={:?}", substs);
     }
-
-    fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
-        debug!(
-            "visit_closure_substs(substs={:?}, location={:?})",
-            substs,
-            location
-        );
-
-        *substs = self.renumber_regions(substs);
-
-        debug!("visit_closure_substs: substs={:?}", substs);
-    }
 }
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 fa326062fe2..698dd6d6522 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -763,10 +763,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 ty::Adt(adt_def, substs) if !adt_def.is_enum() =>
                     (&adt_def.variants[VariantIdx::new(0)], substs),
                 ty::Closure(def_id, substs) => {
-                    return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
+                    return match substs.as_closure().upvar_tys(def_id, tcx).nth(field.index()) {
                         Some(ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
-                            field_count: substs.upvar_tys(def_id, tcx).count(),
+                            field_count: substs.as_closure().upvar_tys(def_id, tcx).count(),
                         }),
                     }
                 }
@@ -1934,10 +1934,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
             AggregateKind::Closure(def_id, substs) => {
-                match substs.upvar_tys(def_id, tcx).nth(field_index) {
+                match substs.as_closure().upvar_tys(def_id, tcx).nth(field_index) {
                     Some(ty) => Ok(ty),
                     None => Err(FieldAccessError::OutOfRange {
-                        field_count: substs.upvar_tys(def_id, tcx).count(),
+                        field_count: substs.as_closure().upvar_tys(def_id, tcx).count(),
                     }),
                 }
             }
@@ -2050,7 +2050,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
                         let sig = match op.ty(body, tcx).kind {
                             ty::Closure(def_id, substs) => {
-                                substs.closure_sig_ty(def_id, tcx).fn_sig(tcx)
+                                substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx)
                             }
                             _ => bug!(),
                         };
@@ -2522,7 +2522,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             // desugaring. A closure gets desugared to a struct, and
             // these extra requirements are basically like where
             // clauses on the struct.
-            AggregateKind::Closure(def_id, ty::ClosureSubsts { substs })
+            AggregateKind::Closure(def_id, substs)
             | AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
                 self.prove_closure_bounds(tcx, *def_id, substs, location)
             }
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 80ed90ede4d..1fa19a2f9f0 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -19,7 +19,7 @@ use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 use rustc::middle::lang_items;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::{InternalSubsts, SubstsRef, Subst};
-use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty, TyCtxt};
+use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty, TyCtxt};
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_errors::DiagnosticBuilder;
@@ -85,7 +85,7 @@ pub struct UniversalRegions<'tcx> {
 pub enum DefiningTy<'tcx> {
     /// The MIR is a closure. The signature is found via
     /// `ClosureSubsts::closure_sig_ty`.
-    Closure(DefId, ty::ClosureSubsts<'tcx>),
+    Closure(DefId, SubstsRef<'tcx>),
 
     /// The MIR is a generator. The signature is that generators take
     /// no parameters and return the result of
@@ -109,7 +109,9 @@ impl<'tcx> DefiningTy<'tcx> {
     /// match up with the upvar order in the HIR, typesystem, and MIR.
     pub fn upvar_tys(self, tcx: TyCtxt<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
         match self {
-            DefiningTy::Closure(def_id, substs) => Either::Left(substs.upvar_tys(def_id, tcx)),
+            DefiningTy::Closure(def_id, substs) => Either::Left(
+                substs.as_closure().upvar_tys(def_id, tcx)
+            ),
             DefiningTy::Generator(def_id, substs, _) => {
                 Either::Right(Either::Left(substs.upvar_tys(def_id, tcx)))
             }
@@ -312,7 +314,7 @@ impl<'tcx> UniversalRegions<'tcx> {
                 err.note(&format!(
                     "defining type: {:?} with closure substs {:#?}",
                     def_id,
-                    &substs.substs[..]
+                    &substs[..]
                 ));
 
                 // FIXME: It'd be nice to print the late-bound regions
@@ -509,8 +511,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     .replace_free_regions_with_nll_infer_vars(FR, &defining_ty);
 
                 match defining_ty.kind {
-                    ty::Closure(def_id, substs) => DefiningTy::Closure(def_id,
-                        rustc::ty::ClosureSubsts::from_ref(substs)),
+                    ty::Closure(def_id, substs) => DefiningTy::Closure(def_id, substs),
                     ty::Generator(def_id, substs, movability) => {
                         DefiningTy::Generator(def_id, substs, movability)
                     }
@@ -547,7 +548,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
         let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
         let fr_substs = match defining_ty {
-            DefiningTy::Closure(_, ClosureSubsts { ref substs })
+            DefiningTy::Closure(_, 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
@@ -583,9 +584,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         match defining_ty {
             DefiningTy::Closure(def_id, substs) => {
                 assert_eq!(self.mir_def_id, def_id);
-                let closure_sig = substs.closure_sig_ty(def_id, tcx).fn_sig(tcx);
+                let closure_sig = substs.as_closure().sig_ty(def_id, tcx).fn_sig(tcx);
                 let inputs_and_output = closure_sig.inputs_and_output();
-                let closure_ty = tcx.closure_env_ty(def_id, substs.substs).unwrap();
+                let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap();
                 ty::Binder::fuse(
                     closure_ty,
                     inputs_and_output,
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index e4d26bda40f..461cc063a47 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -507,7 +507,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
             let closure_ty = cx.tables().expr_ty(expr);
             let (def_id, substs, movability) = match closure_ty.kind {
                 ty::Closure(def_id, substs) => (def_id,
-                    UpvarSubsts::Closure(rustc::ty::ClosureSubsts::from_ref(substs)), None),
+                    UpvarSubsts::Closure(substs), None),
                 ty::Generator(def_id, substs, movability) => {
                     (def_id, UpvarSubsts::Generator(substs), Some(movability))
                 }
@@ -1003,8 +1003,7 @@ fn convert_var(
             let region = cx.tcx.mk_region(region);
 
             let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.kind {
-                match cx.infcx.closure_kind(closure_def_id,
-                    rustc::ty::ClosureSubsts::from_ref(closure_substs)).unwrap() {
+                match cx.infcx.closure_kind(closure_def_id, closure_substs).unwrap() {
                     ty::ClosureKind::Fn => {
                         let ref_closure_ty = cx.tcx.mk_ref(region,
                                                            ty::TypeAndMut {
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 943054cc696..d120412c901 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -75,7 +75,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         let instance = ty::Instance::resolve_closure(
                             *self.tcx,
                             def_id,
-                            rustc::ty::ClosureSubsts::from_ref(substs),
+                            substs,
                             ty::ClosureKind::FnOnce,
                         );
                         let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 21aea5593ee..79403e3a7e8 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -582,7 +582,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                     ty::Closure(def_id, substs) => {
                         let instance = Instance::resolve_closure(
                             self.tcx, def_id,
-                            rustc::ty::ClosureSubsts::from_ref(substs), ty::ClosureKind::FnOnce);
+                            substs, ty::ClosureKind::FnOnce);
                         if should_monomorphize_locally(self.tcx, &instance) {
                             self.output.push(create_fn_mono_item(instance));
                         }
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 4fae0976ffb..28ff1e59d5b 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -320,7 +320,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
         ty::Closure(def_id, substs) => {
             builder.tuple_like_shim(
                 dest, src,
-                substs.upvar_tys(def_id, tcx)
+                substs.as_closure().upvar_tys(def_id, tcx)
             )
         }
         ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index e1015edfa8e..0f7199f1c4e 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -788,7 +788,7 @@ where
         let ty = self.place_ty(self.place);
         match ty.kind {
             ty::Closure(def_id, substs) => {
-                let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
+                let tys : Vec<_> = substs.as_closure().upvar_tys(def_id, self.tcx()).collect();
                 self.open_drop_for_tuple(&tys)
             }
             // Note that `elaborate_drops` only drops the upvars of a generator,
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
index 6790f14f69b..13bbe021ccf 100644
--- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
@@ -266,7 +266,10 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>(
             let closure_ty = generic_types::closure(tcx, def_id);
             let upvar_tys: Vec<_> = match &closure_ty.kind {
                 ty::Closure(_, substs) => {
-                    substs.upvar_tys(def_id, tcx).map(|ty| GenericArg::from(ty)).collect()
+                    substs.as_closure()
+                          .upvar_tys(def_id, tcx)
+                          .map(|ty| GenericArg::from(ty))
+                          .collect()
                 },
                 _ => bug!(),
             };
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index a36b381bed3..7db1a7413c7 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -193,7 +193,7 @@ fn dtorck_constraint_for_ty<'tcx>(
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty.expect_ty()))
             .collect(),
 
-        ty::Closure(def_id, substs) => substs
+        ty::Closure(def_id, substs) => substs.as_closure()
             .upvar_tys(def_id, tcx)
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 3a169268720..300b730b5bb 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -7,6 +7,7 @@ use hir::def::Res;
 use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::subst::SubstsRef;
 use rustc::{infer, traits};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_target::spec::abi;
@@ -103,7 +104,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Check whether this is a call to a closure where we
                 // haven't yet decided on whether the closure is fn vs
                 // fnmut vs fnonce. If so, we have to defer further processing.
-                let substs = rustc::ty::ClosureSubsts::from_ref(substs);
                 if self.closure_kind(def_id, substs).is_none() {
                     let closure_ty = self.closure_sig(def_id, substs);
                     let fn_sig = self
@@ -481,7 +481,7 @@ pub struct DeferredCallResolution<'tcx> {
     adjustments: Vec<Adjustment<'tcx>>,
     fn_sig: ty::FnSig<'tcx>,
     closure_def_id: DefId,
-    closure_substs: ty::ClosureSubsts<'tcx>,
+    closure_substs: SubstsRef<'tcx>,
 }
 
 impl<'a, 'tcx> DeferredCallResolution<'tcx> {
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 09dcce003fe..76c9bec1db6 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -160,14 +160,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.demand_eqtype(
             expr.span,
             sig_fn_ptr_ty,
-            substs.closure_sig_ty(expr_def_id, self.tcx),
+            substs.as_closure().sig_ty(expr_def_id, self.tcx),
         );
 
         if let Some(kind) = opt_kind {
             self.demand_eqtype(
                 expr.span,
                 kind.to_ty(self.tcx),
-                substs.closure_kind_ty(expr_def_id, self.tcx),
+                substs.as_closure().kind_ty(expr_def_id, self.tcx),
             );
         }
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index c10279022bd..1f8c25ae4e0 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -61,7 +61,7 @@ use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{
     Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast
 };
-use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
+use rustc::ty::{self, TypeAndMut, Ty, subst::SubstsRef};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::error::TypeError;
 use rustc::ty::relate::RelateResult;
@@ -237,8 +237,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 // Non-capturing closures are coercible to
                 // function pointers or unsafe function pointers.
                 // It cannot convert closures that require unsafe.
-                self.coerce_closure_to_fn(a, def_id_a,
-                    rustc::ty::ClosureSubsts::from_ref(substs_a), b)
+                self.coerce_closure_to_fn(a, def_id_a, substs_a, b)
             }
             _ => {
                 // Otherwise, just use unification rules.
@@ -728,7 +727,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
     fn coerce_closure_to_fn(&self,
                            a: Ty<'tcx>,
                            def_id_a: DefId,
-                           substs_a: ClosureSubsts<'tcx>,
+                           substs_a: SubstsRef<'tcx>,
                            b: Ty<'tcx>)
                            -> CoerceResult<'tcx> {
         //! Attempts to coerce from the type of a non-capturing closure
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a7832b8c2cf..c1765964720 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4191,7 +4191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Closure(def_id, substs) => {
                 // We don't use `closure_sig` to account for malformed closures like
                 // `|_: [_; continue]| {}` and instead we don't suggest anything.
-                let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx);
+                let closure_sig_ty = substs.as_closure().sig_ty(def_id, self.tcx);
                 (def_id, match closure_sig_ty.kind {
                     ty::FnPtr(sig) => sig,
                     _ => return false,
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 5b7c5c04e44..3f218e1d9fa 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -96,8 +96,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Extract the type of the closure.
         let ty = self.node_ty(closure_hir_id);
         let (closure_def_id, substs) = match ty.kind {
-            ty::Closure(def_id, substs) => (def_id,
-                UpvarSubsts::Closure(rustc::ty::ClosureSubsts::from_ref(substs))),
+            ty::Closure(def_id, substs) => (
+                def_id,
+                UpvarSubsts::Closure(substs)
+            ),
             ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
             ty::Error => {
                 // #51714: skip analysis when we have already encountered type errors
@@ -191,7 +193,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Unify the (as yet unbound) type variable in the closure
             // substs with the kind we inferred.
             let inferred_kind = delegate.current_closure_kind;
-            let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
+            let closure_kind_ty = closure_substs
+                .as_closure().kind_ty(closure_def_id, self.tcx);
             self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
 
             // If we have an origin, store it.
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 1690ae7635f..d973106058e 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1855,7 +1855,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
             // the signature of a closure, you should use the
             // `closure_sig` method on the `ClosureSubsts`:
             //
-            //    closure_substs.closure_sig(def_id, tcx)
+            //    closure_substs.sig(def_id, tcx)
             //
             // or, inside of an inference context, you can use
             //