From 728a2db35e76f5126a405db917757ee43910c136 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Fri, 26 Apr 2019 00:26:33 +0100
Subject: [PATCH 1/3] Add expect_ty method to Kind

---
 src/librustc/ty/subst.rs | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index b8ae0430502b5..ed3da31fb89bd 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -123,6 +123,16 @@ impl<'tcx> Kind<'tcx> {
             }
         }
     }
+
+    /// Unpack the `Kind` as a type when it is known certainly to be a type.
+    /// This is true in cases where `Substs` is used in places where the kinds are known
+    /// to be limited (e.g. in tuples, where the only parameters are type parameters).
+    pub fn expect_ty(self) -> Ty<'tcx> {
+        match self.unpack() {
+            UnpackedKind::Type(ty) => ty,
+            _ => bug!("expected a type, but found another kind"),
+        }
+    }
 }
 
 impl<'a, 'tcx> Lift<'tcx> for Kind<'a> {
@@ -174,8 +184,7 @@ pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
 
 impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
     /// Creates a `InternalSubsts` that maps each generic parameter to itself.
-    pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
-                             -> SubstsRef<'tcx> {
+    pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
         Self::for_item(tcx, def_id, |param, _| {
             tcx.mk_param_from_def(param)
         })

From 283ca7616c69a6c893b7d9dd157fa9df4a746b72 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Fri, 26 Apr 2019 00:26:57 +0100
Subject: [PATCH 2/3] Replace `&'tcx List<Ty<'tcx>>` in `Tuple` with
 `SubstsRef<'tcx>`

---
 src/librustc/ty/sty.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 9a90ccda9140c..7404cf0b0d24e 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -171,7 +171,7 @@ pub enum TyKind<'tcx> {
     Never,
 
     /// A tuple type. For example, `(i32, bool)`.
-    Tuple(&'tcx List<Ty<'tcx>>),
+    Tuple(SubstsRef<'tcx>),
 
     /// The projection of an associated type. For example,
     /// `<T as Trait<..>>::N`.

From a3470c61890710421ddb82fbe72b1ca8fdc8e078 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Fri, 26 Apr 2019 00:27:33 +0100
Subject: [PATCH 3/3] Update handling of Tuple

---
 src/librustc/mir/tcx.rs                       |  2 +-
 src/librustc/traits/error_reporting.rs        |  4 +--
 src/librustc/traits/query/dropck_outlives.rs  |  2 +-
 src/librustc/traits/select.rs                 | 14 +++++---
 src/librustc/ty/context.rs                    | 10 ++++--
 src/librustc/ty/flags.rs                      |  4 +--
 src/librustc/ty/inhabitedness/mod.rs          |  2 +-
 src/librustc/ty/layout.rs                     |  7 ++--
 src/librustc/ty/mod.rs                        |  2 +-
 src/librustc/ty/print/mod.rs                  |  2 +-
 src/librustc/ty/print/pretty.rs               |  3 +-
 src/librustc/ty/relate.rs                     |  4 ++-
 src/librustc/ty/sty.rs                        |  9 +++--
 src/librustc/ty/util.rs                       | 16 ++++++---
 src/librustc/ty/walk.rs                       |  2 +-
 src/librustc/ty/wf.rs                         |  2 +-
 src/librustc_codegen_llvm/abi.rs              |  8 ++---
 .../debuginfo/metadata.rs                     |  3 +-
 src/librustc_codegen_llvm/debuginfo/mod.rs    |  2 +-
 .../debuginfo/type_names.rs                   |  2 +-
 .../borrow_check/error_reporting.rs           |  2 +-
 .../error_reporting/region_name.rs            |  2 +-
 .../borrow_check/nll/type_check/mod.rs        |  2 +-
 .../borrow_check/nll/universal_regions.rs     |  2 +-
 src/librustc_mir/hair/pattern/_match.rs       |  2 +-
 src/librustc_mir/monomorphize/item.rs         |  2 +-
 src/librustc_mir/shim.rs                      |  2 +-
 src/librustc_mir/transform/add_retag.rs       |  2 +-
 src/librustc_mir/transform/inline.rs          |  5 ++-
 src/librustc_mir/util/elaborate_drops.rs      |  3 +-
 .../chalk_context/program_clauses/builtin.rs  | 23 ++++++++-----
 .../program_clauses/primitive.rs              |  2 +-
 src/librustc_traits/dropck_outlives.rs        |  2 +-
 src/librustc_traits/generic_types.rs          |  7 ++--
 src/librustc_typeck/check/_match.rs           | 15 ++++++---
 src/librustc_typeck/check/cast.rs             |  2 +-
 src/librustc_typeck/check/closure.rs          |  6 ++--
 src/librustc_typeck/check/mod.rs              | 33 ++++++++++---------
 src/librustc_typeck/variance/constraints.rs   |  2 +-
 src/librustdoc/clean/mod.rs                   |  8 +++--
 40 files changed, 134 insertions(+), 90 deletions(-)

diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 04b763f773d9e..5d1dca5a1f4c4 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -47,7 +47,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
                 let field_def = &variant_def.fields[f.index()];
                 field_def.ty(tcx, substs)
             }
-            ty::Tuple(ref tys) => tys[f.index()],
+            ty::Tuple(ref tys) => tys[f.index()].expect_ty(),
             _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
         };
         debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 14c81a806c259..76a751536523d 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -875,7 +875,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
                 let expected = match expected_ty.sty {
                     ty::Tuple(ref tys) => tys.iter()
-                        .map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(),
+                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))).collect(),
                     _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
                 };
 
@@ -1247,7 +1247,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             let inputs = trait_ref.substs.type_at(1);
             let sig = if let ty::Tuple(inputs) = inputs.sty {
                 tcx.mk_fn_sig(
-                    inputs.iter().cloned(),
+                    inputs.iter().map(|k| k.expect_ty()),
                     tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
                     false,
                     hir::Unsafety::Normal,
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index e6f9c7ebe6fe4..5800b024ad245 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -217,7 +217,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
 
         // (T1..Tn) and closures have same properties as T1..Tn --
         // check if *any* of those are trivial.
-        ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)),
+        ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
         ty::Closure(def_id, ref substs) => substs
             .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 495b099601dac..8beabe058cf4f 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2429,7 +2429,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
             ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
 
-            ty::Tuple(tys) => Where(ty::Binder::bind(tys.last().into_iter().cloned().collect())),
+            ty::Tuple(tys) => {
+                Where(ty::Binder::bind(tys.last().into_iter().map(|k| k.expect_ty()).collect()))
+            }
 
             ty::Adt(def, substs) => {
                 let sized_crit = def.sized_constraint(self.tcx());
@@ -2503,7 +2505,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
             ty::Tuple(tys) => {
                 // (*) binder moved here
-                Where(ty::Binder::bind(tys.to_vec()))
+                Where(ty::Binder::bind(tys.iter().map(|k| k.expect_ty()).collect()))
             }
 
             ty::Closure(def_id, substs) => {
@@ -2590,7 +2592,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
             ty::Tuple(ref tys) => {
                 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
-                tys.to_vec()
+                tys.iter().map(|k| k.expect_ty()).collect()
             }
 
             ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, self.tcx()).collect(),
@@ -3495,7 +3497,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
                 // Check that the source tuple with the target's
                 // last element is equal to the target.
-                let new_tuple = tcx.mk_tup(a_mid.iter().cloned().chain(iter::once(b_last)));
+                let new_tuple = tcx.mk_tup(
+                    a_mid.iter().map(|k| k.expect_ty()).chain(iter::once(b_last.expect_ty())),
+                );
                 let InferOk { obligations, .. } = self.infcx
                     .at(&obligation.cause, obligation.param_env)
                     .eq(target, new_tuple)
@@ -3508,7 +3512,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     obligation.cause.clone(),
                     obligation.predicate.def_id(),
                     obligation.recursion_depth + 1,
-                    a_last,
+                    a_last.expect_ty(),
                     &[b_last.into()],
                 ));
             }
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 2d857f402ed60..132477547a0d8 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2431,7 +2431,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let converted_sig = sig.map_bound(|s| {
             let params_iter = match s.inputs()[0].sty {
                 ty::Tuple(params) => {
-                    params.into_iter().cloned()
+                    params.into_iter().map(|k| k.expect_ty())
                 }
                 _ => bug!(),
             };
@@ -2573,11 +2573,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     #[inline]
     pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
-        self.mk_ty(Tuple(self.intern_type_list(ts)))
+        let kinds: Vec<_> = ts.into_iter().map(|&t| Kind::from(t)).collect();
+        self.mk_ty(Tuple(self.intern_substs(&kinds)))
     }
 
     pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output {
-        iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(ts))))
+        iter.intern_with(|ts| {
+            let kinds: Vec<_> = ts.into_iter().map(|&t| Kind::from(t)).collect();
+            self.mk_ty(Tuple(self.intern_substs(&kinds)))
+        })
     }
 
     #[inline]
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 7aed2a4288c8e..cb4724adc932c 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -195,8 +195,8 @@ impl FlagComputation {
                 self.add_ty(ty);
             }
 
-            &ty::Tuple(ref ts) => {
-                self.add_tys(&ts[..]);
+            &ty::Tuple(ref substs) => {
+                self.add_substs(substs);
             }
 
             &ty::FnDef(_, substs) => {
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 042f06e13a35a..197d3325f51cf 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
 
             Tuple(ref tys) => {
                 DefIdForest::union(tcx, tys.iter().map(|ty| {
-                    ty.uninhabited_from(tcx)
+                    ty.expect_ty().uninhabited_from(tcx)
                 }))
             }
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index fd1d3a91ede1f..50f01522aeede 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -626,8 +626,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
                     StructKind::MaybeUnsized
                 };
 
-                univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
-                           &ReprOptions::default(), kind)?
+                univariant(&tys.iter().map(|k| {
+                    self.layout_of(k.expect_ty())
+                }).collect::<Result<Vec<_>, _>>()?, &ReprOptions::default(), kind)?
             }
 
             // SIMD vector types.
@@ -1723,7 +1724,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                 substs.field_tys(def_id, tcx).nth(i).unwrap()
             }
 
-            ty::Tuple(tys) => tys[i],
+            ty::Tuple(tys) => tys[i].expect_ty(),
 
             // SIMD vector types.
             ty::Adt(def, ..) if def.repr.simd() => {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index f2c77b1bfab7d..00bdd4a98cebd 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2505,7 +2505,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
             Tuple(ref tys) => {
                 match tys.last() {
                     None => vec![],
-                    Some(ty) => self.sized_constraint_for_ty(tcx, ty)
+                    Some(ty) => self.sized_constraint_for_ty(tcx, ty.expect_ty()),
                 }
             }
 
diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs
index ef30a4032d8fa..d5d4f64844463 100644
--- a/src/librustc/ty/print/mod.rs
+++ b/src/librustc/ty/print/mod.rs
@@ -264,7 +264,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty),
 
         ty::Tuple(ref tys) => tys.iter()
-                                   .filter_map(|ty| characteristic_def_id_of_type(ty))
+                                   .filter_map(|ty| characteristic_def_id_of_type(ty.expect_ty()))
                                    .next(),
 
         ty::FnDef(def_id, _) |
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index b31ba10d523a5..e5803b7be4f63 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -701,7 +701,8 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
                 if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
                     let mut projections = predicates.projection_bounds();
                     if let (Some(proj), None) = (projections.next(), projections.next()) {
-                        p!(pretty_fn_sig(args, false, proj.ty));
+                        let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect();
+                        p!(pretty_fn_sig(&tys, false, proj.ty));
                         resugared = true;
                     }
                 }
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 810bd10c8f4f7..1f5a39cbef14e 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -526,7 +526,9 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
         (&ty::Tuple(as_), &ty::Tuple(bs)) =>
         {
             if as_.len() == bs.len() {
-                Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b)))?)
+                Ok(tcx.mk_tup(as_.iter().zip(bs).map(|(a, b)| {
+                    relation.relate(&a.expect_ty(), &b.expect_ty())
+                }))?)
             } else if !(as_.is_empty() || bs.is_empty()) {
                 Err(TypeError::TupleSize(
                     expected_found(relation, &as_.len(), &bs.len())))
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 7404cf0b0d24e..1e8f3ebd0ddca 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1651,7 +1651,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
                     })
                 })
             }
-            ty::Tuple(tys) => tys.iter().any(|ty| ty.conservative_is_privately_uninhabited(tcx)),
+            ty::Tuple(tys) => tys.iter().any(|ty| {
+                ty.expect_ty().conservative_is_privately_uninhabited(tcx)
+            }),
             ty::Array(ty, len) => {
                 match len.assert_usize(tcx) {
                     // If the array is definitely non-empty, it's uninhabited if
@@ -2087,8 +2089,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
             ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) =>
                 false,
 
-            ty::Tuple(tys) =>
-                tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
+            ty::Tuple(tys) => {
+                tys.iter().all(|ty| ty.expect_ty().is_trivially_sized(tcx))
+            }
 
             ty::Adt(def, _substs) =>
                 def.sized_constraint(tcx).is_empty(),
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 67507f7b5d116..2db2ef59a6ba0 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -278,7 +278,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
                 ty::Tuple(tys) => {
                     if let Some((&last_ty, _)) = tys.split_last() {
-                        ty = last_ty;
+                        ty = last_ty.expect_ty();
                     } else {
                         break;
                     }
@@ -316,8 +316,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 (&Tuple(a_tys), &Tuple(b_tys))
                         if a_tys.len() == b_tys.len() => {
                     if let Some(a_last) = a_tys.last() {
-                        a = a_last;
-                        b = b_tys.last().unwrap();
+                        a = a_last.expect_ty();
+                        b = b_tys.last().unwrap().expect_ty();
                     } else {
                         break;
                     }
@@ -795,7 +795,13 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
                 Tuple(ref ts) => {
                     // Find non representable
                     fold_repr(ts.iter().map(|ty| {
-                        is_type_structurally_recursive(tcx, sp, seen, representable_cache, ty)
+                        is_type_structurally_recursive(
+                            tcx,
+                            sp,
+                            seen,
+                            representable_cache,
+                            ty.expect_ty(),
+                        )
                     }))
                 }
                 // Fixed-length vectors.
@@ -1048,7 +1054,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // state transformation pass
         ty::Generator(..) => true,
 
-        ty::Tuple(ref tys) => tys.iter().cloned().any(needs_drop),
+        ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).any(needs_drop),
 
         // unions don't have destructors because of the child types,
         // only if they manually implement `Drop` (handled above).
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index fa1eadf34ac89..234407a7c4eaf 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -120,7 +120,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
             stack.extend(ts.skip_binder().iter().cloned().rev());
         }
         ty::Tuple(ts) => {
-            stack.extend(ts.iter().cloned().rev());
+            stack.extend(ts.iter().map(|k| k.expect_ty()).rev());
         }
         ty::FnDef(_, substs) => {
             stack.extend(substs.types().rev());
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 7bfda6a6557a3..b793b37fb2ae1 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -265,7 +265,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                 ty::Tuple(ref tys) => {
                     if let Some((_last, rest)) = tys.split_last() {
                         for elem in rest {
-                            self.require_sized(elem, traits::TupleElem);
+                            self.require_sized(elem.expect_ty(), traits::TupleElem);
                         }
                     }
                 }
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 348616790b0bc..2c4a1ded97f39 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -426,9 +426,9 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
             assert!(!sig.c_variadic && extra_args.is_empty());
 
             match sig.inputs().last().unwrap().sty {
-                ty::Tuple(ref tupled_arguments) => {
+                ty::Tuple(tupled_arguments) => {
                     inputs = &sig.inputs()[0..sig.inputs().len() - 1];
-                    tupled_arguments
+                    tupled_arguments.iter().map(|k| k.expect_ty()).collect()
                 }
                 _ => {
                     bug!("argument to function with \"rust-call\" ABI \
@@ -437,7 +437,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
             }
         } else {
             assert!(sig.c_variadic || extra_args.is_empty());
-            extra_args
+            extra_args.to_vec()
         };
 
         let target = &cx.sess().target.target;
@@ -587,7 +587,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
 
         let mut fn_ty = FnType {
             ret: arg_of(sig.output(), None),
-            args: inputs.iter().chain(extra_args).enumerate().map(|(i, ty)| {
+            args: inputs.iter().cloned().chain(extra_args).enumerate().map(|(i, ty)| {
                 arg_of(ty, Some(i))
             }).collect(),
             c_variadic: sig.c_variadic,
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 31348b99c5af0..765992fd2b70e 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -722,9 +722,10 @@ pub fn type_metadata(
             }
         },
         ty::Tuple(ref elements) => {
+            let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect();
             prepare_tuple_metadata(cx,
                                    t,
-                                   &elements[..],
+                                   &tys,
                                    unique_type_id,
                                    usage_site_span).finalize(cx)
         }
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index cb00cca0f9c96..2154ac9b1d259 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -392,7 +392,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                 if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
                     signature.extend(
                         args.iter().map(|argument_type| {
-                            Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
+                            Some(type_metadata(cx, argument_type.expect_ty(), syntax_pos::DUMMY_SP))
                         })
                     );
                 }
diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs
index fee6c5b04d0d1..39aea4b9828fe 100644
--- a/src/librustc_codegen_ssa/debuginfo/type_names.rs
+++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs
@@ -46,7 +46,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::Tuple(component_types) => {
             output.push('(');
             for &component_type in component_types {
-                push_debuginfo_type_name(tcx, component_type, true, output, visited);
+                push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
                 output.push_str(", ");
             }
             if !component_types.is_empty() {
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 12dcea7bd5981..ac0b9da87048b 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -2214,7 +2214,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // Closure arguments are wrapped in a tuple, so we need to get the first
                 // from that.
                 if let ty::Tuple(elems) = argument_ty.sty {
-                    let argument_ty = elems.first()?;
+                    let argument_ty = elems.first()?.expect_ty();
                     if let ty::Ref(_, _, _) = argument_ty.sty {
                         return Some(AnnotatedBorrowFnSignature::Closure {
                             argument_ty,
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 680e7ce576af0..f9b571a7d60eb 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
@@ -515,7 +515,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // just worry about trying to match up the rustc type
                 // with the HIR types:
                 (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => {
-                    search_stack.extend(elem_tys.iter().cloned().zip(elem_hir_tys));
+                    search_stack.extend(elem_tys.iter().map(|k| k.expect_ty()).zip(elem_hir_tys));
                 }
 
                 (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty))
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 0dee64db72763..6c26dc33e781d 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -779,7 +779,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 }
                 ty::Tuple(tys) => {
                     return match tys.get(field.index()) {
-                        Some(&ty) => Ok(ty),
+                        Some(&ty) => Ok(ty.expect_ty()),
                         None => Err(FieldAccessError::OutOfRange {
                             field_count: tys.len(),
                         }),
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index d3cef46b4022d..499bfd62b00b5 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -580,7 +580,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
 
                         tcx.mk_type_list(
                             iter::once(closure_ty)
-                                .chain(inputs.iter().cloned())
+                                .chain(inputs.iter().map(|k| k.expect_ty()))
                                 .chain(iter::once(output)),
                         )
                     },
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index c41a09aecaad6..edd36abc0b8a4 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -1359,7 +1359,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
 {
     debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
     match ty.sty {
-        ty::Tuple(ref fs) => fs.into_iter().map(|t| *t).collect(),
+        ty::Tuple(ref fs) => fs.into_iter().map(|t| t.expect_ty()).collect(),
         ty::Slice(ty) | ty::Array(ty, _) => match *ctor {
             Slice(length) => (0..length).map(|_| ty).collect(),
             ConstantValue(_) => vec![],
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 51ba690d3a14b..2fc0e08834a6e 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -272,7 +272,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
             ty::Tuple(component_types) => {
                 output.push('(');
                 for &component_type in component_types {
-                    self.push_type_name(component_type, output, debug);
+                    self.push_type_name(component_type.expect_ty(), output, debug);
                     output.push_str(", ");
                 }
                 if !component_types.is_empty() {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index cb25db73cd2be..a3708d064ec3b 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -331,7 +331,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 substs.upvar_tys(def_id, tcx)
             )
         }
-        ty::Tuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().cloned()),
+        ty::Tuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().map(|k| k.expect_ty())),
         _ => {
             bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty)
         }
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index a393847fd4922..32c9953ee9e08 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -63,7 +63,7 @@ fn may_have_reference<'a, 'gcx, 'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
         ty::Array(ty, ..) | ty::Slice(ty) =>
             may_have_reference(ty, tcx),
         ty::Tuple(tys) =>
-            tys.iter().any(|ty| may_have_reference(ty, tcx)),
+            tys.iter().any(|ty| may_have_reference(ty.expect_ty(), tcx)),
         ty::Adt(adt, substs) =>
             adt.variants.iter().any(|v| v.fields.iter().any(|f|
                 may_have_reference(f.ty(tcx, substs), tcx)
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index e96a40ad2f036..b75321d031fda 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -575,7 +575,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             let tuple_tmp_args =
                 tuple_tys.iter().enumerate().map(|(i, ty)| {
                     // This is e.g., `tuple_tmp.0` in our example above.
-                    let tuple_field = Operand::Move(tuple.clone().field(Field::new(i), ty));
+                    let tuple_field = Operand::Move(tuple.clone().field(
+                        Field::new(i),
+                        ty.expect_ty(),
+                    ));
 
                     // Spill to a local to make e.g., `tmp0`.
                     self.create_temp_if_necessary(tuple_field, callsite, caller_mir)
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 2d275c9a13792..1c3545cc18cef 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -797,7 +797,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
                 self.open_drop_for_tuple(&tys)
             }
             ty::Tuple(tys) => {
-                self.open_drop_for_tuple(tys)
+                let tys: Vec<_> = tys.iter().map(|k| k.expect_ty()).collect();
+                self.open_drop_for_tuple(&tys)
             }
             ty::Adt(def, substs) => {
                 if def.is_box() {
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
index 27af8511915d1..e2552bb1bdd5a 100644
--- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
@@ -5,7 +5,7 @@ use rustc::traits::{
     ProgramClauseCategory,
 };
 use rustc::ty;
-use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::ty::subst::{Kind, InternalSubsts, Subst};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use crate::lowering::Lower;
@@ -17,7 +17,7 @@ use crate::generic_types;
 fn builtin_impl_clause(
     tcx: ty::TyCtxt<'_, '_, 'tcx>,
     ty: ty::Ty<'tcx>,
-    nested: &[ty::Ty<'tcx>],
+    nested: &[Kind<'tcx>],
     trait_def_id: DefId
 ) -> ProgramClause<'tcx> {
     ProgramClause {
@@ -32,7 +32,7 @@ fn builtin_impl_clause(
                 .cloned()
                 .map(|nested_ty| ty::TraitRef {
                     def_id: trait_def_id,
-                    substs: tcx.mk_substs_trait(nested_ty, &[]),
+                    substs: tcx.mk_substs_trait(nested_ty.expect_ty(), &[]),
                 })
                 .map(|trait_ref| ty::TraitPredicate { trait_ref })
                 .map(|pred| GoalKind::DomainGoal(pred.lower()))
@@ -124,7 +124,7 @@ crate fn assemble_builtin_sized_impls<'tcx>(
     ty: ty::Ty<'tcx>,
     clauses: &mut Vec<Clause<'tcx>>
 ) {
-    let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
+    let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[Kind<'tcx>]| {
         let clause = builtin_impl_clause(tcx, ty, nested, sized_def_id);
         // Bind innermost bound vars that may exist in `ty` and `nested`.
         clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
@@ -176,7 +176,7 @@ crate fn assemble_builtin_sized_impls<'tcx>(
         // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
         &ty::Tuple(type_list) => {
             let type_list = generic_types::type_list(tcx, type_list.len());
-            push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
+            push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &type_list);
         }
 
         // Struct def
@@ -185,7 +185,7 @@ crate fn assemble_builtin_sized_impls<'tcx>(
             let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
             let sized_constraint = adt_def.sized_constraint(tcx)
                 .iter()
-                .map(|ty| ty.subst(tcx, substs))
+                .map(|ty| Kind::from(ty.subst(tcx, substs)))
                 .collect::<Vec<_>>();
             push_builtin_impl(adt, &sized_constraint);
         }
@@ -228,7 +228,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>(
     ty: ty::Ty<'tcx>,
     clauses: &mut Vec<Clause<'tcx>>
 ) {
-    let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
+    let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[Kind<'tcx>]| {
         let clause = builtin_impl_clause(tcx, ty, nested, trait_def_id);
         // Bind innermost bound vars that may exist in `ty` and `nested`.
         clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
@@ -253,7 +253,10 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>(
         // These implement `Copy`/`Clone` if their element types do.
         &ty::Array(_, length) => {
             let element_ty = generic_types::bound(tcx, 0);
-            push_builtin_impl(tcx.mk_ty(ty::Array(element_ty, length)), &[element_ty]);
+            push_builtin_impl(
+                tcx.mk_ty(ty::Array(element_ty, length)),
+                &[Kind::from(element_ty)],
+            );
         }
         &ty::Tuple(type_list) => {
             let type_list = generic_types::type_list(tcx, type_list.len());
@@ -262,7 +265,9 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>(
         &ty::Closure(def_id, ..) => {
             let closure_ty = generic_types::closure(tcx, def_id);
             let upvar_tys: Vec<_> = match &closure_ty.sty {
-                ty::Closure(_, substs) => substs.upvar_tys(def_id, tcx).collect(),
+                ty::Closure(_, substs) => {
+                    substs.upvar_tys(def_id, tcx).map(|ty| Kind::from(ty)).collect()
+                },
                 _ => bug!(),
             };
             push_builtin_impl(closure_ty, &upvar_tys);
diff --git a/src/librustc_traits/chalk_context/program_clauses/primitive.rs b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
index fc6d40914745d..5131bae137d01 100644
--- a/src/librustc_traits/chalk_context/program_clauses/primitive.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
@@ -131,7 +131,7 @@ crate fn wf_clause_for_tuple<'tcx>(
     let sized_implemented = type_list[0 .. std::cmp::max(arity, 1) - 1].iter()
         .map(|ty| ty::TraitRef {
             def_id: sized_trait,
-            substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
+            substs: tcx.mk_substs_trait(ty.expect_ty(), ty::List::empty()),
         })
         .map(|trait_ref| ty::TraitPredicate { trait_ref })
         .map(|predicate| predicate.lower());
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 49fcb7cd83355..0f02601ed705b 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -191,7 +191,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
         }
 
         ty::Tuple(tys) => tys.iter()
-            .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
+            .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty.expect_ty()))
             .collect(),
 
         ty::Closure(def_id, substs) => substs
diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs
index f2ce9631f35ab..cf54260084e11 100644
--- a/src/librustc_traits/generic_types.rs
+++ b/src/librustc_traits/generic_types.rs
@@ -1,7 +1,7 @@
 //! Utilities for creating generic types with bound vars in place of parameter values.
 
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::InternalSubsts;
+use rustc::ty::subst::{Kind, SubstsRef, InternalSubsts};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc_target::spec::abi;
@@ -44,11 +44,12 @@ crate fn fn_ptr(
     tcx.mk_fn_ptr(fn_sig)
 }
 
-crate fn type_list(tcx: ty::TyCtxt<'_, '_, 'tcx>, arity: usize) -> &'tcx ty::List<Ty<'tcx>> {
-    tcx.mk_type_list(
+crate fn type_list(tcx: ty::TyCtxt<'_, '_, 'tcx>, arity: usize) -> SubstsRef<'tcx> {
+    tcx.mk_substs(
         (0..arity).into_iter()
             .map(|i| ty::BoundVar::from(i))
             .map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into())))
+            .map(|ty| Kind::from(ty))
     )
 }
 
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 032821e6d42f2..f3cabced34dfc 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -9,6 +9,7 @@ use rustc::infer;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::traits::ObligationCauseCode;
 use rustc::ty::{self, Ty, TypeFoldable};
+use rustc::ty::subst::Kind;
 use syntax::ast;
 use syntax::source_map::Spanned;
 use syntax::ptr::P;
@@ -304,11 +305,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
                 let max_len = cmp::max(expected_len, elements.len());
 
-                let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
+                let element_tys_iter = (0..max_len).map(|_| {
                     // FIXME: `MiscVariable` for now -- obtaining the span and name information
                     // from all tuple elements isn't trivial.
-                    TypeVariableOrigin::TypeInference(pat.span)));
-                let element_tys = tcx.mk_type_list(element_tys_iter);
+                    Kind::from(self.next_ty_var(TypeVariableOrigin::TypeInference(pat.span)))
+                });
+                let element_tys = tcx.mk_substs(element_tys_iter);
                 let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
                 if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
                     err.emit();
@@ -321,7 +323,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     tcx.mk_tup(element_tys_iter)
                 } else {
                     for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
-                        self.check_pat_walk(elem, &element_tys[i], def_bm, match_discrim_span);
+                        self.check_pat_walk(
+                            elem,
+                            &element_tys[i].expect_ty(),
+                            def_bm,
+                            match_discrim_span,
+                        );
                     }
                     pat_ty
                 }
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index cad9e73bd2ac9..4689456d11fe2 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -107,7 +107,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
             ty::Tuple(fields) => match fields.last() {
                 None => Some(PointerKind::Thin),
-                Some(f) => self.pointer_kind(f, span)?
+                Some(f) => self.pointer_kind(f.expect_ty(), span)?
             },
 
             // Pointers to foreign types are thin, despite being unsized
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index f7396cbd42f2f..838874cc2bf07 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -274,8 +274,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         );
 
         let input_tys = match arg_param_ty.sty {
-            ty::Tuple(tys) => tys.into_iter(),
-            _ => return None
+            ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()),
+            _ => return None,
         };
 
         let ret_param_ty = projection.skip_binder().ty;
@@ -286,7 +286,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         );
 
         let sig = self.tcx.mk_fn_sig(
-            input_tys.cloned(),
+            input_tys,
             ret_param_ty,
             false,
             hir::Unsafety::Normal,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d2d05982c619a..edca00f69b12b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2859,7 +2859,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             sp: Span,
                             expr_sp: Span,
                             fn_inputs: &[Ty<'tcx>],
-                            mut expected_arg_tys: &[Ty<'tcx>],
+                            expected_arg_tys: &[Ty<'tcx>],
                             args: &'gcx [hir::Expr],
                             c_variadic: bool,
                             tuple_arguments: TupleArgumentsFlag,
@@ -2915,29 +2915,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             err.emit();
         };
 
+        let mut expected_arg_tys = expected_arg_tys.to_vec();
+
         let formal_tys = if tuple_arguments == TupleArguments {
             let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
             match tuple_type.sty {
                 ty::Tuple(arg_types) if arg_types.len() != args.len() => {
                     param_count_error(arg_types.len(), args.len(), "E0057", false, false);
-                    expected_arg_tys = &[];
+                    expected_arg_tys = vec![];
                     self.err_args(args.len())
                 }
                 ty::Tuple(arg_types) => {
                     expected_arg_tys = match expected_arg_tys.get(0) {
                         Some(&ty) => match ty.sty {
-                            ty::Tuple(ref tys) => &tys,
-                            _ => &[]
+                            ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(),
+                            _ => vec![],
                         },
-                        None => &[]
+                        None => vec![],
                     };
-                    arg_types.to_vec()
+                    arg_types.iter().map(|k| k.expect_ty()).collect()
                 }
                 _ => {
                     span_err!(tcx.sess, sp, E0059,
                         "cannot use call notation; the first type parameter \
                          for the function trait is neither a tuple nor unit");
-                    expected_arg_tys = &[];
+                    expected_arg_tys = vec![];
                     self.err_args(args.len())
                 }
             }
@@ -2948,7 +2950,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 fn_inputs.to_vec()
             } else {
                 param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false);
-                expected_arg_tys = &[];
+                expected_arg_tys = vec![];
                 self.err_args(supplied_arg_count)
             }
         } else {
@@ -2962,19 +2964,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             };
             param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit);
 
-            expected_arg_tys = &[];
+            expected_arg_tys = vec![];
             self.err_args(supplied_arg_count)
         };
+
+        debug!("check_argument_types: formal_tys={:?}",
+               formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>());
+
         // If there is no expectation, expect formal_tys.
         let expected_arg_tys = if !expected_arg_tys.is_empty() {
             expected_arg_tys
         } else {
-            &formal_tys
+            formal_tys.clone()
         };
 
-        debug!("check_argument_types: formal_tys={:?}",
-               formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::<Vec<String>>());
-
         // Check the arguments.
         // We do this in a pretty awful way: first we type-check any arguments
         // that are not closures, then we type-check the closures. This is so
@@ -3560,7 +3563,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 autoderef.finalize(self);
 
                                 self.write_field_index(expr.hir_id, index);
-                                return field_ty;
+                                return field_ty.expect_ty();
                             }
                         }
                     }
@@ -4630,7 +4633,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| {
                     let t = match flds {
                         Some(ref fs) if i < fs.len() => {
-                            let ety = fs[i];
+                            let ety = fs[i].expect_ty();
                             self.check_expr_coercable_to_type(&e, ety);
                             ety
                         }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 644ba5981a63d..5079a3bb55f89 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -288,7 +288,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
             ty::Tuple(subtys) => {
                 for &subty in subtys {
-                    self.add_constraints_from_ty(current, subty, variance);
+                    self.add_constraints_from_ty(current, subty.expect_ty(), variance);
                 }
             }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 81e4905890d45..b0a0b96f6b5fd 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1136,7 +1136,7 @@ fn external_generic_args(
         Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
             assert!(ty_sty.is_some());
             let inputs = match ty_sty {
-                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.clean(cx)).collect(),
+                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
                 _ => return GenericArgs::AngleBracketed { args, bindings },
             };
             let output = None;
@@ -1181,7 +1181,7 @@ impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
         for ty_s in trait_ref.input_types().skip(1) {
             if let ty::Tuple(ts) = ty_s.sty {
                 for &ty_s in ts {
-                    if let ty::Ref(ref reg, _, _) = ty_s.sty {
+                    if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().sty {
                         if let &ty::RegionKind::ReLateBound(..) = *reg {
                             debug!("  hit an ReLateBound {:?}", reg);
                             if let Some(Lifetime(name)) = reg.clean(cx) {
@@ -3066,7 +3066,9 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     is_generic: false,
                 }
             }
-            ty::Tuple(ref t) => Tuple(t.clean(cx)),
+            ty::Tuple(ref t) => {
+                Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
+            }
 
             ty::Projection(ref data) => data.clean(cx),