]> git.lizzy.rs Git - rust.git/commitdiff
rustc: add TyAnon (impl Trait) to the typesystem.
authorEduard Burtescu <edy.burt@gmail.com>
Fri, 22 Jul 2016 15:56:22 +0000 (18:56 +0300)
committerEduard Burtescu <edy.burt@gmail.com>
Fri, 12 Aug 2016 03:43:34 +0000 (06:43 +0300)
40 files changed:
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/infer/freshen.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/ty/contents.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_lint/types.rs
src/librustc_metadata/def_key.rs
src/librustc_metadata/tydecode.rs
src/librustc_metadata/tyencode.rs
src/librustc_trans/collector.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/constrained_type_params.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs

index 58bbd8add26d96e660b1164e9e02675185c210b0..752b0e9a253dd9a7ee1cf41cd922c1f8467ce1c2 100644 (file)
@@ -268,6 +268,9 @@ fn visit_ty(&mut self, ty: &Ty) {
         if let TyKind::FixedLengthVec(_, ref length) = ty.node {
             self.visit_ast_const_integer(length);
         }
+        if let TyKind::ImplTrait(..) = ty.node {
+            self.create_def(ty.id, DefPathData::ImplTrait);
+        }
         visit::walk_ty(self, ty);
     }
 
@@ -428,6 +431,9 @@ fn visit_ty(&mut self, ty: &'ast hir::Ty) {
         if let hir::TyFixedLengthVec(_, ref length) = ty.node {
             self.visit_hir_const_integer(length);
         }
+        if let hir::TyImplTrait(..) = ty.node {
+            self.create_def(ty.id, DefPathData::ImplTrait);
+        }
         intravisit::walk_ty(self, ty);
     }
 
index e3425d7fa61f5f73d9270f4ed5f4163e49efc59c..901a489728eeca0aca5c4ff7d9e26b23985047af 100644 (file)
@@ -215,6 +215,8 @@ pub enum DefPathData {
     Initializer,
     /// Pattern binding
     Binding(InternedString),
+    /// An `impl Trait` type node.
+    ImplTrait
 }
 
 impl Definitions {
@@ -369,6 +371,10 @@ pub fn as_interned_str(&self) -> InternedString {
             Initializer => {
                 InternedString::new("{{initializer}}")
             }
+
+            ImplTrait => {
+                InternedString::new("{{impl-Trait}}")
+            }
         }
     }
 
index 880661a882af3c38e114390d6d39226b5eccd020..1fb4e59e13189ff07fc14de61e81f58142d9ecff 100644 (file)
@@ -170,7 +170,8 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::TyClosure(..) |
             ty::TyTuple(..) |
             ty::TyProjection(..) |
-            ty::TyParam(..) => {
+            ty::TyParam(..) |
+            ty::TyAnon(..) => {
                 t.super_fold_with(self)
             }
         }
index 4344eb1ebf6645faf708d6f0c55677fd10c5b004..37193d45e68852245a523c298b94e01689ce8164 100644 (file)
@@ -281,7 +281,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
             true
         }
 
-        ty::TyClosure(..) => {
+        ty::TyClosure(..) | ty::TyAnon(..) => {
             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
         }
     }
index 62a31133a5499b33a21ba1898a01e9d0cfde226d..09b5a34fdf33722cb048348fe8e70b16d6c13a3b 100644 (file)
@@ -211,6 +211,7 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
                 ty::TyTuple(..) => Some(12),
                 ty::TyProjection(..) => Some(13),
                 ty::TyParam(..) => Some(14),
+                ty::TyAnon(..) => Some(15),
                 ty::TyInfer(..) | ty::TyError => None
             }
         }
index b93693cd756ce7f2337c3649d089e4181107a566..aed4f4393241191d1f2d655f2ba594a709d67b10 100644 (file)
@@ -94,6 +94,16 @@ pub enum Reveal {
     NotSpecializable,
 
     /// At trans time, all monomorphic projections will succeed.
+    /// Also, `impl Trait` is normalized to the concrete type,
+    /// which has to be already collected by type-checking.
+    ///
+    /// NOTE: As `impl Trait`'s concrete type should *never*
+    /// be observable directly by the user, `Reveal::All`
+    /// should not be used by checks which may expose
+    /// type equality or type contents to the user.
+    /// There are some exceptions, e.g. around OIBITS and
+    /// transmute-checking, which expose some details, but
+    /// not the whole concrete type of the `impl Trait`.
     All,
 }
 
@@ -298,6 +308,17 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.sty {
+            ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
+                // Only normalize `impl Trait` after type-checking, usually in trans.
+                if self.selcx.projection_mode() == Reveal::All {
+                    let generic_ty = self.tcx().lookup_item_type(def_id).ty;
+                    let concrete_ty = generic_ty.subst(self.tcx(), substs);
+                    self.fold_ty(concrete_ty)
+                } else {
+                    ty
+                }
+            }
+
             ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*)
 
                 // (*) This is kind of hacky -- we need to be able to
@@ -773,8 +794,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
     debug!("assemble_candidates_from_trait_def(..)");
 
     // Check whether the self-type is itself a projection.
-    let trait_ref = match obligation_trait_ref.self_ty().sty {
-        ty::TyProjection(ref data) => data.trait_ref.clone(),
+    let (def_id, substs) = match obligation_trait_ref.self_ty().sty {
+        ty::TyProjection(ref data) => {
+            (data.trait_ref.def_id, data.trait_ref.substs)
+        }
+        ty::TyAnon(def_id, substs) => (def_id, substs),
         ty::TyInfer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -785,8 +809,8 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
     };
 
     // If so, extract what we know from the trait and try to come up with a good answer.
-    let trait_predicates = selcx.tcx().lookup_predicates(trait_ref.def_id);
-    let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs);
+    let trait_predicates = selcx.tcx().lookup_predicates(def_id);
+    let bounds = trait_predicates.instantiate(selcx.tcx(), substs);
     let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec());
     assemble_candidates_from_predicates(selcx,
                                         obligation,
index 028d05731b64b98eb56ddf8c50a64800599b1cc9..f353c54089db5b6c205c31087d09f67e22e41066 100644 (file)
@@ -1158,20 +1158,17 @@ fn assemble_candidates_from_projected_tys(&mut self,
 
         // before we go into the whole skolemization thing, just
         // quickly check if the self-type is a projection at all.
-        let trait_def_id = match obligation.predicate.0.trait_ref.self_ty().sty {
-            ty::TyProjection(ref data) => data.trait_ref.def_id,
+        match obligation.predicate.0.trait_ref.self_ty().sty {
+            ty::TyProjection(_) | ty::TyAnon(..) => {}
             ty::TyInfer(ty::TyVar(_)) => {
                 span_bug!(obligation.cause.span,
                     "Self=_ should have been handled by assemble_candidates");
             }
-            _ => { return; }
-        };
-
-        debug!("assemble_candidates_for_projected_tys: trait_def_id={:?}",
-               trait_def_id);
+            _ => return
+        }
 
         let result = self.probe(|this, snapshot| {
-            this.match_projection_obligation_against_bounds_from_trait(obligation,
+            this.match_projection_obligation_against_definition_bounds(obligation,
                                                                        snapshot)
         });
 
@@ -1180,7 +1177,7 @@ fn assemble_candidates_from_projected_tys(&mut self,
         }
     }
 
-    fn match_projection_obligation_against_bounds_from_trait(
+    fn match_projection_obligation_against_definition_bounds(
         &mut self,
         obligation: &TraitObligation<'tcx>,
         snapshot: &infer::CombinedSnapshot)
@@ -1190,28 +1187,29 @@ fn match_projection_obligation_against_bounds_from_trait(
             self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
         let (skol_trait_predicate, skol_map) =
             self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot);
-        debug!("match_projection_obligation_against_bounds_from_trait: \
+        debug!("match_projection_obligation_against_definition_bounds: \
                 skol_trait_predicate={:?} skol_map={:?}",
                skol_trait_predicate,
                skol_map);
 
-        let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty {
-            ty::TyProjection(ref data) => &data.trait_ref,
+        let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
+            ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs),
+            ty::TyAnon(def_id, substs) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
-                    "match_projection_obligation_against_bounds_from_trait() called \
+                    "match_projection_obligation_against_definition_bounds() called \
                      but self-ty not a projection: {:?}",
                     skol_trait_predicate.trait_ref.self_ty());
             }
         };
-        debug!("match_projection_obligation_against_bounds_from_trait: \
-                projection_trait_ref={:?}",
-               projection_trait_ref);
+        debug!("match_projection_obligation_against_definition_bounds: \
+                def_id={:?}, substs={:?}",
+               def_id, substs);
 
-        let trait_predicates = self.tcx().lookup_predicates(projection_trait_ref.def_id);
-        let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
-        debug!("match_projection_obligation_against_bounds_from_trait: \
+        let item_predicates = self.tcx().lookup_predicates(def_id);
+        let bounds = item_predicates.instantiate(self.tcx(), substs);
+        debug!("match_projection_obligation_against_definition_bounds: \
                 bounds={:?}",
                bounds);
 
@@ -1226,7 +1224,7 @@ fn match_projection_obligation_against_bounds_from_trait(
                                                     &skol_map,
                                                     snapshot)));
 
-        debug!("match_projection_obligation_against_bounds_from_trait: \
+        debug!("match_projection_obligation_against_definition_bounds: \
                 matching_bound={:?}",
                matching_bound);
         match matching_bound {
@@ -1472,7 +1470,8 @@ fn assemble_candidates_from_default_impls(&mut self,
                     }
                 }
                 ty::TyParam(..) |
-                ty::TyProjection(..) => {
+                ty::TyProjection(..) |
+                ty::TyAnon(..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -1796,7 +1795,7 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 }))
             }
 
-            ty::TyProjection(_) | ty::TyParam(_) => None,
+            ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None,
             ty::TyInfer(ty::TyVar(_)) => Ambiguous,
 
             ty::TyInfer(ty::FreshTy(_))
@@ -1842,7 +1841,8 @@ fn copy_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 Where(ty::Binder(tys.to_vec()))
             }
 
-            ty::TyStruct(..) | ty::TyEnum(..) | ty::TyProjection(..) | ty::TyParam(..) => {
+            ty::TyStruct(..) | ty::TyEnum(..) |
+            ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
             }
@@ -1893,6 +1893,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
             ty::TyTrait(..) |
             ty::TyParam(..) |
             ty::TyProjection(..) |
+            ty::TyAnon(..) |
             ty::TyInfer(ty::TyVar(_)) |
             ty::TyInfer(ty::FreshTy(_)) |
             ty::TyInfer(ty::FreshIntTy(_)) |
@@ -2073,7 +2074,7 @@ fn confirm_projection_candidate(&mut self,
     {
         self.in_snapshot(|this, snapshot| {
             let result =
-                this.match_projection_obligation_against_bounds_from_trait(obligation,
+                this.match_projection_obligation_against_definition_bounds(obligation,
                                                                            snapshot);
             assert!(result);
         })
index 14b0a8070983c84a3628b665e1d07648689768ea..8da7568c558a70b6d16b7fbcc8854122fd02c983 100644 (file)
@@ -240,7 +240,8 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
 
                 ty::TyProjection(..) |
-                ty::TyParam(_) => {
+                ty::TyParam(_) |
+                ty::TyAnon(..) => {
                     TC::All
                 }
 
index a816d26edadf36678d254f83b15f8932e5b4bdc9..13401e91265eb9ac8db3f4ae39490b01ec67d0fd 100644 (file)
@@ -1016,7 +1016,7 @@ pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
             TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
-            TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
+            TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
@@ -1355,6 +1355,10 @@ pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
         self.mk_param(def.space, def.index, def.name)
     }
 
+    pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyAnon(def_id, substs))
+    }
+
     pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> {
         self.trait_items_cache.memoize(trait_did, || {
             let def_ids = self.trait_item_def_ids(trait_did);
index bddc2dbdb7e779e63c6237837ecda20a86ce89cf..66165ec6ff7d06aa179c4c7c5279aa4daadd51ae 100644 (file)
@@ -247,6 +247,7 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
                     "type parameter".to_string()
                 }
             }
+            ty::TyAnon(..) => "anonymized type".to_string(),
             ty::TyError => "type error".to_string(),
         }
     }
index 25f3552b565e720cccd1a0ec86b9bda1b759d1b2..e6f2ba8b650f1c77851ceb6c3eeaaeee93489295 100644 (file)
@@ -30,6 +30,7 @@ pub enum SimplifiedType {
     TraitSimplifiedType(DefId),
     StructSimplifiedType(DefId),
     ClosureSimplifiedType(DefId),
+    AnonSimplifiedType(DefId),
     FunctionSimplifiedType(usize),
     ParameterSimplifiedType,
 }
@@ -98,6 +99,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 None
             }
         }
+        ty::TyAnon(def_id, _) => {
+            Some(AnonSimplifiedType(def_id))
+        }
         ty::TyInfer(_) | ty::TyError => None,
     }
 }
index 44b450784ed2a9c51e87cb1b6d891cbd7cecb234..85b7d66a2eb085e8a1740d66d87387479277f602 100644 (file)
@@ -110,6 +110,11 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_projection_ty(data);
             }
 
+            &ty::TyAnon(_, substs) => {
+                self.add_flags(TypeFlags::HAS_PROJECTION);
+                self.add_substs(substs);
+            }
+
             &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
                 let mut computation = FlagComputation::new();
                 computation.add_substs(principal.0.substs);
index b334964bf489b4e4fac8e9e533e4fc771b887b88..3580013c2a9129aa973bf308a31b5bded98fb2a2 100644 (file)
@@ -695,7 +695,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         // in the normalized form
         if self.just_constrained {
             match t.sty {
-                ty::TyProjection(..) => { return false; }
+                ty::TyProjection(..) | ty::TyAnon(..) => { return false; }
                 _ => { }
             }
         }
index 74c05feb6d16a5822464da1319f591f3b8d62b69..bfe6303d8a328a7bf8793d78a0c9a95853475a72 100644 (file)
@@ -188,7 +188,8 @@ pub fn push_item_path<T>(self, buffer: &mut T, def_id: DefId)
             data @ DefPathData::Initializer |
             data @ DefPathData::MacroDef(..) |
             data @ DefPathData::ClosureExpr |
-            data @ DefPathData::Binding(..) => {
+            data @ DefPathData::Binding(..) |
+            data @ DefPathData::ImplTrait => {
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
                 self.push_item_path(buffer, parent_def_id);
                 buffer.push(&data.as_interned_str());
@@ -345,6 +346,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
         ty::TyFnPtr(_) |
         ty::TyProjection(_) |
         ty::TyParam(_) |
+        ty::TyAnon(..) |
         ty::TyInfer(_) |
         ty::TyError |
         ty::TyFloat(_) => None,
index e27a9d79b62d110188ef91343008200cb70d65ee..d73e412f55f267c7b1e40d5c18ccb5890aa209ff 100644 (file)
@@ -594,7 +594,7 @@ pub fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                 Struct::non_zero_field_path(infcx, Some(ety).into_iter())
             }
 
-            (_, &ty::TyProjection(_)) => {
+            (_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
                 let normalized = normalize_associated_type(infcx, ty);
                 if ty == normalized {
                     return Ok(None);
@@ -1108,7 +1108,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
             }
 
             // Types with no meaningful known layout.
-            ty::TyProjection(_) => {
+            ty::TyProjection(_) | ty::TyAnon(..) => {
                 let normalized = normalize_associated_type(infcx, ty);
                 if ty == normalized {
                     return Err(LayoutError::Unknown(ty));
@@ -1332,7 +1332,7 @@ pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
                 }
             }
 
-            ty::TyProjection(_) => {
+            ty::TyProjection(_) | ty::TyAnon(..) => {
                 let normalized = normalize_associated_type(infcx, ty);
                 if ty == normalized {
                     Err(err)
index a7c534198923b7a1183bb7f9b7f0a0d65dcd24bf..fe5c602575beaa03827a5800242acae9c21b81bf 100644 (file)
@@ -1885,7 +1885,7 @@ fn sized_constraint_for_ty(
                 }
             }
 
-            TyProjection(..) => {
+            TyProjection(..) | TyAnon(..) => {
                 // must calculate explicitly.
                 // FIXME: consider special-casing always-Sized projections
                 vec![ty]
index 9ae3325c2588f5f7749206f780b1be0a72b609ed..df907c26f71420b3e091c36ab02c96d5e5df394a 100644 (file)
@@ -174,6 +174,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             ty::TyEnum(..) |        // OutlivesNominalType
             ty::TyStruct(..) |      // OutlivesNominalType
             ty::TyBox(..) |         // OutlivesNominalType (ish)
+            ty::TyAnon(..) |        // OutlivesNominalType (ish)
             ty::TyStr |             // OutlivesScalar (ish)
             ty::TyArray(..) |       // ...
             ty::TySlice(..) |       // ...
index 80c727f022127745809e6e299b2725486a76d0fb..f9263947c0379c099562fc55c35046ffc025dd0e 100644 (file)
@@ -582,6 +582,13 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name))
         }
 
+        (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs))
+            if a_def_id == b_def_id =>
+        {
+            let substs = relate_substs(relation, None, a_substs, b_substs)?;
+            Ok(tcx.mk_anon(a_def_id, substs))
+        }
+
         _ =>
         {
             Err(TypeError::Sorts(expected_found(relation, &a, &b)))
index 16a54c20925deda7b8417a3747be29e6e0289bec..e542e8f237f1a1c88097ba766da88ca2a475476c 100644 (file)
@@ -485,6 +485,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             ty::TyStruct(did, substs) => ty::TyStruct(did, substs.fold_with(folder)),
             ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)),
             ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
+            ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
             ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
             ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
             ty::TyParam(..) => self.sty.clone(),
@@ -513,6 +514,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             ty::TyStruct(_did, ref substs) => substs.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
             ty::TyProjection(ref data) => data.visit_with(visitor),
+            ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
             ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
             ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
             ty::TyParam(..) => false,
index 7c69618068a6b7c89597d3ae6cf23270d622e693..912cb39face0a6d9ec910ce33194618826999551 100644 (file)
@@ -166,6 +166,12 @@ pub enum TypeVariants<'tcx> {
     /// `<T as Trait<..>>::N`.
     TyProjection(ProjectionTy<'tcx>),
 
+    /// Anonymized (`impl Trait`) type found in a return type.
+    /// The DefId comes from the `impl Trait` ast::Ty node, and the
+    /// substitutions are for the generics of the function in question.
+    /// After typeck, the concrete type can be found in the `tcache` map.
+    TyAnon(DefId, &'tcx Substs<'tcx>),
+
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
     TyParam(ParamTy),
 
@@ -1232,7 +1238,8 @@ pub fn regions(&self) -> Vec<ty::Region> {
                 v
             }
             TyEnum(_, substs) |
-            TyStruct(_, substs) => {
+            TyStruct(_, substs) |
+            TyAnon(_, substs) => {
                 substs.regions.as_slice().to_vec()
             }
             TyClosure(_, ref substs) => {
index 07439d7104af4348ed8cd350b5cca5a860c70eee..e7bcfbfd823453dd2893fae3044744e7a8ee4b5c 100644 (file)
@@ -437,6 +437,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             TyRawPtr(m) |
             TyRef(_, m) => self.hash(m.mutbl),
             TyClosure(def_id, _) |
+            TyAnon(def_id, _) |
             TyFnDef(def_id, _, _) => self.def_id(def_id),
             TyFnPtr(f) => {
                 self.hash(f.unsafety);
@@ -559,7 +560,7 @@ pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }) => Some(true),
 
             TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
-            TyClosure(..) | TyEnum(..) | TyStruct(..) |
+            TyClosure(..) | TyEnum(..) | TyStruct(..) | TyAnon(..) |
             TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
         }.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
 
@@ -600,7 +601,7 @@ fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             TyStr | TyTrait(..) | TySlice(_) => Some(false),
 
             TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
-            TyInfer(..) | TyError => None
+            TyInfer(..) | TyAnon(..) | TyError => None
         }.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
 
         if !self.has_param_types() && !self.has_self_ty() {
index fa7c9b782311f955a1c4c637586c13c77be2f05e..ebc2642678bfd80bb3b9d0a794dd0704dc88c263 100644 (file)
@@ -88,7 +88,8 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
             }).collect::<Vec<_>>());
         }
         ty::TyEnum(_, ref substs) |
-        ty::TyStruct(_, ref substs) => {
+        ty::TyStruct(_, ref substs) |
+        ty::TyAnon(_, ref substs) => {
             push_reversed(stack, substs.types.as_slice());
         }
         ty::TyClosure(_, ref substs) => {
index 37ba936d2f42a73f71a6e3193cdfbf183345d6e5..f6ddfe60d40e6804c7ffee6f72b0276a303bcbe6 100644 (file)
@@ -383,6 +383,12 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     // types appearing in the fn signature
                 }
 
+                ty::TyAnon(..) => {
+                    // all of the requirements on type parameters
+                    // should've been checked by the instantiation
+                    // of whatever returned this exact `impl Trait`.
+                }
+
                 ty::TyTrait(ref data) => {
                     // WfObject
                     //
index 60977a80946ff6e23950ef024d739eb4764a45a1..a17c01068139a376cd6c5b1aaa83d1a16e1fb57a 100644 (file)
@@ -907,6 +907,37 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             }
             TyTrait(ref data) => write!(f, "{}", data),
             ty::TyProjection(ref data) => write!(f, "{}", data),
+            ty::TyAnon(def_id, substs) => {
+                ty::tls::with(|tcx| {
+                    // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+                    // by looking up the projections associated with the def_id.
+                    let item_predicates = tcx.lookup_predicates(def_id);
+                    let substs = tcx.lift(&substs).unwrap_or_else(|| {
+                        tcx.mk_substs(subst::Substs::empty())
+                    });
+                    let bounds = item_predicates.instantiate(tcx, substs);
+
+                    let mut first = true;
+                    let mut is_sized = false;
+                    write!(f, "impl")?;
+                    for predicate in bounds.predicates.into_vec() {
+                        if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
+                            // Don't print +Sized, but rather +?Sized if absent.
+                            if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() {
+                                is_sized = true;
+                                continue;
+                            }
+
+                            write!(f, "{}{}", if first { " " } else { "+" }, trait_ref)?;
+                            first = false;
+                        }
+                    }
+                    if !is_sized {
+                        write!(f, "{}?Sized", if first { " " } else { "+" })?;
+                    }
+                    Ok(())
+                })
+            }
             TyStr => write!(f, "str"),
             TyClosure(did, substs) => ty::tls::with(|tcx| {
                 write!(f, "[closure")?;
index 09dd8748b30c5f343c18e205313c3c227272406d..b9861c309dbec985d3e467eb9c9032219ecbf336 100644 (file)
@@ -596,7 +596,7 @@ fn check_type_for_ffi(&self,
             }
 
             ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
-            ty::TyClosure(..) | ty::TyProjection(..) |
+            ty::TyClosure(..) | ty::TyProjection(..) | ty::TyAnon(..) |
             ty::TyFnDef(..) => {
                 bug!("Unexpected type in foreign function")
             }
index 2444d669f7f32345c8c95ec007130f17123a091f..285ca2e4d4d4de2367259410dd9f09a3e291e73c 100644 (file)
@@ -41,6 +41,7 @@ pub enum DefPathData {
     StructCtor,
     Initializer,
     Binding,
+    ImplTrait,
 }
 
 pub fn simplify_def_key(key: hir_map::DefKey) -> DefKey {
@@ -72,6 +73,7 @@ fn simplify_def_path_data(data: hir_map::DefPathData) -> DefPathData {
         hir_map::DefPathData::StructCtor => DefPathData::StructCtor,
         hir_map::DefPathData::Initializer => DefPathData::Initializer,
         hir_map::DefPathData::Binding(_) => DefPathData::Binding,
+        hir_map::DefPathData::ImplTrait => DefPathData::ImplTrait,
     }
 }
 
@@ -103,5 +105,6 @@ fn recover_def_path_data(data: DefPathData, name: Option<InternedString>) -> hir
         DefPathData::StructCtor => hir_map::DefPathData::StructCtor,
         DefPathData::Initializer => hir_map::DefPathData::Initializer,
         DefPathData::Binding => hir_map::DefPathData::Binding(name.unwrap()),
+        DefPathData::ImplTrait => hir_map::DefPathData::ImplTrait,
     }
 }
index 119640af463aa8bf768dddfc23ede46bd996df88..1dcec35adb285554642a41712abcc6265d736166 100644 (file)
@@ -445,6 +445,13 @@ pub fn parse_ty(&mut self) -> Ty<'tcx> {
                 let name = token::intern(&self.parse_str(']'));
                 return tcx.mk_projection(trait_ref, name);
             }
+            'A' => {
+                assert_eq!(self.next(), '[');
+                let def_id = self.parse_def();
+                let substs = self.parse_substs();
+                assert_eq!(self.next(), ']');
+                return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs));
+            }
             'e' => {
                 return tcx.types.err;
             }
index 3484a8b75dded7105c12e44d98d5e3b11ad7ccd2..c2e91eba0d2523a600d322ccf35f1d548375958a 100644 (file)
@@ -170,6 +170,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
             enc_trait_ref(w, cx, data.trait_ref);
             write!(w, "{}]", data.item_name);
         }
+        ty::TyAnon(def_id, substs) => {
+            write!(w, "A[{}|", (cx.ds)(cx.tcx, def_id));
+            enc_substs(w, cx, substs);
+            write!(w, "]");
+        }
         ty::TyError => {
             write!(w, "e");
         }
index 58b49f6944fa7d69dbd2d2dff6e6f84ad4ba3170..4a6dbb2bdae56d746926987e2a7921357e1eadbb 100644 (file)
@@ -796,6 +796,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         ty::TyProjection(_) |
         ty::TyParam(_)      |
         ty::TyInfer(_)      |
+        ty::TyAnon(..)      |
         ty::TyError         => {
             bug!("encountered unexpected type");
         }
index 63f460e4693d56be227fb0daf7a09d20018d4afa..bee2667c71f9db974660ff39bde162776e9379b3 100644 (file)
@@ -150,6 +150,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyError |
         ty::TyInfer(_) |
         ty::TyProjection(..) |
+        ty::TyAnon(..) |
         ty::TyParam(_) => {
             bug!("debuginfo: Trying to create type name for \
                 unexpected type: {:?}", t);
index d0e00a6d593a5edf18742ebdae8156e467ac9ea0..187ffe353fdcb5f596bd87dbfb0994feaa8e8c79 100644 (file)
@@ -536,7 +536,8 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::TyError |
         ty::TyInfer(_) |
         ty::TyProjection(..) |
-        ty::TyParam(_) => {
+        ty::TyParam(_) |
+        ty::TyAnon(..) => {
             bug!("debuginfo: Trying to create type name for \
                   unexpected type: {:?}", t);
         }
index 496870d6c27a1aa5242c6050a1a9c34bf442ebf5..cde53f6fa899cb9c89a33977e8e42070764b6f19 100644 (file)
@@ -112,7 +112,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => {
+        ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) |
+        ty::TyAnon(..) | ty::TyError => {
             bug!("fictitious type {:?} in sizing_type_of()", t)
         }
         ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => bug!()
@@ -339,10 +340,11 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           }
       }
 
-      ty::TyInfer(..) => bug!("type_of with TyInfer"),
-      ty::TyProjection(..) => bug!("type_of with TyProjection"),
-      ty::TyParam(..) => bug!("type_of with ty_param"),
-      ty::TyError => bug!("type_of with TyError"),
+      ty::TyInfer(..) |
+      ty::TyProjection(..) |
+      ty::TyParam(..) |
+      ty::TyAnon(..) |
+      ty::TyError => bug!("type_of with {:?}", t),
     };
 
     debug!("--> mapped t={:?} to llty={:?}", t, llty);
index 07595c5dbe1144cb987de5165a121575e420234a..f1d2bdb0117a87068dde5d9fe9224765d08af3f2 100644 (file)
@@ -56,6 +56,7 @@
 use middle::resolve_lifetime as rl;
 use rustc::lint;
 use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
+use rustc::ty::subst::VecPerParamSpace;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
@@ -1745,6 +1746,24 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
             hir::TyPolyTraitRef(ref bounds) => {
                 self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
             }
+            hir::TyImplTrait(ref bounds) => {
+                use collect::{compute_bounds, SizedByDefault};
+
+                // Create the anonymized type.
+                let def_id = tcx.map.local_def_id(ast_ty.id);
+                let substs = tcx.mk_substs(Substs::empty());
+                let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
+
+                // Collect the bounds, i.e. the `Trait` in `impl Trait`.
+                let bounds = compute_bounds(self, ty, bounds, SizedByDefault::Yes, ast_ty.span);
+                let predicates = tcx.lift_to_global(&bounds.predicates(tcx, ty)).unwrap();
+                let predicates = ty::GenericPredicates {
+                    predicates: VecPerParamSpace::new(vec![], vec![], predicates)
+                };
+                tcx.predicates.borrow_mut().insert(def_id, predicates);
+
+                ty
+            }
             hir::TyPath(ref maybe_qself, ref path) => {
                 debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
                 let path_res = tcx.expect_resolution(ast_ty.id);
index 0791c76c7121f9ee5039015e2b6a3f0e4133b703..f65e15430daf75c7de17357c61f1bab01cc2d49a 100644 (file)
@@ -499,7 +499,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
         }
 
         // these are always dtorck
-        ty::TyTrait(..) | ty::TyProjection(_) => bug!(),
+        ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
     }
 }
 
@@ -509,7 +509,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyEnum(def, _) | ty::TyStruct(def, _) => {
             def.is_dtorck(tcx)
         }
-        ty::TyTrait(..) | ty::TyProjection(..) => {
+        ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
             debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
             true
         },
index 648d1f42fb5208322843c8a3d41791ae357ef2aa..99f1b13d4e4ab422a6c218dd0c202da6812b037e 100644 (file)
@@ -786,16 +786,19 @@ fn assemble_projection_candidates(&mut self,
             debug!("assemble_projection_candidates: step={:?}",
                    step);
 
-            let projection_trait_ref = match step.self_ty.sty {
-                ty::TyProjection(ref data) => &data.trait_ref,
+            let (def_id, substs) = match step.self_ty.sty {
+                ty::TyProjection(ref data) => {
+                    (data.trait_ref.def_id, data.trait_ref.substs)
+                }
+                ty::TyAnon(def_id, substs) => (def_id, substs),
                 _ => continue,
             };
 
-            debug!("assemble_projection_candidates: projection_trait_ref={:?}",
-                   projection_trait_ref);
+            debug!("assemble_projection_candidates: def_id={:?} substs={:?}",
+                   def_id, substs);
 
-            let trait_predicates = self.tcx.lookup_predicates(projection_trait_ref.def_id);
-            let bounds = trait_predicates.instantiate(self.tcx, projection_trait_ref.substs);
+            let trait_predicates = self.tcx.lookup_predicates(def_id);
+            let bounds = trait_predicates.instantiate(self.tcx, substs);
             let predicates = bounds.predicates.into_vec();
             debug!("assemble_projection_candidates: predicates={:?}",
                    predicates);
@@ -806,9 +809,8 @@ fn assemble_projection_candidates(&mut self,
             {
                 let bound = self.erase_late_bound_regions(&poly_bound);
 
-                debug!("assemble_projection_candidates: projection_trait_ref={:?} bound={:?}",
-                       projection_trait_ref,
-                       bound);
+                debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}",
+                       def_id, substs, bound);
 
                 if self.can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
                     let xform_self_ty = self.xform_self_ty(&item,
index 3e6df0ca5bbbd0b69b492d7e345002198aac087a..13deac57330e3b28e5c44914b07b439d29d905cc 100644 (file)
@@ -27,7 +27,7 @@
 use rustc::ty::{TyRef, TyStruct, TyTrait, TyTuple};
 use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
 use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
-use rustc::ty::TyProjection;
+use rustc::ty::{TyProjection, TyAnon};
 use rustc::ty::util::CopyImplementationError;
 use middle::free_region::FreeRegionMap;
 use CrateCtxt;
@@ -89,7 +89,7 @@ fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
                 None
             }
 
-            TyInfer(..) | TyClosure(..) => {
+            TyInfer(..) | TyClosure(..) | TyAnon(..) => {
                 // `ty` comes from a user declaration so we should only expect types
                 // that the user can type
                 span_bug!(
index f68d902ef36ab9c8fe80e1d3d058cb48be35277a..480a166f56a966b0abfe4d441721c79d9cefbcf1 100644 (file)
@@ -1694,10 +1694,10 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
-fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                           bounds: &mut ty::BuiltinBounds,
-                           ast_bounds: &[hir::TyParamBound],
-                           span: Span)
+fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                       bounds: &mut ty::BuiltinBounds,
+                                       ast_bounds: &[hir::TyParamBound],
+                                       span: Span)
 {
     let tcx = astconv.tcx();
 
@@ -2038,17 +2038,17 @@ fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     }
 }
 
-enum SizedByDefault { Yes, No, }
+pub enum SizedByDefault { Yes, No, }
 
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
-fn compute_bounds<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                        param_ty: ty::Ty<'tcx>,
-                        ast_bounds: &[hir::TyParamBound],
-                        sized_by_default: SizedByDefault,
-                        span: Span)
-                        -> Bounds<'tcx>
+pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                        param_ty: ty::Ty<'tcx>,
+                                        ast_bounds: &[hir::TyParamBound],
+                                        sized_by_default: SizedByDefault,
+                                        span: Span)
+                                        -> Bounds<'tcx>
 {
     let mut bounds =
         conv_param_bounds(astconv,
@@ -2098,11 +2098,11 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
     }
 }
 
-fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                             param_ty: Ty<'tcx>,
-                             trait_ref: &hir::PolyTraitRef,
-                             projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-                             -> ty::PolyTraitRef<'tcx>
+fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                         param_ty: Ty<'tcx>,
+                                         trait_ref: &hir::PolyTraitRef,
+                                         projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+                                         -> ty::PolyTraitRef<'tcx>
 {
     AstConv::instantiate_poly_trait_ref(astconv,
                                         &ExplicitRscope,
@@ -2111,11 +2111,11 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                                         projections)
 }
 
-fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                              span: Span,
-                              param_ty: ty::Ty<'tcx>,
-                              ast_bounds: &[hir::TyParamBound])
-                              -> Bounds<'tcx>
+fn conv_param_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                       span: Span,
+                                       param_ty: ty::Ty<'tcx>,
+                                       ast_bounds: &[hir::TyParamBound])
+                                       -> Bounds<'tcx>
 {
     let tcx = astconv.tcx();
     let PartitionedBounds {
index 7909584bfabdf560b4c11ffe97b08f3133a2667d..7d3bd095a3a888c930b813f17654334ae4e92ded 100644 (file)
@@ -45,7 +45,7 @@ struct ParameterCollector {
 impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         match t.sty {
-            ty::TyProjection(..) if !self.include_nonconstraining => {
+            ty::TyProjection(..) | ty::TyAnon(..) if !self.include_nonconstraining => {
                 // projections are not injective
                 return false;
             }
index 01a310da25ddd26a364f0526a51df43c7e8f844f..b9e0b4a10ea45ec9396a186cd103800ac0b085c1 100644 (file)
@@ -326,7 +326,7 @@ fn add_constraints_from_ty(&mut self,
                 /* leaf type -- noop */
             }
 
-            ty::TyClosure(..) => {
+            ty::TyClosure(..) | ty::TyAnon(..) => {
                 bug!("Unexpected closure type in variance computation");
             }
 
index 37af778d5556876b5e599488ea01ca8b554b30a8..73bc647fa9ffbcf63d8129fb30d8f66e452a5502 100644 (file)
@@ -1867,6 +1867,18 @@ fn clean(&self, cx: &DocContext) -> Type {
 
             ty::TyParam(ref p) => Generic(p.name.to_string()),
 
+            ty::TyAnon(def_id, substs) => {
+                // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+                // by looking up the projections associated with the def_id.
+                let item_predicates = cx.tcx().lookup_predicates(def_id);
+                let substs = cx.tcx().lift(&substs).unwrap();
+                let bounds = item_predicates.instantiate(cx.tcx(), substs);
+                let predicates = bounds.predicates.into_vec();
+                ImplTrait(predicates.into_iter().filter_map(|predicate| {
+                    predicate.to_opt_poly_trait_ref().clean(cx)
+                }).collect())
+            }
+
             ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
             ty::TyInfer(..) => panic!("TyInfer"),