]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #48523 - varkor:generics-ty-generalisations, r=nikomatsakis
authorbors <bors@rust-lang.org>
Tue, 15 May 2018 23:03:04 +0000 (23:03 +0000)
committerbors <bors@rust-lang.org>
Tue, 15 May 2018 23:03:04 +0000 (23:03 +0000)
The Great Generics Generalisation: Ty Edition

Part of the generic parameter refactoring effort, split off from https://github.com/rust-lang/rust/pull/48149. Contains the `ty`-relative refactoring.

r? @eddyb

48 files changed:
src/librustc/hir/lowering.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/anon_types/mod.rs
src/librustc/infer/mod.rs
src/librustc/lib.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/traits/util.rs
src/librustc/ty/context.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_driver/test.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_privacy/lib.rs
src/librustc_traits/dropck_outlives.rs
src/librustc_traits/lib.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/outlives/implicit_infer.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/test/ui/on-unimplemented/bad-annotation.rs
src/test/ui/on-unimplemented/bad-annotation.stderr

index 51f0c1d7047c91613c76e3ece8213546ec6db877..be9c5d2d334ae442d6bb78f8913316ef63f924bb 100644 (file)
@@ -1459,10 +1459,9 @@ fn lower_qpath(
                             return n;
                         }
                         assert!(!def_id.is_local());
-                        let n = self.cstore
-                            .item_generics_cloned_untracked(def_id, self.sess)
-                            .regions
-                            .len();
+                        let item_generics =
+                            self.cstore.item_generics_cloned_untracked(def_id, self.sess);
+                        let n = item_generics.own_counts().lifetimes;
                         self.type_def_lifetime_params.insert(def_id, n);
                         n
                     });
index 1036eae9b856b0092ec949d94aa3655a33dcfb17..31dce2a14c2b783869720488634fb89ed4a7ac5a 100644 (file)
@@ -735,54 +735,40 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           hasher: &mut StableHasher<W>) {
         let ty::Generics {
             parent,
-            parent_regions,
-            parent_types,
-            ref regions,
-            ref types,
+            ref parent_count,
+            ref params,
 
-            // Reverse map to each `TypeParameterDef`'s `index` field, from
+            // Reverse map to each `TypeParamDef`'s `index` field, from
             // `def_id.index` (`def_id.krate` is the same as the item's).
-            type_param_to_index: _, // Don't hash this
+            param_def_id_to_index: _, // Don't hash this
             has_self,
             has_late_bound_regions,
         } = *self;
 
         parent.hash_stable(hcx, hasher);
-        parent_regions.hash_stable(hcx, hasher);
-        parent_types.hash_stable(hcx, hasher);
-        regions.hash_stable(hcx, hasher);
-        types.hash_stable(hcx, hasher);
+        parent_count.hash_stable(hcx, hasher);
+        params.hash_stable(hcx, hasher);
         has_self.hash_stable(hcx, hasher);
         has_late_bound_regions.hash_stable(hcx, hasher);
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>>
-for ty::RegionParameterDef {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        let ty::RegionParameterDef {
-            name,
-            def_id,
-            index,
-            pure_wrt_drop
-        } = *self;
-
-        name.hash_stable(hcx, hasher);
-        def_id.hash_stable(hcx, hasher);
-        index.hash_stable(hcx, hasher);
-        pure_wrt_drop.hash_stable(hcx, hasher);
-    }
-}
+impl_stable_hash_for!(enum ty::GenericParamDefKind {
+    Lifetime,
+    Type(ty)
+});
 
-impl_stable_hash_for!(struct ty::TypeParameterDef {
+impl_stable_hash_for!(struct ty::GenericParamDef {
     name,
     def_id,
     index,
+    pure_wrt_drop,
+    kind
+});
+
+impl_stable_hash_for!(struct ty::TypeParamDef {
     has_default,
     object_lifetime_default,
-    pure_wrt_drop,
     synthetic
 });
 
index 725ea9734abf4b2540dee577c378dd90ebe4d334..d681e2e3d34b9b735c634a70c2c420749ff5dbc6 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast;
 use traits::{self, PredicateObligation};
-use ty::{self, Ty, TyCtxt};
+use ty::{self, Ty, TyCtxt, GenericParamDefKind};
 use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
 use ty::outlives::Component;
 use ty::subst::{Kind, Substs, UnpackedKind};
@@ -313,12 +313,13 @@ fn constrain_anon_type<FRR: FreeRegionRelations<'tcx>>(
         // `['a]` for the first impl trait and `'b` for the
         // second.
         let mut least_region = None;
-        for region_def in &abstract_type_generics.regions {
-            // Find the index of this region in the list of substitutions.
-            let index = region_def.index as usize;
-
+        for param in &abstract_type_generics.params {
+            match param.kind {
+                GenericParamDefKind::Lifetime => {}
+                _ => continue
+            }
             // Get the value supplied for this region from the substs.
-            let subst_arg = anon_defn.substs.region_at(index);
+            let subst_arg = anon_defn.substs.region_at(param.index as usize);
 
             // Compute the least upper bound of it with the other regions.
             debug!("constrain_anon_types: least_region={:?}", least_region);
@@ -616,10 +617,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 // during trans.
 
                 let generics = self.tcx.generics_of(def_id);
-                let parent_len = generics.parent_count();
                 let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
                     |(index, &kind)| {
-                        if index < parent_len {
+                        if index < generics.parent_count {
                             // Accommodate missing regions in the parent kinds...
                             self.fold_kind_mapping_missing_regions_to_empty(kind)
                         } else {
index c62e7f8d9b6350a8a20350625a08c0b9f8039909..1cc65dcfd1027003ae9258d07fe993d21e0c32e8 100644 (file)
@@ -21,9 +21,9 @@
 use middle::free_region::RegionRelations;
 use middle::region;
 use middle::lang_items;
-use ty::subst::Substs;
+use ty::subst::{Kind, Substs};
 use ty::{TyVid, IntVid, FloatVid};
-use ty::{self, Ty, TyCtxt};
+use ty::{self, Ty, TyCtxt, GenericParamDefKind};
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::TypeFoldable;
 use ty::relate::RelateResult;
@@ -905,34 +905,35 @@ pub fn next_nll_region_var(&self, origin: NLLRegionVariableOrigin)
         self.next_region_var(RegionVariableOrigin::NLL(origin))
     }
 
-    /// Create a region inference variable for the given
-    /// region parameter definition.
-    pub fn region_var_for_def(&self,
-                              span: Span,
-                              def: &ty::RegionParameterDef)
-                              -> ty::Region<'tcx> {
-        self.next_region_var(EarlyBoundRegion(span, def.name))
-    }
-
-    /// Create a type inference variable for the given
-    /// type parameter definition. The substitutions are
-    /// for actual parameters that may be referred to by
-    /// the default of this type parameter, if it exists.
-    /// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
-    /// used in a path such as `Foo::<T, U>::new()` will
-    /// use an inference variable for `C` with `[T, U]`
-    /// as the substitutions for the default, `(T, U)`.
-    pub fn type_var_for_def(&self,
-                            span: Span,
-                            def: &ty::TypeParameterDef)
-                            -> Ty<'tcx> {
-        let ty_var_id = self.type_variables
-                            .borrow_mut()
-                            .new_var(self.universe(),
-                                     false,
-                                     TypeVariableOrigin::TypeParameterDefinition(span, def.name));
-
-        self.tcx.mk_var(ty_var_id)
+    pub fn var_for_def(&self,
+                       span: Span,
+                       param: &ty::GenericParamDef)
+                       -> Kind<'tcx> {
+        match param.kind {
+            GenericParamDefKind::Lifetime => {
+                // Create a region inference variable for the given
+                // region parameter definition.
+                self.next_region_var(EarlyBoundRegion(span, param.name)).into()
+            }
+            GenericParamDefKind::Type(_) => {
+                // Create a type inference variable for the given
+                // type parameter definition. The substitutions are
+                // for actual parameters that may be referred to by
+                // the default of this type parameter, if it exists.
+                // E.g. `struct Foo<A, B, C = (A, B)>(...);` when
+                // used in a path such as `Foo::<T, U>::new()` will
+                // use an inference variable for `C` with `[T, U]`
+                // as the substitutions for the default, `(T, U)`.
+                let ty_var_id =
+                    self.type_variables
+                        .borrow_mut()
+                        .new_var(self.universe(),
+                                    false,
+                                    TypeVariableOrigin::TypeParameterDefinition(span, param.name));
+
+                self.tcx.mk_var(ty_var_id).into()
+            }
+        }
     }
 
     /// Given a set of generics defined on a type or impl, returns a substitution mapping each
@@ -941,10 +942,8 @@ pub fn fresh_substs_for_item(&self,
                                  span: Span,
                                  def_id: DefId)
                                  -> &'tcx Substs<'tcx> {
-        Substs::for_item(self.tcx, def_id, |def, _| {
-            self.region_var_for_def(span, def)
-        }, |def, _| {
-            self.type_var_for_def(span, def)
+        Substs::for_item(self.tcx, def_id, |param, _| {
+            self.var_for_def(span, param)
         })
     }
 
index 2a288ae522aac16ddb25c0e0ac41154f93d718f4..26ac9d6ee9ea6798f8cd99d63c62250f018ec84a 100644 (file)
@@ -49,6 +49,7 @@
 #![cfg_attr(stage0, feature(dyn_trait))]
 #![feature(from_ref)]
 #![feature(fs_read_write)]
+#![feature(iterator_find_map)]
 #![cfg_attr(windows, feature(libc))]
 #![cfg_attr(stage0, feature(macro_lifetime_matcher))]
 #![feature(macro_vis_matcher)]
index 8c19a19523275d226692e95be3fa0d1349ed5323..900fbdfdeadb3c58af9193f68128f55125d475d6 100644 (file)
@@ -20,7 +20,7 @@
 use hir::map::Map;
 use hir::ItemLocalId;
 use hir::LifetimeName;
-use ty::{self, TyCtxt};
+use ty::{self, TyCtxt, GenericParamDefKind};
 
 use errors::DiagnosticBuilder;
 use rustc::lint;
@@ -667,8 +667,8 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                 for lt_def in generics.lifetimes() {
                     let (lt_name, region) = Region::early(&self.tcx.hir, &mut index, &lt_def);
                     if let hir::LifetimeName::Underscore = lt_name {
-                        // Pick the elided lifetime "definition" if one exists and use it to make an
-                        // elision scope.
+                        // Pick the elided lifetime "definition" if one exists and use it to make
+                        // an elision scope.
                         elision = Some(region);
                     } else {
                         lifetimes.insert(lt_name, region);
@@ -1659,9 +1659,16 @@ fn visit_segment_parameters(
                     .entry(def_id)
                     .or_insert_with(|| {
                         tcx.generics_of(def_id)
-                            .types
+                            .params
                             .iter()
-                            .map(|def| def.object_lifetime_default)
+                            .filter_map(|param| {
+                                match param.kind {
+                                    GenericParamDefKind::Type(ty) => {
+                                        Some(ty.object_lifetime_default)
+                                    }
+                                    GenericParamDefKind::Lifetime => None,
+                                }
+                            })
                             .collect()
                     })
             };
index 5d708f60604f1599f268b1a3ff0875df82aac949..227cba40d146388a016431509201bd3a522f3c94 100644 (file)
@@ -222,9 +222,14 @@ pub fn find_auto_trait_generics<A>(
             });
 
             let names_map: FxHashSet<String> = generics
-                .regions
+                .params
                 .iter()
-                .map(|l| l.name.to_string())
+                .filter_map(|param| {
+                    match param.kind {
+                        ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
+                        _ => None
+                    }
+                })
                 .collect();
 
             let body_ids: FxHashSet<_> = infcx
index f6ec01546c18d31ca457c75028db21b1540c994e..3e7f3af0358535c93abfee6a180a8f589b211580 100644 (file)
@@ -36,6 +36,7 @@
 use syntax::ast;
 use session::DiagnosticMessageId;
 use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use ty::GenericParamDefKind;
 use ty::error::ExpectedFound;
 use ty::fast_reject;
 use ty::fold::TypeFolder;
@@ -378,12 +379,15 @@ fn on_unimplemented_note(
             flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
         }
 
-        for param in generics.types.iter() {
+        for param in generics.params.iter() {
+            let value = match param.kind {
+                GenericParamDefKind::Type(_) => {
+                    trait_ref.substs[param.index as usize].to_string()
+                },
+                GenericParamDefKind::Lifetime => continue,
+            };
             let name = param.name.to_string();
-            let ty = trait_ref.substs.type_for_def(param);
-            let ty_str = ty.to_string();
-            flags.push((name.clone(),
-                        Some(ty_str.clone())));
+            flags.push((name, Some(value)));
         }
 
         if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {
index a765ffe2396bf471db0e385e17a0bc36286bd5a6..154c6815bb666174d3d7e67dcda7c939c3b5bf35 100644 (file)
@@ -23,7 +23,7 @@
 use middle::region;
 use middle::const_val::ConstEvalErr;
 use ty::subst::Substs;
-use ty::{self, AdtKind, Slice, Ty, TyCtxt, TypeFoldable, ToPredicate};
+use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
 use ty::error::{ExpectedFound, TypeError};
 use infer::{InferCtxt};
 
@@ -841,10 +841,14 @@ fn vtable_methods<'a, 'tcx>(
                 // the method may have some early-bound lifetimes, add
                 // regions for those
                 let substs = trait_ref.map_bound(|trait_ref| {
-                    Substs::for_item(
-                        tcx, def_id,
-                        |_, _| tcx.types.re_erased,
-                        |def, _| trait_ref.substs.type_for_def(def))
+                    Substs::for_item(tcx, def_id, |param, _| {
+                        match param.kind {
+                            GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
+                            GenericParamDefKind::Type(_) => {
+                                trait_ref.substs[param.index as usize]
+                            }
+                        }
+                    })
                 });
 
                 // the trait type may have higher-ranked lifetimes in it;
index c0d5a337cee3a1ca018026856bb058633e67e128..6c67c10dc69cf490dd3120bb064e5cc90ea5def4 100644 (file)
@@ -284,7 +284,7 @@ fn virtual_call_violation_for_method(self,
         }
 
         // We can't monomorphize things like `fn foo<A>(...)`.
-        if !self.generics_of(method.def_id).types.is_empty() {
+        if self.generics_of(method.def_id).own_counts().types != 0 {
             return Some(MethodViolationCode::Generic);
         }
 
@@ -387,7 +387,6 @@ fn contains_illegal_self_type_reference(self,
 }
 
 pub(super) fn is_object_safe_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                         trait_def_id: DefId)
-                                         -> bool {
+                                                trait_def_id: DefId) -> bool {
     tcx.object_safety_violations(trait_def_id).is_empty()
 }
index 3cf7af30b3d551a0442f509f2a5279f2494cd5a3..539f40cf3efb5a061440bfc4c419a0837bffd5ab 100644 (file)
@@ -11,7 +11,7 @@
 use fmt_macros::{Parser, Piece, Position};
 
 use hir::def_id::DefId;
-use ty::{self, TyCtxt};
+use ty::{self, TyCtxt, GenericParamDefKind};
 use util::common::ErrorReported;
 use util::nodemap::FxHashMap;
 
@@ -243,7 +243,6 @@ fn verify(&self,
         let name = tcx.item_name(trait_def_id);
         let generics = tcx.generics_of(trait_def_id);
         let parser = Parser::new(&self.0);
-        let types = &generics.types;
         let mut result = Ok(());
         for token in parser {
             match token {
@@ -254,13 +253,13 @@ fn verify(&self,
                     // `{ThisTraitsName}` is allowed
                     Position::ArgumentNamed(s) if s == name => (),
                     // So is `{A}` if A is a type parameter
-                    Position::ArgumentNamed(s) => match types.iter().find(|t| {
-                        t.name == s
+                    Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
+                        param.name == s
                     }) {
                         Some(_) => (),
                         None => {
                             span_err!(tcx.sess, span, E0230,
-                                      "there is no type parameter \
+                                      "there is no parameter \
                                        {} on trait {}",
                                       s, name);
                             result = Err(ErrorReported);
@@ -288,9 +287,15 @@ pub fn format(&self,
         let name = tcx.item_name(trait_ref.def_id);
         let trait_str = tcx.item_path_str(trait_ref.def_id);
         let generics = tcx.generics_of(trait_ref.def_id);
-        let generic_map = generics.types.iter().map(|param| {
-            (param.name.to_string(),
-             trait_ref.substs.type_for_def(param).to_string())
+        let generic_map = generics.params.iter().filter_map(|param| {
+            let value = match param.kind {
+                GenericParamDefKind::Type(_) => {
+                    trait_ref.substs[param.index as usize].to_string()
+                },
+                GenericParamDefKind::Lifetime => return None
+            };
+            let name = param.name.to_string();
+            Some((name, value))
         }).collect::<FxHashMap<String, String>>();
 
         let parser = Parser::new(&self.0);
index 3c62f04afc56eefcbf9944c161665c1caa8ecd77..f5a9d2a7f00145f5d510f358a8a1d7ceda1de3eb 100644 (file)
@@ -213,7 +213,7 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
                            },
 
                            Component::Param(p) => {
-                               let ty = tcx.mk_param(p.idx, p.name);
+                               let ty = tcx.mk_ty_param(p.idx, p.name);
                                Some(ty::Predicate::TypeOutlives(
                                    ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min))))
                            },
index dcd20465fbb9a1537954f701501564de942c0a43..3c345fcd9ee61f15cb01f60abf90ee23cef87cf2 100644 (file)
@@ -44,6 +44,7 @@
 use ty::RegionKind;
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
 use ty::TypeVariants::*;
+use ty::GenericParamDefKind;
 use ty::layout::{LayoutDetails, TargetDataLayout};
 use ty::maps;
 use ty::steal::Steal;
@@ -2325,15 +2326,19 @@ pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
     pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
         let adt_def = self.adt_def(def_id);
-        let generics = self.generics_of(def_id);
-        let mut substs = vec![Kind::from(ty)];
-        // Add defaults for other generic params if there are some.
-        for def in generics.types.iter().skip(1) {
-            assert!(def.has_default);
-            let ty = self.type_of(def.def_id).subst(self, &substs);
-            substs.push(ty.into());
-        }
-        let substs = self.mk_substs(substs.into_iter());
+        let substs = Substs::for_item(self, def_id, |param, substs| {
+            match param.kind {
+                GenericParamDefKind::Lifetime => bug!(),
+                GenericParamDefKind::Type(ty_param) => {
+                    if param.index == 0 {
+                        ty.into()
+                    } else {
+                        assert!(ty_param.has_default);
+                        self.type_of(param.def_id).subst(self, substs).into()
+                    }
+                }
+            }
+        });
         self.mk_ty(TyAdt(adt_def, substs))
     }
 
@@ -2457,18 +2462,23 @@ pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> {
         self.mk_ty(TyInfer(it))
     }
 
-    pub fn mk_param(self,
+    pub fn mk_ty_param(self,
                     index: u32,
                     name: InternedString) -> Ty<'tcx> {
         self.mk_ty(TyParam(ParamTy { idx: index, name: name }))
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_param(0, keywords::SelfType.name().as_interned_str())
+        self.mk_ty_param(0, keywords::SelfType.name().as_interned_str())
     }
 
-    pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
-        self.mk_param(def.index, def.name)
+    pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> {
+        match param.kind {
+            GenericParamDefKind::Lifetime => {
+                self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
+            }
+            GenericParamDefKind::Type(_) => self.mk_ty_param(param.index, param.name).into(),
+        }
     }
 
     pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
index 4e104692d859b78f75a0efd5a30ae0e13a847f23..ad48519e136c8eae12f77fc758adcbd38f49a31a 100644 (file)
@@ -543,7 +543,7 @@ fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_late_bound_map<'tcx> {
     fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
-        format!("testing if a region is late boudn")
+        format!("testing if a region is late bound")
     }
 }
 
index eede7bd2ea619ac230f5a63aa0371c1879cafbeb..6861683ed1298160aa5f6eb2b8bf3e0e72bf18ec 100644 (file)
@@ -709,148 +709,152 @@ pub enum IntVarValue {
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub struct FloatVarValue(pub ast::FloatTy);
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
-pub struct TypeParameterDef {
-    pub name: InternedString,
-    pub def_id: DefId,
-    pub index: u32,
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct TypeParamDef {
     pub has_default: bool,
     pub object_lifetime_default: ObjectLifetimeDefault,
+    pub synthetic: Option<hir::SyntheticTyParamKind>,
+}
 
-    /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
-    /// on generic parameter `T`, asserts data behind the parameter
-    /// `T` won't be accessed during the parent type's `Drop` impl.
-    pub pure_wrt_drop: bool,
+impl ty::EarlyBoundRegion {
+    pub fn to_bound_region(&self) -> ty::BoundRegion {
+        ty::BoundRegion::BrNamed(self.def_id, self.name)
+    }
+}
 
-    pub synthetic: Option<hir::SyntheticTyParamKind>,
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub enum GenericParamDefKind {
+    Lifetime,
+    Type(TypeParamDef),
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
-pub struct RegionParameterDef {
+#[derive(Clone, RustcEncodable, RustcDecodable)]
+pub struct GenericParamDef {
     pub name: InternedString,
     pub def_id: DefId,
     pub index: u32,
 
     /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
-    /// on generic parameter `'a`, asserts data of lifetime `'a`
-    /// won't be accessed during the parent type's `Drop` impl.
+    /// on generic parameter `'a`/`T`, asserts data behind the parameter
+    /// `'a`/`T` won't be accessed during the parent type's `Drop` impl.
     pub pure_wrt_drop: bool,
+
+    pub kind: GenericParamDefKind,
 }
 
-impl RegionParameterDef {
+impl GenericParamDef {
     pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
-        ty::EarlyBoundRegion {
-            def_id: self.def_id,
-            index: self.index,
-            name: self.name,
+        match self.kind {
+            GenericParamDefKind::Lifetime => {
+                ty::EarlyBoundRegion {
+                    def_id: self.def_id,
+                    index: self.index,
+                    name: self.name,
+                }
+            }
+            _ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
         }
     }
 
     pub fn to_bound_region(&self) -> ty::BoundRegion {
-        self.to_early_bound_region_data().to_bound_region()
+        match self.kind {
+            GenericParamDefKind::Lifetime => {
+                self.to_early_bound_region_data().to_bound_region()
+            }
+            _ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
+        }
     }
 }
 
-impl ty::EarlyBoundRegion {
-    pub fn to_bound_region(&self) -> ty::BoundRegion {
-        ty::BoundRegion::BrNamed(self.def_id, self.name)
-    }
+pub struct GenericParamCount {
+    pub lifetimes: usize,
+    pub types: usize,
 }
 
 /// Information about the formal type/lifetime parameters associated
 /// with an item or method. Analogous to hir::Generics.
 ///
-/// Note that in the presence of a `Self` parameter, the ordering here
-/// is different from the ordering in a Substs. Substs are ordered as
-///     Self, *Regions, *Other Type Params, (...child generics)
-/// while this struct is ordered as
-///     regions = Regions
-///     types = [Self, *Other Type Params]
+/// The ordering of parameters is the same as in Subst (excluding child generics):
+/// Self (optionally), Lifetime params..., Type params...
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct Generics {
     pub parent: Option<DefId>,
-    pub parent_regions: u32,
-    pub parent_types: u32,
-    pub regions: Vec<RegionParameterDef>,
-    pub types: Vec<TypeParameterDef>,
+    pub parent_count: usize,
+    pub params: Vec<GenericParamDef>,
 
-    /// Reverse map to each `TypeParameterDef`'s `index` field
-    pub type_param_to_index: FxHashMap<DefId, u32>,
+    /// Reverse map to the `index` field of each `GenericParamDef`
+    pub param_def_id_to_index: FxHashMap<DefId, u32>,
 
     pub has_self: bool,
     pub has_late_bound_regions: Option<Span>,
 }
 
 impl<'a, 'gcx, 'tcx> Generics {
-    pub fn parent_count(&self) -> usize {
-        self.parent_regions as usize + self.parent_types as usize
+    pub fn count(&self) -> usize {
+        self.parent_count + self.params.len()
     }
 
-    pub fn own_count(&self) -> usize {
-        self.regions.len() + self.types.len()
+    pub fn own_counts(&self) -> GenericParamCount {
+        // We could cache this as a property of `GenericParamCount`, but
+        // the aim is to refactor this away entirely eventually and the
+        // presence of this method will be a constant reminder.
+        let mut own_counts = GenericParamCount {
+            lifetimes: 0,
+            types: 0,
+        };
+
+        for param in &self.params {
+            match param.kind {
+                GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
+                GenericParamDefKind::Type(_) => own_counts.types += 1,
+            };
+        }
+
+        own_counts
     }
 
-    pub fn count(&self) -> usize {
-        self.parent_count() + self.own_count()
+    pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+        for param in &self.params {
+            match param.kind {
+                GenericParamDefKind::Type(_) => return true,
+                GenericParamDefKind::Lifetime => {}
+            }
+        }
+        if let Some(parent_def_id) = self.parent {
+            let parent = tcx.generics_of(parent_def_id);
+            parent.requires_monomorphization(tcx)
+        } else {
+            false
+        }
     }
 
     pub fn region_param(&'tcx self,
                         param: &EarlyBoundRegion,
                         tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                        -> &'tcx RegionParameterDef
+                        -> &'tcx GenericParamDef
     {
-        if let Some(index) = param.index.checked_sub(self.parent_count() as u32) {
-            &self.regions[index as usize - self.has_self as usize]
+        if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
+            let param = &self.params[index as usize];
+            match param.kind {
+                ty::GenericParamDefKind::Lifetime => param,
+                _ => bug!("expected lifetime parameter, but found another generic parameter")
+            }
         } else {
             tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
                 .region_param(param, tcx)
         }
     }
 
-    /// Returns the `TypeParameterDef` associated with this `ParamTy`.
+    /// Returns the `TypeParamDef` associated with this `ParamTy`.
     pub fn type_param(&'tcx self,
                       param: &ParamTy,
                       tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                      -> &TypeParameterDef {
-        if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
-            // non-Self type parameters are always offset by exactly
-            // `self.regions.len()`. In the absence of a Self, this is obvious,
-            // but even in the presence of a `Self` we just have to "compensate"
-            // for the regions:
-            //
-            // Without a `Self` (or in a nested generics that doesn't have
-            // a `Self` in itself, even through it parent does), for example
-            // for `fn foo<'a, T1, T2>()`, the situation is:
-            //     Substs:
-            //         0  1  2
-            //         'a T1 T2
-            //     generics.types:
-            //         0  1
-            //         T1 T2
-            //
-            // And with a `Self`, for example for `trait Foo<'a, 'b, T1, T2>`, the
-            // situation is:
-            //     Substs:
-            //         0   1  2  3  4
-            //       Self 'a 'b  T1 T2
-            //     generics.types:
-            //         0  1  2
-            //       Self T1 T2
-            //
-            // And it can be seen that in both cases, to move from a substs
-            // offset to a generics offset you just have to offset by the
-            // number of regions.
-            let type_param_offset = self.regions.len();
-
-            let has_self = self.has_self && self.parent.is_none();
-            let is_separated_self = type_param_offset != 0 && idx == 0 && has_self;
-
-            if let Some(idx) = (idx as usize).checked_sub(type_param_offset) {
-                assert!(!is_separated_self, "found a Self after type_param_offset");
-                &self.types[idx]
-            } else {
-                assert!(is_separated_self, "non-Self param before type_param_offset");
-                &self.types[0]
+                      -> &'tcx GenericParamDef {
+        if let Some(index) = param.idx.checked_sub(self.parent_count as u32) {
+            let param = &self.params[index as usize];
+            match param.kind {
+                ty::GenericParamDefKind::Type(_) => param,
+                _ => bug!("expected type parameter, but found another generic parameter")
             }
         } else {
             tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
index f0a7ce54971661db1768ba9e0d71467addb88bfc..acc225ddf568031fc4dec07df802afb8e154da74 100644 (file)
@@ -292,7 +292,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// ordering.
     fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitClosureSubsts<'tcx> {
         let generics = tcx.generics_of(def_id);
-        let parent_len = generics.parent_count();
+        let parent_len = generics.parent_count;
         SplitClosureSubsts {
             closure_kind_ty: self.substs.type_at(parent_len),
             closure_sig_ty: self.substs.type_at(parent_len + 1),
@@ -366,7 +366,7 @@ struct SplitGeneratorSubsts<'tcx> {
 impl<'tcx> GeneratorSubsts<'tcx> {
     fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitGeneratorSubsts<'tcx> {
         let generics = tcx.generics_of(def_id);
-        let parent_len = generics.parent_count();
+        let parent_len = generics.parent_count;
         SplitGeneratorSubsts {
             yield_ty: self.substs.type_at(parent_len),
             return_ty: self.substs.type_at(parent_len + 1),
@@ -928,12 +928,12 @@ pub fn for_self() -> ParamTy {
         ParamTy::new(0, keywords::SelfType.name().as_interned_str())
     }
 
-    pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
+    pub fn for_def(def: &ty::GenericParamDef) -> ParamTy {
         ParamTy::new(def.index, def.name)
     }
 
     pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        tcx.mk_param(self.idx, self.name)
+        tcx.mk_ty_param(self.idx, self.name)
     }
 
     pub fn is_self(&self) -> bool {
index e7b58ae1564aa1683a86a36d92c5ee81eae26a47..b94b3e17f862fb29f2edcc4aad42c4e7ddbe4c19 100644 (file)
@@ -174,92 +174,72 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Kind<'tcx>, D::Error> {
     }
 }
 
-/// A substitution mapping type/region parameters to new values.
+/// A substitution mapping generic parameters to new values.
 pub type Substs<'tcx> = Slice<Kind<'tcx>>;
 
 impl<'a, 'gcx, 'tcx> Substs<'tcx> {
     /// Creates a Substs that maps each generic parameter to itself.
     pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
                              -> &'tcx Substs<'tcx> {
-        Substs::for_item(tcx, def_id, |def, _| {
-            tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
-        }, |def, _| tcx.mk_param_from_def(def))
+        Substs::for_item(tcx, def_id, |param, _| {
+            tcx.mk_param_from_def(param)
+        })
     }
 
     /// Creates a Substs for generic parameter definitions,
-    /// by calling closures to obtain each region and type.
+    /// by calling closures to obtain each kind.
     /// The closures get to observe the Substs as they're
     /// being built, which can be used to correctly
-    /// substitute defaults of type parameters.
-    pub fn for_item<FR, FT>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                            def_id: DefId,
-                            mut mk_region: FR,
-                            mut mk_type: FT)
-                            -> &'tcx Substs<'tcx>
-    where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
-          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
+    /// substitute defaults of generic parameters.
+    pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                       def_id: DefId,
+                       mut mk_kind: F)
+                       -> &'tcx Substs<'tcx>
+    where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
+    {
         let defs = tcx.generics_of(def_id);
         let mut substs = Vec::with_capacity(defs.count());
-        Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type);
+        Substs::fill_item(&mut substs, tcx, defs, &mut mk_kind);
         tcx.intern_substs(&substs)
     }
 
-    pub fn extend_to<FR, FT>(&self,
-                             tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                             def_id: DefId,
-                             mut mk_region: FR,
-                             mut mk_type: FT)
-                             -> &'tcx Substs<'tcx>
-    where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
-          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx>
+    pub fn extend_to<F>(&self,
+                        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                        def_id: DefId,
+                        mut mk_kind: F)
+                        -> &'tcx Substs<'tcx>
+    where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
     {
         let defs = tcx.generics_of(def_id);
         let mut result = Vec::with_capacity(defs.count());
         result.extend(self[..].iter().cloned());
-        Substs::fill_single(&mut result, defs, &mut mk_region, &mut mk_type);
+        Substs::fill_single(&mut result, defs, &mut mk_kind);
         tcx.intern_substs(&result)
     }
 
-    pub fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
+    pub fn fill_item<F>(substs: &mut Vec<Kind<'tcx>>,
                              tcx: TyCtxt<'a, 'gcx, 'tcx>,
                              defs: &ty::Generics,
-                             mk_region: &mut FR,
-                             mk_type: &mut FT)
-    where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
-          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
+                             mk_kind: &mut F)
+    where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
+    {
 
         if let Some(def_id) = defs.parent {
             let parent_defs = tcx.generics_of(def_id);
-            Substs::fill_item(substs, tcx, parent_defs, mk_region, mk_type);
+            Substs::fill_item(substs, tcx, parent_defs, mk_kind);
         }
-        Substs::fill_single(substs, defs, mk_region, mk_type)
+        Substs::fill_single(substs, defs, mk_kind)
     }
 
-    fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
+    fn fill_single<F>(substs: &mut Vec<Kind<'tcx>>,
                            defs: &ty::Generics,
-                           mk_region: &mut FR,
-                           mk_type: &mut FT)
-    where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
-          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
-        // Handle Self first, before all regions.
-        let mut types = defs.types.iter();
-        if defs.parent.is_none() && defs.has_self {
-            let def = types.next().unwrap();
-            let ty = mk_type(def, substs);
-            assert_eq!(def.index as usize, substs.len());
-            substs.push(ty.into());
-        }
-
-        for def in &defs.regions {
-            let region = mk_region(def, substs);
-            assert_eq!(def.index as usize, substs.len());
-            substs.push(Kind::from(region));
-        }
-
-        for def in types {
-            let ty = mk_type(def, substs);
-            assert_eq!(def.index as usize, substs.len());
-            substs.push(Kind::from(ty));
+                           mk_kind: &mut F)
+    where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
+    {
+        for param in &defs.params {
+            let kind = mk_kind(param, substs);
+            assert_eq!(param.index as usize, substs.len());
+            substs.push(kind);
         }
     }
 
@@ -308,13 +288,8 @@ pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
     }
 
     #[inline]
-    pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
-        self.type_at(ty_param_def.index as usize)
-    }
-
-    #[inline]
-    pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region<'tcx> {
-        self.region_at(def.index as usize)
+    pub fn type_for_def(&self, def: &ty::GenericParamDef) -> Kind<'tcx> {
+        self.type_at(def.index as usize).into()
     }
 
     /// Transform from substitutions for a child of `source_ancestor`
@@ -327,7 +302,7 @@ pub fn rebase_onto(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                        target_substs: &Substs<'tcx>)
                        -> &'tcx Substs<'tcx> {
         let defs = tcx.generics_of(source_ancestor);
-        tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
+        tcx.mk_substs(target_substs.iter().chain(&self[defs.params.len()..]).cloned())
     }
 
     pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics)
@@ -580,7 +555,7 @@ pub fn from_method(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
         ty::TraitRef {
             def_id: trait_id,
-            substs: tcx.intern_substs(&substs[..defs.own_count()])
+            substs: tcx.intern_substs(&substs[..defs.params.len()])
         }
     }
 }
index fdd0754730febb72bf0d37a73f73d95bf00c864f..d5532f8f8355a3167ea79d8c40cb5db9a6f37255 100644 (file)
@@ -17,9 +17,9 @@
 use ich::NodeIdHashingMode;
 use middle::const_val::ConstVal;
 use traits::{self, ObligationCause};
-use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
 use ty::fold::TypeVisitor;
-use ty::subst::UnpackedKind;
+use ty::subst::{Substs, UnpackedKind};
 use ty::maps::TyCtxtAt;
 use ty::TypeVariants::*;
 use ty::layout::{Integer, IntegerExt};
@@ -573,11 +573,14 @@ pub fn closure_env_ty(self,
 
     /// Given the def-id of some item that has no type parameters, make
     /// a suitable "empty substs" for it.
-    pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {
-        ty::Substs::for_item(self, item_def_id,
-                             |_, _| self.types.re_erased,
-                             |_, _| {
-            bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
+    pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
+        Substs::for_item(self, item_def_id, |param, _| {
+            match param.kind {
+                GenericParamDefKind::Lifetime => self.types.re_erased.into(),
+                GenericParamDefKind::Type(_) => {
+                    bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
+                }
+            }
         })
     }
 
index a6eb468e33836fc43fcddf6ae9e209a95b174c82..eaae874635f62772a1795aa4571a60445b62abad 100644 (file)
@@ -19,7 +19,7 @@
 use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
 use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon};
 use ty::{TyDynamic, TyInt, TyUint, TyInfer};
-use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
 use util::nodemap::FxHashSet;
 
 use std::cell::Cell;
@@ -256,8 +256,10 @@ fn parameterized<F: fmt::Write>(&mut self,
         let verbose = self.is_verbose;
         let mut num_supplied_defaults = 0;
         let mut has_self = false;
-        let mut num_regions = 0;
-        let mut num_types = 0;
+        let mut own_counts = GenericParamCount {
+            lifetimes: 0,
+            types: 0,
+        };
         let mut is_value_path = false;
         let fn_trait_kind = ty::tls::with(|tcx| {
             // Unfortunately, some kinds of items (e.g., closures) don't have
@@ -303,6 +305,7 @@ fn parameterized<F: fmt::Write>(&mut self,
                 }
             }
             let mut generics = tcx.generics_of(item_def_id);
+            let child_own_counts = generics.own_counts();
             let mut path_def_id = did;
             has_self = generics.has_self;
 
@@ -310,10 +313,9 @@ fn parameterized<F: fmt::Write>(&mut self,
             if let Some(def_id) = generics.parent {
                 // Methods.
                 assert!(is_value_path);
-                child_types = generics.types.len();
+                child_types = child_own_counts.types;
                 generics = tcx.generics_of(def_id);
-                num_regions = generics.regions.len();
-                num_types = generics.types.len();
+                own_counts = generics.own_counts();
 
                 if has_self {
                     print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
@@ -328,20 +330,30 @@ fn parameterized<F: fmt::Write>(&mut self,
                     assert_eq!(has_self, false);
                 } else {
                     // Types and traits.
-                    num_regions = generics.regions.len();
-                    num_types = generics.types.len();
+                    own_counts = child_own_counts;
                 }
             }
 
             if !verbose {
-                if generics.types.last().map_or(false, |def| def.has_default) {
+                let mut type_params =
+                    generics.params.iter().rev().filter_map(|param| {
+                        match param.kind {
+                            GenericParamDefKind::Type(ty) => Some((param.def_id, ty.has_default)),
+                            GenericParamDefKind::Lifetime => None,
+                        }
+                    }).peekable();
+                let has_default = {
+                    let has_default = type_params.peek().map(|(_, has_default)| has_default);
+                    *has_default.unwrap_or(&false)
+                };
+                if has_default {
                     if let Some(substs) = tcx.lift(&substs) {
-                        let tps = substs.types().rev().skip(child_types);
-                        for (def, actual) in generics.types.iter().rev().zip(tps) {
-                            if !def.has_default {
+                        let mut types = substs.types().rev().skip(child_types);
+                        for ((def_id, has_default), actual) in type_params.zip(types) {
+                            if !has_default {
                                 break;
                             }
-                            if tcx.type_of(def.def_id).subst(tcx, substs) != actual {
+                            if tcx.type_of(def_id).subst(tcx, substs) != actual {
                                 break;
                             }
                             num_supplied_defaults += 1;
@@ -401,10 +413,11 @@ fn parameterized<F: fmt::Write>(&mut self,
             Ok(())
         };
 
-        print_regions(f, "<", 0, num_regions)?;
+        print_regions(f, "<", 0, own_counts.lifetimes)?;
 
-        let tps = substs.types().take(num_types - num_supplied_defaults)
-                                .skip(has_self as usize);
+        let tps = substs.types()
+                        .take(own_counts.types - num_supplied_defaults)
+                        .skip(has_self as usize);
 
         for ty in tps {
             start_or_continue(f, "<", ", ")?;
@@ -435,10 +448,10 @@ fn parameterized<F: fmt::Write>(&mut self,
                 write!(f, "::{}", item_name)?;
             }
 
-            print_regions(f, "::<", num_regions, usize::MAX)?;
+            print_regions(f, "::<", own_counts.lifetimes, usize::MAX)?;
 
             // FIXME: consider being smart with defaults here too
-            for ty in substs.types().skip(num_types) {
+            for ty in substs.types().skip(own_counts.types) {
                 start_or_continue(f, "::<", ", ")?;
                 ty.print_display(f, self)?;
             }
@@ -588,18 +601,14 @@ fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result
     }
 }
 
-impl fmt::Debug for ty::TypeParameterDef {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TypeParameterDef({}, {:?}, {})",
-               self.name,
-               self.def_id,
-               self.index)
-    }
-}
-
-impl fmt::Debug for ty::RegionParameterDef {
+impl fmt::Debug for ty::GenericParamDef {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "RegionParameterDef({}, {:?}, {})",
+        let type_name = match self.kind {
+            ty::GenericParamDefKind::Lifetime => "Lifetime",
+            ty::GenericParamDefKind::Type(_) => "Type",
+        };
+        write!(f, "{}({}, {:?}, {})",
+               type_name,
                self.name,
                self.def_id,
                self.index)
index 7ae26e9e9798e72c15b8f64e70d1459c0b90e6c5..78c95a5ce0504e1a60a19433bdc4db3395fe9c60 100644 (file)
@@ -308,7 +308,7 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_interned_str())
+        self.infcx.tcx.mk_ty_param(index, Symbol::intern(&name).as_interned_str())
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
index d7a06f7932fef396a8de850578e442efea6435a9..3de90abd9663f84213e90addb6ccd7292e228a9b 100644 (file)
@@ -929,10 +929,9 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
                 hir::ImplItemKind::Const(..) => true,
                 hir::ImplItemKind::Method(ref sig, _) => {
                     let generics = self.tcx.generics_of(def_id);
-                    let types = generics.parent_types as usize + generics.types.len();
-                    let needs_inline =
-                        (types > 0 || tcx.trans_fn_attrs(def_id).requests_inline())
-                            && !self.metadata_output_only();
+                    let needs_inline = (generics.requires_monomorphization(self.tcx) ||
+                                        tcx.trans_fn_attrs(def_id).requests_inline()) &&
+                                        !self.metadata_output_only();
                     let is_const_fn = sig.constness == hir::Constness::Const;
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                     needs_inline || is_const_fn || always_encode_mir
index e690e8ee88066cc9b9f99efaaea7d758529175b0..dc2009a02600309b79e35db58b221611e97411de 100644 (file)
 use rustc::mir::interpret::{AllocId, ConstValue};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::ty::subst::{Substs, Kind};
-use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
+use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::session::config;
 use rustc::mir::{self, Location, Promoted};
@@ -1076,7 +1076,7 @@ fn push_extra_entry_roots(&mut self) {
 
 fn item_has_type_parameters<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
     let generics = tcx.generics_of(def_id);
-    generics.parent_types as usize + generics.types.len() > 0
+    generics.requires_monomorphization(tcx)
 }
 
 fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -1108,14 +1108,18 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         continue;
                     }
 
-                    if !tcx.generics_of(method.def_id).types.is_empty() {
+                    if tcx.generics_of(method.def_id).own_counts().types != 0 {
                         continue;
                     }
 
-                    let substs = Substs::for_item(tcx,
-                                                  method.def_id,
-                                                  |_, _| tcx.types.re_erased,
-                                                  |def, _| trait_ref.substs.type_for_def(def));
+                    let substs = Substs::for_item(tcx, method.def_id, |param, _| {
+                        match param.kind {
+                            GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
+                            GenericParamDefKind::Type(_) => {
+                                trait_ref.substs[param.index as usize]
+                            }
+                        }
+                    });
 
                     let instance = ty::Instance::resolve(tcx,
                                                          ty::ParamEnv::reveal_all(),
index 5b2f3a8b8aac7ee01237d4ee84e572f28e090e74..c79298d8dd2cfa8a2dcbaf2432b33f32ab5fd53d 100644 (file)
@@ -12,7 +12,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::infer;
 use rustc::mir::*;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
 
@@ -427,12 +427,12 @@ fn make_clone_call(
     ) {
         let tcx = self.tcx;
 
-        let substs = Substs::for_item(
-            tcx,
-            self.def_id,
-            |_, _| tcx.types.re_erased,
-            |_, _| ty
-        );
+        let substs = Substs::for_item(tcx, self.def_id, |param, _| {
+            match param.kind {
+                GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
+                GenericParamDefKind::Type(_) => ty.into(),
+            }
+        });
 
         // `func == Clone::clone(&ty) -> ty`
         let func_ty = tcx.mk_fn_def(self.def_id, substs);
index 2bf5a49c97e8ff31eaf648f27dc810065de63878..fc3764e4f49a5bbb8391ab4604b655c93340f9a5 100644 (file)
@@ -357,7 +357,7 @@ fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: D
 
     // FIXME: when we make this a hard error, this should have its
     // own error code.
-    let message = if !tcx.generics_of(def_id).types.is_empty() {
+    let message = if tcx.generics_of(def_id).own_counts().types != 0 {
         format!("#[derive] can't be used on a #[repr(packed)] struct with \
                  type parameters (error E0133)")
     } else {
index 6b0217c8f7cbc17b48687f4d94a1e83286df3d2c..80603959ec202fdd0542d64941bedd7c2ff94a0b 100644 (file)
@@ -184,7 +184,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
             // evaluate the promoted and replace the constant with the evaluated result
             Literal::Promoted { index } => {
                 let generics = self.tcx.generics_of(self.source.def_id);
-                if generics.parent_types as usize + generics.types.len() > 0 {
+                if generics.requires_monomorphization(self.tcx) {
                     // FIXME: can't handle code with generics
                     return None;
                 }
@@ -295,7 +295,7 @@ fn const_prop(
                     self.source.def_id
                 };
                 let generics = self.tcx.generics_of(def_id);
-                if generics.parent_types as usize + generics.types.len() > 0 {
+                if generics.requires_monomorphization(self.tcx) {
                     // FIXME: can't handle code with generics
                     return None;
                 }
@@ -317,8 +317,7 @@ fn const_prop(
                     self.source.def_id
                 };
                 let generics = self.tcx.generics_of(def_id);
-                let has_generics = generics.parent_types as usize + generics.types.len() > 0;
-                if has_generics {
+                if generics.requires_monomorphization(self.tcx) {
                     // FIXME: can't handle code with generics
                     return None;
                 }
index 42031d9cc56308d73ee38d0d851a8050e1e96884..6e9b03cd2a9c6cedb35d803f4c1fa0d421f6c6d2 100644 (file)
@@ -27,7 +27,7 @@
 use rustc::hir::itemlikevisit::DeepVisitor;
 use rustc::lint;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
-use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
+use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, GenericParamDefKind};
 use rustc::ty::fold::TypeVisitor;
 use rustc::ty::maps::Providers;
 use rustc::ty::subst::UnpackedKind;
@@ -399,9 +399,14 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
 
 impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
     fn generics(&mut self) -> &mut Self {
-        for def in &self.ev.tcx.generics_of(self.item_def_id).types {
-            if def.has_default {
-                self.ev.tcx.type_of(def.def_id).visit_with(self);
+        for param in &self.ev.tcx.generics_of(self.item_def_id).params {
+            match param.kind {
+                GenericParamDefKind::Type(ty) => {
+                    if ty.has_default {
+                        self.ev.tcx.type_of(param.def_id).visit_with(self);
+                    }
+                }
+                GenericParamDefKind::Lifetime => {}
             }
         }
         self
@@ -1335,9 +1340,14 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     fn generics(&mut self) -> &mut Self {
-        for def in &self.tcx.generics_of(self.item_def_id).types {
-            if def.has_default {
-                self.tcx.type_of(def.def_id).visit_with(self);
+        for param in &self.tcx.generics_of(self.item_def_id).params {
+            match param.kind {
+                GenericParamDefKind::Type(ty) => {
+                    if ty.has_default {
+                        self.tcx.type_of(param.def_id).visit_with(self);
+                    }
+                }
+                GenericParamDefKind::Lifetime => {}
             }
         }
         self
index ce5707276ee1a543a73b96483fd453abec3c5740..219c6b9aefba51f72be5cacf674fcfd98413d0b6 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::traits::query::{CanonicalTyGoal, NoSolution};
 use rustc::traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
-use rustc::ty::subst::Subst;
+use rustc::ty::subst::{Subst, Substs};
 use rustc::util::nodemap::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use syntax::codemap::{Span, DUMMY_SP};
@@ -278,9 +278,13 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
     debug!("dtorck_constraint: {:?}", def);
 
     if def.is_phantom_data() {
+        // The first generic parameter here is guaranteed to be a type because it's
+        // `PhantomData`.
+        let substs = Substs::identity_for_item(tcx, def_id);
+        assert_eq!(substs.len(), 1);
         let result = DtorckConstraint {
             outlives: vec![],
-            dtorck_types: vec![tcx.mk_param_from_def(&tcx.generics_of(def_id).types[0])],
+            dtorck_types: vec![substs.type_at(0)],
             overflows: vec![],
         };
         debug!("dtorck_constraint: {:?} => {:?}", def, result);
index 7f18fac2db5a3a5b8996c722c6959492ac4302c1..f2627f65702411d3e53a0539551c273755c23c39 100644 (file)
@@ -12,6 +12,7 @@
 //! the guts are broken up into modules; see the comments in those modules.
 
 #![feature(crate_visibility_modifier)]
+#![feature(iterator_find_map)]
 
 #[macro_use]
 extern crate log;
index d8520b61d9157b624e6c0917a08a51a5d676504a..d77855220691d31113a8ef018b636552baf1e02e 100644 (file)
@@ -117,7 +117,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }) => {
                     let def_id = tcx.hir.local_def_id(node_id);
                     let generics = tcx.generics_of(def_id);
-                    if (generics.parent_types == 0 && generics.types.is_empty()) &&
+                    if !generics.requires_monomorphization(tcx) &&
                         // Functions marked with #[inline] are only ever translated
                         // with "internal" linkage and are never exported.
                         !Instance::mono(tcx, def_id).def.requires_local(tcx) {
index 30676b91620a62c27e7d60e03bbcfcd6f7a114f3..2039a90a043bf4c5fd9a5240ddad9505fbe35c65 100644 (file)
@@ -25,7 +25,7 @@
 use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
 use rustc::hir::TransFnAttrFlags;
 use rustc::hir::def_id::{DefId, CrateNum};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Substs, UnpackedKind};
 
 use abi::Abi;
 use common::CodegenCx;
@@ -390,20 +390,25 @@ fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
         // Again, only create type information if full debuginfo is enabled
         let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
-            let names = get_type_parameter_names(cx, generics);
-            substs.types().zip(names).map(|(ty, name)| {
-                let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
-                let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
-                let name = CString::new(name.as_str().as_bytes()).unwrap();
-                unsafe {
-                    llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
-                        DIB(cx),
-                        ptr::null_mut(),
-                        name.as_ptr(),
-                        actual_type_metadata,
-                        file_metadata,
-                        0,
-                        0)
+            let names = get_parameter_names(cx, generics);
+            substs.iter().zip(names).filter_map(|(kind, name)| {
+                if let UnpackedKind::Type(ty) = kind.unpack() {
+                    let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+                    let actual_type_metadata =
+                        type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
+                    let name = CString::new(name.as_str().as_bytes()).unwrap();
+                    Some(unsafe {
+                        llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
+                            DIB(cx),
+                            ptr::null_mut(),
+                            name.as_ptr(),
+                            actual_type_metadata,
+                            file_metadata,
+                            0,
+                            0)
+                    })
+                } else {
+                    None
                 }
             }).collect()
         } else {
@@ -413,11 +418,13 @@ fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         return create_DIArray(DIB(cx), &template_params[..]);
     }
 
-    fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<InternedString> {
+    fn get_parameter_names(cx: &CodegenCx,
+                           generics: &ty::Generics)
+                           -> Vec<InternedString> {
         let mut names = generics.parent.map_or(vec![], |def_id| {
-            get_type_parameter_names(cx, cx.tcx.generics_of(def_id))
+            get_parameter_names(cx, cx.tcx.generics_of(def_id))
         });
-        names.extend(generics.types.iter().map(|param| param.name));
+        names.extend(generics.params.iter().map(|param| param.name));
         names
     }
 
index d307ef30044e12f13d9faa92fc3059fe4265765f..c1868467503f823d0d17fed9d202de43c73d0873 100644 (file)
@@ -21,6 +21,7 @@
 use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable};
+use rustc::ty::GenericParamDefKind;
 use rustc::ty::wf::object_region_bounds;
 use rustc_target::spec::abi;
 use std::slice;
@@ -43,7 +44,7 @@ fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
                                  -> ty::GenericPredicates<'tcx>;
 
     /// What lifetime should we use when a lifetime is omitted (and not elided)?
-    fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
+    fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>)
                 -> Option<ty::Region<'tcx>>;
 
     /// What type should we use when a type is omitted?
@@ -51,7 +52,7 @@ fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
 
     /// Same as ty_infer, but with a known type parameter definition.
     fn ty_infer_for_def(&self,
-                        _def: &ty::TypeParameterDef,
+                        _def: &ty::GenericParamDef,
                         span: Span) -> Ty<'tcx> {
         self.ty_infer(span)
     }
@@ -87,6 +88,11 @@ struct ConvertedBinding<'tcx> {
     span: Span,
 }
 
+struct ParamRange {
+    required: usize,
+    accepted: usize
+}
+
 /// Dummy type used for the `Self` of a `TraitRef` created for converting
 /// a trait object, and which gets removed in `ExistentialTraitRef`.
 /// This type must not appear anywhere in other converted types.
@@ -95,7 +101,7 @@ struct ConvertedBinding<'tcx> {
 impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
     pub fn ast_region_to_region(&self,
         lifetime: &hir::Lifetime,
-        def: Option<&ty::RegionParameterDef>)
+        def: Option<&ty::GenericParamDef>)
         -> ty::Region<'tcx>
     {
         let tcx = self.tcx();
@@ -208,92 +214,119 @@ fn create_substs_for_ast_path(&self,
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
         let decl_generics = tcx.generics_of(def_id);
-        let num_types_provided = parameters.types.len();
-        let expected_num_region_params = decl_generics.regions.len();
-        let supplied_num_region_params = parameters.lifetimes.len();
-        if expected_num_region_params != supplied_num_region_params {
-            report_lifetime_number_error(tcx, span,
-                                         supplied_num_region_params,
-                                         expected_num_region_params);
+        let ty_provided = parameters.types.len();
+        let lt_provided = parameters.lifetimes.len();
+
+        let mut lt_accepted = 0;
+        let mut ty_params = ParamRange { required: 0, accepted: 0 };
+        for param in &decl_generics.params {
+            match param.kind {
+                GenericParamDefKind::Lifetime => {
+                    lt_accepted += 1;
+                }
+                GenericParamDefKind::Type(ty) => {
+                    ty_params.accepted += 1;
+                    if !ty.has_default {
+                        ty_params.required += 1;
+                    }
+                }
+            };
+        }
+        if self_ty.is_some() {
+            ty_params.required -= 1;
+            ty_params.accepted -= 1;
+        }
+
+        if lt_accepted != lt_provided {
+            report_lifetime_number_error(tcx, span, lt_provided, lt_accepted);
         }
 
         // If a self-type was declared, one should be provided.
         assert_eq!(decl_generics.has_self, self_ty.is_some());
 
         // Check the number of type parameters supplied by the user.
-        let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
-        if !infer_types || num_types_provided > ty_param_defs.len() {
-            check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
+        if !infer_types || ty_provided > ty_params.required {
+            check_type_argument_count(tcx, span, ty_provided, ty_params);
         }
 
         let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
-        let default_needs_object_self = |p: &ty::TypeParameterDef| {
-            if is_object && p.has_default {
-                if tcx.at(span).type_of(p.def_id).has_self_ty() {
-                    // There is no suitable inference default for a type parameter
-                    // that references self, in an object type.
-                    return true;
+        let default_needs_object_self = |param: &ty::GenericParamDef| {
+            if let GenericParamDefKind::Type(ty) = param.kind {
+                if is_object && ty.has_default {
+                    if tcx.at(span).type_of(param.def_id).has_self_ty() {
+                        // There is no suitable inference default for a type parameter
+                        // that references self, in an object type.
+                        return true;
+                    }
                 }
             }
 
             false
         };
 
-        let substs = Substs::for_item(tcx, def_id, |def, _| {
-            let i = def.index as usize - self_ty.is_some() as usize;
-            if let Some(lifetime) = parameters.lifetimes.get(i) {
-                self.ast_region_to_region(lifetime, Some(def))
-            } else {
-                tcx.types.re_static
-            }
-        }, |def, substs| {
-            let i = def.index as usize;
+        let own_self = self_ty.is_some() as usize;
+        let substs = Substs::for_item(tcx, def_id, |param, substs| {
+            match param.kind {
+                GenericParamDefKind::Lifetime => {
+                    let i = param.index as usize - own_self;
+                    if let Some(lifetime) = parameters.lifetimes.get(i) {
+                        self.ast_region_to_region(lifetime, Some(param)).into()
+                    } else {
+                        tcx.types.re_static.into()
+                    }
+                }
+                GenericParamDefKind::Type(ty) => {
+                    let i = param.index as usize;
 
-            // Handle Self first, so we can adjust the index to match the AST.
-            if let (0, Some(ty)) = (i, self_ty) {
-                return ty;
-            }
+                    // Handle Self first, so we can adjust the index to match the AST.
+                    if let (0, Some(ty)) = (i, self_ty) {
+                        return ty.into();
+                    }
 
-            let i = i - self_ty.is_some() as usize - decl_generics.regions.len();
-            if i < num_types_provided {
-                // A provided type parameter.
-                self.ast_ty_to_ty(&parameters.types[i])
-            } else if infer_types {
-                // No type parameters were provided, we can infer all.
-                let ty_var = if !default_needs_object_self(def) {
-                    self.ty_infer_for_def(def, span)
-                } else {
-                    self.ty_infer(span)
-                };
-                ty_var
-            } else if def.has_default {
-                // No type parameter provided, but a default exists.
-
-                // If we are converting an object type, then the
-                // `Self` parameter is unknown. However, some of the
-                // other type parameters may reference `Self` in their
-                // defaults. This will lead to an ICE if we are not
-                // careful!
-                if default_needs_object_self(def) {
-                    struct_span_err!(tcx.sess, span, E0393,
-                                     "the type parameter `{}` must be explicitly specified",
-                                     def.name)
-                        .span_label(span, format!("missing reference to `{}`", def.name))
-                        .note(&format!("because of the default `Self` reference, \
-                                        type parameters must be specified on object types"))
-                        .emit();
-                    tcx.types.err
-                } else {
-                    // This is a default type parameter.
-                    self.normalize_ty(
-                        span,
-                        tcx.at(span).type_of(def.def_id)
-                            .subst_spanned(tcx, substs, Some(span))
-                    )
+                    let i = i - (lt_accepted + own_self);
+                    if i < ty_provided {
+                        // A provided type parameter.
+                        self.ast_ty_to_ty(&parameters.types[i]).into()
+                    } else if infer_types {
+                        // No type parameters were provided, we can infer all.
+                        if !default_needs_object_self(param) {
+                            self.ty_infer_for_def(param, span).into()
+                        } else {
+                            self.ty_infer(span).into()
+                        }
+                    } else if ty.has_default {
+                        // No type parameter provided, but a default exists.
+
+                        // If we are converting an object type, then the
+                        // `Self` parameter is unknown. However, some of the
+                        // other type parameters may reference `Self` in their
+                        // defaults. This will lead to an ICE if we are not
+                        // careful!
+                        if default_needs_object_self(param) {
+                            struct_span_err!(tcx.sess, span, E0393,
+                                             "the type parameter `{}` must be explicitly \
+                                             specified",
+                                             param.name)
+                                .span_label(span,
+                                            format!("missing reference to `{}`", param.name))
+                                .note(&format!("because of the default `Self` reference, \
+                                                type parameters must be specified on object \
+                                                types"))
+                                .emit();
+                            tcx.types.err.into()
+                        } else {
+                            // This is a default type parameter.
+                            self.normalize_ty(
+                                span,
+                                tcx.at(span).type_of(param.def_id)
+                                    .subst_spanned(tcx, substs, Some(span))
+                            ).into()
+                        }
+                    } else {
+                        // We've already errored above about the mismatch.
+                        tcx.types.err.into()
+                    }
                 }
-            } else {
-                // We've already errored above about the mismatch.
-                tcx.types.err
             }
         });
 
@@ -979,8 +1012,8 @@ pub fn def_to_ty(&self,
                 let item_id = tcx.hir.get_parent_node(node_id);
                 let item_def_id = tcx.hir.local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id);
-                let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id)];
-                tcx.mk_param(index, tcx.hir.name(node_id).as_interned_str())
+                let index = generics.param_def_id_to_index[&tcx.hir.local_def_id(node_id)];
+                tcx.mk_ty_param(index, tcx.hir.name(node_id).as_interned_str())
             }
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
@@ -1124,12 +1157,9 @@ pub fn impl_trait_ty_to_ty(&self, def_id: DefId, lifetimes: &[hir::Lifetime]) ->
         let mut substs = Vec::with_capacity(generics.count());
         if let Some(parent_id) = generics.parent {
             let parent_generics = tcx.generics_of(parent_id);
-            Substs::fill_item(
-                &mut substs, tcx, parent_generics,
-                &mut |def, _| tcx.mk_region(
-                    ty::ReEarlyBound(def.to_early_bound_region_data())),
-                &mut |def, _| tcx.mk_param_from_def(def)
-            );
+            Substs::fill_item(&mut substs, tcx, parent_generics, &mut |param, _| {
+                tcx.mk_param_from_def(param)
+            });
 
             // Replace all lifetimes with 'static
             for subst in &mut substs {
@@ -1139,10 +1169,10 @@ pub fn impl_trait_ty_to_ty(&self, def_id: DefId, lifetimes: &[hir::Lifetime]) ->
             }
             debug!("impl_trait_ty_to_ty: substs from parent = {:?}", substs);
         }
-        assert_eq!(substs.len(), generics.parent_count());
+        assert_eq!(substs.len(), generics.parent_count);
 
         // Fill in our own generics with the resolved lifetimes
-        assert_eq!(lifetimes.len(), generics.own_count());
+        assert_eq!(lifetimes.len(), generics.params.len());
         substs.extend(lifetimes.iter().map(|lt| Kind::from(self.ast_region_to_region(lt, None))));
 
         debug!("impl_trait_ty_to_ty: final substs = {:?}", substs);
@@ -1299,10 +1329,12 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     (auto_traits, trait_bounds)
 }
 
-fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
-                             ty_param_defs: &[ty::TypeParameterDef]) {
-    let accepted = ty_param_defs.len();
-    let required = ty_param_defs.iter().take_while(|x| !x.has_default).count();
+fn check_type_argument_count(tcx: TyCtxt,
+                             span: Span,
+                             supplied: usize,
+                             ty_params: ParamRange)
+{
+    let (required, accepted) = (ty_params.required, ty_params.accepted);
     if supplied < required {
         let expected = if required < accepted {
             "expected at least"
index 94ef040d80a4f81e58180b0ef3861cdbb37f7353..c2ec6475b9c6596bb97cd9227c90f9f8ff89d254 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::infer::LateBoundRegionConversionTime;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::traits::error_reporting::ArgKind;
-use rustc::ty::{self, ToPolyTraitRef, Ty};
+use rustc::ty::{self, ToPolyTraitRef, Ty, GenericParamDefKind};
 use rustc::ty::subst::Substs;
 use rustc::ty::TypeFoldable;
 use std::cmp;
@@ -104,15 +104,17 @@ fn check_closure(
         // inference phase (`upvar.rs`).
         let base_substs =
             Substs::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
-        let substs = base_substs.extend_to(
-            self.tcx,
-            expr_def_id,
-            |_, _| span_bug!(expr.span, "closure has region param"),
-            |_, _| {
-                self.infcx
-                    .next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span))
-            },
-        );
+        let substs = base_substs.extend_to(self.tcx,expr_def_id, |param, _| {
+            match param.kind {
+                GenericParamDefKind::Lifetime => {
+                    span_bug!(expr.span, "closure has region param")
+                }
+                GenericParamDefKind::Type(_) => {
+                    self.infcx
+                        .next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)).into()
+                }
+            }
+        });
         if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types {
             let substs = ty::GeneratorSubsts { substs };
             self.demand_eqtype(
index 91264849cadf85f41f6930da4045cb23c54e89b1..ba950f90d0a02db5fa5bef9c87761ed0a139c673 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::hir::{self, ImplItemKind, TraitItemKind};
 use rustc::infer::{self, InferOk};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, TyCtxt, GenericParamDefKind};
 use rustc::ty::util::ExplicitSelf;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::error::{ExpectedFound, TypeError};
@@ -357,8 +357,8 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 trait_to_skol_substs: &Substs<'tcx>)
                                                 -> Result<(), ErrorReported> {
     let span = tcx.sess.codemap().def_span(span);
-    let trait_params = &trait_generics.regions[..];
-    let impl_params = &impl_generics.regions[..];
+    let trait_params = trait_generics.own_counts().lifetimes;
+    let impl_params = impl_generics.own_counts().lifetimes;
 
     debug!("check_region_bounds_on_impl_method: \
             trait_generics={:?} \
@@ -377,7 +377,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // but found 0" it's confusing, because it looks like there
     // are zero. Since I don't quite know how to phrase things at
     // the moment, give a kind of vague error message.
-    if trait_params.len() != impl_params.len() {
+    if trait_params != impl_params {
         let mut err = struct_span_err!(tcx.sess,
                                        span,
                                        E0195,
@@ -574,8 +574,8 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         -> Result<(), ErrorReported> {
     let impl_m_generics = tcx.generics_of(impl_m.def_id);
     let trait_m_generics = tcx.generics_of(trait_m.def_id);
-    let num_impl_m_type_params = impl_m_generics.types.len();
-    let num_trait_m_type_params = trait_m_generics.types.len();
+    let num_impl_m_type_params = impl_m_generics.own_counts().types;
+    let num_trait_m_type_params = trait_m_generics.own_counts().types;
     if num_impl_m_type_params != num_trait_m_type_params {
         let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap();
         let impl_m_item = tcx.hir.expect_impl_item(impl_m_node_id);
@@ -728,11 +728,24 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut error_found = false;
     let impl_m_generics = tcx.generics_of(impl_m.def_id);
     let trait_m_generics = tcx.generics_of(trait_m.def_id);
-    for (impl_ty, trait_ty) in impl_m_generics.types.iter().zip(trait_m_generics.types.iter()) {
-        if impl_ty.synthetic != trait_ty.synthetic {
-            let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap();
+    let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| {
+        match param.kind {
+            GenericParamDefKind::Type(ty) => Some((param.def_id, ty.synthetic)),
+            GenericParamDefKind::Lifetime => None,
+        }
+    });
+    let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| {
+        match param.kind {
+            GenericParamDefKind::Type(ty) => Some((param.def_id, ty.synthetic)),
+            GenericParamDefKind::Lifetime => None,
+        }
+    });
+    for ((impl_def_id, impl_synthetic),
+         (trait_def_id, trait_synthetic)) in impl_m_type_params.zip(trait_m_type_params) {
+        if impl_synthetic != trait_synthetic {
+            let impl_node_id = tcx.hir.as_local_node_id(impl_def_id).unwrap();
             let impl_span = tcx.hir.span(impl_node_id);
-            let trait_span = tcx.def_span(trait_ty.def_id);
+            let trait_span = tcx.def_span(trait_def_id);
             let mut err = struct_span_err!(tcx.sess,
                                            impl_span,
                                            E0643,
index fcf7541a159b02388449edd83fb53f0e0465d162..97e4a35ea4762a449220ad77c9fbd8521d53031b 100644 (file)
@@ -45,7 +45,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    let i_n_tps = tcx.generics_of(def_id).types.len();
+    let i_n_tps = tcx.generics_of(def_id).own_counts().types;
     if i_n_tps != n_tps {
         let span = match it.node {
             hir::ForeignItemFn(_, _, ref generics) => generics.span,
@@ -76,7 +76,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
-    let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
+    let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
     let name = it.name.as_str();
     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
@@ -342,11 +342,11 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                it: &hir::ForeignItem) {
     let param = |n| {
         let name = Symbol::intern(&format!("P{}", n)).as_interned_str();
-        tcx.mk_param(n, name)
+        tcx.mk_ty_param(n, name)
     };
 
     let def_id = tcx.hir.local_def_id(it.id);
-    let i_n_tps = tcx.generics_of(def_id).types.len();
+    let i_n_tps = tcx.generics_of(def_id).own_counts().types;
     let name = it.name.as_str();
 
     let (n_tps, inputs, output) = match &*name {
index 46288181037f49d596968d4bfa0b29736ec15b99..aa3a166d0656fd71136c0cafe013bb5a7a845da3 100644 (file)
@@ -15,7 +15,7 @@
 use hir::def_id::DefId;
 use rustc::ty::subst::Substs;
 use rustc::traits;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, GenericParamDefKind};
 use rustc::ty::subst::Subst;
 use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
 use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@@ -314,30 +314,32 @@ fn instantiate_method_substs(&mut self,
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
-        assert_eq!(method_generics.parent_count(), parent_substs.len());
+        assert_eq!(method_generics.parent_count, parent_substs.len());
         let provided = &segment.parameters;
-        Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
-            let i = def.index as usize;
+        let own_counts = method_generics.own_counts();
+        Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
+            let i = param.index as usize;
             if i < parent_substs.len() {
-                parent_substs.region_at(i)
-            } else if let Some(lifetime)
-                    = provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) {
-                AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
+                parent_substs[i]
             } else {
-                self.region_var_for_def(self.span, def)
-            }
-        }, |def, _cur_substs| {
-            let i = def.index as usize;
-            if i < parent_substs.len() {
-                parent_substs.type_at(i)
-            } else if let Some(ast_ty)
-                = provided.as_ref().and_then(|p| {
-                    p.types.get(i - parent_substs.len() - method_generics.regions.len())
-                })
-            {
-                self.to_ty(ast_ty)
-            } else {
-                self.type_var_for_def(self.span, def)
+                match param.kind {
+                    GenericParamDefKind::Lifetime => {
+                        if let Some(lifetime) = provided.as_ref().and_then(|p| {
+                            p.lifetimes.get(i - parent_substs.len())
+                        }) {
+                            return AstConv::ast_region_to_region(
+                                self.fcx, lifetime, Some(param)).into();
+                        }
+                    }
+                    GenericParamDefKind::Type(_) => {
+                        if let Some(ast_ty) = provided.as_ref().and_then(|p| {
+                            p.types.get(i - parent_substs.len() - own_counts.lifetimes)
+                        }) {
+                            return self.to_ty(ast_ty).into();
+                        }
+                    }
+                }
+                self.var_for_def(self.span, param)
             }
         })
     }
index 5f904a9419b1d6b85caf708d4460d5cd6682a428..15a8efd5885d77755c2ca725f822e64c5471b913 100644 (file)
@@ -19,6 +19,7 @@
 use rustc::ty::subst::Substs;
 use rustc::traits;
 use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
+use rustc::ty::GenericParamDefKind;
 use rustc::ty::subst::Subst;
 use rustc::infer::{self, InferOk};
 
@@ -253,17 +254,18 @@ pub fn lookup_method_in_trait(&self,
                trait_def_id);
 
         // Construct a trait-reference `self_ty : Trait<input_tys>`
-        let substs = Substs::for_item(self.tcx,
-                                      trait_def_id,
-                                      |def, _| self.region_var_for_def(span, def),
-                                      |def, _substs| {
-            if def.index == 0 {
-                self_ty
-            } else if let Some(ref input_types) = opt_input_types {
-                input_types[def.index as usize - 1]
-            } else {
-                self.type_var_for_def(span, def)
+        let substs = Substs::for_item(self.tcx, trait_def_id, |param, _| {
+            match param.kind {
+                GenericParamDefKind::Lifetime => {}
+                GenericParamDefKind::Type(_) => {
+                    if param.index == 0 {
+                        return self_ty.into();
+                    } else if let Some(ref input_types) = opt_input_types {
+                        return input_types[param.index as usize - 1].into();
+                    }
+                }
             }
+            self.var_for_def(span, param)
         });
 
         let trait_ref = ty::TraitRef::new(trait_def_id, substs);
@@ -288,8 +290,7 @@ pub fn lookup_method_in_trait(&self,
         let method_item = self.associated_item(trait_def_id, m_name, Namespace::Value).unwrap();
         let def_id = method_item.def_id;
         let generics = tcx.generics_of(def_id);
-        assert_eq!(generics.types.len(), 0);
-        assert_eq!(generics.regions.len(), 0);
+        assert_eq!(generics.params.len(), 0);
 
         debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
         let mut obligations = vec![];
index e45565c2f52203783f1389b2a79d11f21d6f1869..6b860dbe8febbfee9a756afe14eb848d3f613fb0 100644 (file)
@@ -20,6 +20,7 @@
 use rustc::ty::subst::{Subst, Substs};
 use rustc::traits::{self, ObligationCause};
 use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
+use rustc::ty::GenericParamDefKind;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::util::nodemap::FxHashSet;
 use rustc::infer::{self, InferOk};
@@ -1378,31 +1379,28 @@ fn xform_method_sig(&self,
         // method yet. So create fresh variables here for those too,
         // if there are any.
         let generics = self.tcx.generics_of(method);
-        assert_eq!(substs.types().count(), generics.parent_types as usize);
-        assert_eq!(substs.regions().count(), generics.parent_regions as usize);
+        assert_eq!(substs.len(), generics.parent_count as usize);
 
         // Erase any late-bound regions from the method and substitute
         // in the values from the substitution.
         let xform_fn_sig = self.erase_late_bound_regions(&fn_sig);
 
-        if generics.types.is_empty() && generics.regions.is_empty() {
+        if generics.params.is_empty() {
             xform_fn_sig.subst(self.tcx, substs)
         } else {
-            let substs = Substs::for_item(self.tcx, method, |def, _| {
-                let i = def.index as usize;
+            let substs = Substs::for_item(self.tcx, method, |param, _| {
+                let i = param.index as usize;
                 if i < substs.len() {
-                    substs.region_at(i)
+                    substs[i]
                 } else {
-                    // In general, during probe we erase regions. See
-                    // `impl_self_ty()` for an explanation.
-                    self.tcx.types.re_erased
-                }
-            }, |def, _cur_substs| {
-                let i = def.index as usize;
-                if i < substs.len() {
-                    substs.type_at(i)
-                } else {
-                    self.type_var_for_def(self.span, def)
+                    match param.kind {
+                        GenericParamDefKind::Lifetime => {
+                            // In general, during probe we erase regions. See
+                            // `impl_self_ty()` for an explanation.
+                            self.tcx.types.re_erased.into()
+                        }
+                        GenericParamDefKind::Type(_) => self.var_for_def(self.span, param),
+                    }
                 }
             });
             xform_fn_sig.subst(self.tcx, substs)
@@ -1415,12 +1413,15 @@ fn impl_ty_and_substs(&self, impl_def_id: DefId) -> (Ty<'tcx>, &'tcx Substs<'tcx
     }
 
     fn fresh_item_substs(&self, def_id: DefId) -> &'tcx Substs<'tcx> {
-        Substs::for_item(self.tcx,
-                         def_id,
-                         |_, _| self.tcx.types.re_erased,
-                         |_, _| self.next_ty_var(
-                             TypeVariableOrigin::SubstitutionPlaceholder(
-                                 self.tcx.def_span(def_id))))
+        Substs::for_item(self.tcx, def_id, |param, _| {
+            match param.kind {
+                GenericParamDefKind::Lifetime => self.tcx.types.re_erased.into(),
+                GenericParamDefKind::Type(_) => {
+                    self.next_ty_var(TypeVariableOrigin::SubstitutionPlaceholder(
+                        self.tcx.def_span(def_id))).into()
+                }
+            }
+        })
     }
 
     /// Replace late-bound-regions bound by `value` with `'static` using
index 2d10e84be3a0a34a1a07b691f20c9c72d36dc220..955dc6f5aac3bea7dbec8d65941f229226bfc04e 100644 (file)
@@ -94,9 +94,9 @@
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
 use rustc::mir::interpret::{GlobalId};
-use rustc::ty::subst::{Kind, Subst, Substs};
+use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
-use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
+use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::maps::Providers;
@@ -1239,7 +1239,7 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
         } else {
             for item in &m.items {
                 let generics = tcx.generics_of(tcx.hir.local_def_id(item.id));
-                if !generics.types.is_empty() {
+                if generics.params.len() - generics.own_counts().lifetimes != 0 {
                     let mut err = struct_span_err!(tcx.sess, item.span, E0044,
                         "foreign items may not have type parameters");
                     err.span_label(item.span, "can't have type parameters");
@@ -1716,7 +1716,7 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
         let item_id = tcx.hir.ty_param_owner(node_id);
         let item_def_id = tcx.hir.local_def_id(item_id);
         let generics = tcx.generics_of(item_def_id);
-        let index = generics.type_param_to_index[&def_id];
+        let index = generics.param_def_id_to_index[&def_id];
         ty::GenericPredicates {
             parent: None,
             predicates: self.param_env.caller_bounds.iter().filter(|predicate| {
@@ -1730,7 +1730,7 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
         }
     }
 
-    fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)
+    fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>)
                 -> Option<ty::Region<'tcx>> {
         let v = match def {
             Some(def) => infer::EarlyBoundRegion(span, def.name),
@@ -1744,9 +1744,12 @@ fn ty_infer(&self, span: Span) -> Ty<'tcx> {
     }
 
     fn ty_infer_for_def(&self,
-                        ty_param_def: &ty::TypeParameterDef,
+                        ty_param_def: &ty::GenericParamDef,
                         span: Span) -> Ty<'tcx> {
-        self.type_var_for_def(span, ty_param_def)
+        if let UnpackedKind::Type(ty) = self.var_for_def(span, ty_param_def).unpack() {
+            return ty;
+        }
+        unreachable!()
     }
 
     fn projected_ty_from_poly_trait_ref(&self,
@@ -4751,73 +4754,77 @@ pub fn instantiate_value_path(&self,
 
         let (fn_start, has_self) = match (type_segment, fn_segment) {
             (_, Some((_, generics))) => {
-                (generics.parent_count(), generics.has_self)
+                (generics.parent_count, generics.has_self)
             }
             (Some((_, generics)), None) => {
-                (generics.own_count(), generics.has_self)
+                (generics.params.len(), generics.has_self)
             }
             (None, None) => (0, false)
         };
-        let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| {
-            let mut i = def.index as usize;
+        let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
+            let mut i = param.index as usize;
 
             let segment = if i < fn_start {
+                if let GenericParamDefKind::Type(_) = param.kind {
+                    // Handle Self first, so we can adjust the index to match the AST.
+                    if has_self && i == 0 {
+                        return opt_self_ty.map(|ty| Kind::from(ty)).unwrap_or_else(|| {
+                            self.var_for_def(span, param)
+                        });
+                    }
+                }
                 i -= has_self as usize;
                 type_segment
             } else {
                 i -= fn_start;
                 fn_segment
             };
-            let lifetimes = segment.map_or(&[][..], |(s, _)| {
-                s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
-            });
 
-            if let Some(lifetime) = lifetimes.get(i) {
-                AstConv::ast_region_to_region(self, lifetime, Some(def))
-            } else {
-                self.re_infer(span, Some(def)).unwrap()
-            }
-        }, |def, substs| {
-            let mut i = def.index as usize;
-
-            let segment = if i < fn_start {
-                // Handle Self first, so we can adjust the index to match the AST.
-                if has_self && i == 0 {
-                    return opt_self_ty.unwrap_or_else(|| {
-                        self.type_var_for_def(span, def)
+            match param.kind {
+                GenericParamDefKind::Lifetime => {
+                    let lifetimes = segment.map_or(&[][..], |(s, _)| {
+                        s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
                     });
+
+                    if let Some(lifetime) = lifetimes.get(i) {
+                        AstConv::ast_region_to_region(self, lifetime, Some(param)).into()
+                    } else {
+                        self.re_infer(span, Some(param)).unwrap().into()
+                    }
                 }
-                i -= has_self as usize;
-                type_segment
-            } else {
-                i -= fn_start;
-                fn_segment
-            };
-            let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
-                (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
-            });
+                GenericParamDefKind::Type(_) => {
+                    let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
+                        (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
+                    });
 
-            // Skip over the lifetimes in the same segment.
-            if let Some((_, generics)) = segment {
-                i -= generics.regions.len();
-            }
+                    // Skip over the lifetimes in the same segment.
+                    if let Some((_, generics)) = segment {
+                        i -= generics.own_counts().lifetimes;
+                    }
 
-            if let Some(ast_ty) = types.get(i) {
-                // A provided type parameter.
-                self.to_ty(ast_ty)
-            } else if !infer_types && def.has_default {
-                // No type parameter provided, but a default exists.
-                let default = self.tcx.type_of(def.def_id);
-                self.normalize_ty(
-                    span,
-                    default.subst_spanned(self.tcx, substs, Some(span))
-                )
-            } else {
-                // No type parameters were provided, we can infer all.
-                // This can also be reached in some error cases:
-                // We prefer to use inference variables instead of
-                // TyError to let type inference recover somewhat.
-                self.type_var_for_def(span, def)
+                    let has_default = match param.kind {
+                        GenericParamDefKind::Type(ty) => ty.has_default,
+                        _ => unreachable!()
+                    };
+
+                    if let Some(ast_ty) = types.get(i) {
+                        // A provided type parameter.
+                        self.to_ty(ast_ty).into()
+                    } else if !infer_types && has_default {
+                        // No type parameter provided, but a default exists.
+                        let default = self.tcx.type_of(param.def_id);
+                        self.normalize_ty(
+                            span,
+                            default.subst_spanned(self.tcx, substs, Some(span))
+                        ).into()
+                    } else {
+                        // No type parameters were provided, we can infer all.
+                        // This can also be reached in some error cases:
+                        // We prefer to use inference variables instead of
+                        // TyError to let type inference recover somewhat.
+                        self.var_for_def(span, param)
+                    }
+                }
             }
         });
 
@@ -4917,18 +4924,40 @@ fn check_path_parameter_count(&self,
             format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
         };
 
-        // Check provided type parameters.
-        let type_defs = segment.map_or(&[][..], |(_, generics)| {
-            if generics.parent.is_none() {
-                &generics.types[generics.has_self as usize..]
-            } else {
-                &generics.types
-            }
-        });
-        let required_len = type_defs.iter().take_while(|d| !d.has_default).count();
-        if types.len() > type_defs.len() {
-            let span = types[type_defs.len()].span;
-            let expected_text = count_type_params(type_defs.len());
+        // Check provided parameters.
+        let ((ty_required, ty_accepted), lt_accepted) =
+            segment.map_or(((0, 0), 0), |(_, generics)| {
+                struct ParamRange {
+                    required: usize,
+                    accepted: usize
+                };
+
+                let mut lt_accepted = 0;
+                let mut ty_params = ParamRange { required: 0, accepted: 0 };
+                for param in &generics.params {
+                    match param.kind {
+                        GenericParamDefKind::Lifetime => {
+                            lt_accepted += 1;
+                        }
+                        GenericParamDefKind::Type(ty) => {
+                            ty_params.accepted += 1;
+                            if !ty.has_default {
+                                ty_params.required += 1;
+                            }
+                        }
+                    };
+                }
+                if generics.parent.is_none() && generics.has_self {
+                    ty_params.required -= 1;
+                    ty_params.accepted -= 1;
+                }
+
+                ((ty_params.required, ty_params.accepted), lt_accepted)
+            });
+
+        if types.len() > ty_accepted {
+            let span = types[ty_accepted].span;
+            let expected_text = count_type_params(ty_accepted);
             let actual_text = count_type_params(types.len());
             struct_span_err!(self.tcx.sess, span, E0087,
                              "too many type parameters provided: \
@@ -4941,8 +4970,8 @@ fn check_path_parameter_count(&self,
             // type parameters, we force instantiate_value_path to
             // use inference variables instead of the provided types.
             *segment = None;
-        } else if types.len() < required_len && !infer_types && !supress_mismatch_error {
-            let expected_text = count_type_params(required_len);
+        } else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
+            let expected_text = count_type_params(ty_required);
             let actual_text = count_type_params(types.len());
             struct_span_err!(self.tcx.sess, span, E0089,
                              "too few type parameters provided: \
@@ -4956,10 +4985,6 @@ fn check_path_parameter_count(&self,
             AstConv::prohibit_projection(self, bindings[0].span);
         }
 
-        // Check provided lifetime parameters.
-        let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
-        let required_len = lifetime_defs.len();
-
         // Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
         let has_late_bound_lifetime_defs =
             segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
@@ -4968,8 +4993,8 @@ fn check_path_parameter_count(&self,
             let primary_msg = "cannot specify lifetime arguments explicitly \
                                if late bound lifetime parameters are present";
             let note_msg = "the late bound lifetime parameter is introduced here";
-            if !is_method_call && (lifetimes.len() > lifetime_defs.len() ||
-                                   lifetimes.len() < required_len && !infer_lifetimes) {
+            if !is_method_call && (lifetimes.len() > lt_accepted ||
+                                   lifetimes.len() < lt_accepted && !infer_lifetimes) {
                 let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
                 err.span_note(span_late, note_msg);
                 err.emit();
@@ -4983,9 +5008,9 @@ fn check_path_parameter_count(&self,
             return;
         }
 
-        if lifetimes.len() > lifetime_defs.len() {
-            let span = lifetimes[lifetime_defs.len()].span;
-            let expected_text = count_lifetime_params(lifetime_defs.len());
+        if lifetimes.len() > lt_accepted {
+            let span = lifetimes[lt_accepted].span;
+            let expected_text = count_lifetime_params(lt_accepted);
             let actual_text = count_lifetime_params(lifetimes.len());
             struct_span_err!(self.tcx.sess, span, E0088,
                              "too many lifetime parameters provided: \
@@ -4993,8 +5018,8 @@ fn check_path_parameter_count(&self,
                              expected_text, actual_text)
                 .span_label(span, format!("expected {}", expected_text))
                 .emit();
-        } else if lifetimes.len() < required_len && !infer_lifetimes {
-            let expected_text = count_lifetime_params(lifetime_defs.len());
+        } else if lifetimes.len() < lt_accepted && !infer_lifetimes {
+            let expected_text = count_lifetime_params(lt_accepted);
             let actual_text = count_lifetime_params(lifetimes.len());
             struct_span_err!(self.tcx.sess, span, E0090,
                              "too few lifetime parameters provided: \
@@ -5010,17 +5035,16 @@ fn check_impl_trait(&self,
                         span: Span,
                         segment: &mut Option<(&hir::PathSegment, &ty::Generics)>)
                         -> bool {
-        use hir::SyntheticTyParamKind::*;
-
         let segment = segment.map(|(path_segment, generics)| {
             let explicit = !path_segment.infer_types;
-            let impl_trait = generics.types.iter()
-                                           .any(|ty_param| {
-                                               match ty_param.synthetic {
-                                                   Some(ImplTrait) => true,
-                                                   _ => false,
-                                               }
-                                           });
+            let impl_trait = generics.params.iter().any(|param| {
+                if let ty::GenericParamDefKind::Type(ty) = param.kind {
+                    if let Some(hir::SyntheticTyParamKind::ImplTrait) = ty.synthetic {
+                        return true;
+                    }
+                }
+                false
+            });
 
             if explicit && impl_trait {
                 let mut err = struct_span_err! {
index d0ff44c8e7e10e65da9a3ad874edecb4ecdf7cb3..6b873c093c02f616b11e9c58b247ba4b78f668a2 100644 (file)
@@ -13,7 +13,8 @@
 
 use hir::def_id::DefId;
 use rustc::traits::{self, ObligationCauseCode};
-use rustc::ty::{self, Lift, Ty, TyCtxt};
+use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind};
+use rustc::ty::subst::Substs;
 use rustc::ty::util::ExplicitSelf;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::middle::lang_items;
@@ -187,7 +188,7 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 fcx.register_wf_obligation(ty, span, code.clone());
             }
             ty::AssociatedKind::Method => {
-                reject_shadowing_type_parameters(fcx.tcx, item.def_id);
+                reject_shadowing_parameters(fcx.tcx, item.def_id);
                 let sig = fcx.tcx.fn_sig(item.def_id);
                 let sig = fcx.normalize_associated_types_in(span, &sig);
                 check_fn_or_method(tcx, fcx, span, sig,
@@ -368,21 +369,31 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
     let mut substituted_predicates = Vec::new();
 
     let generics = tcx.generics_of(def_id);
-    let is_our_default = |def: &ty::TypeParameterDef|
-                            def.has_default && def.index >= generics.parent_count() as u32;
+    let is_our_default = |def: &ty::GenericParamDef| {
+        match def.kind {
+            GenericParamDefKind::Type(ty) => {
+                ty.has_default && def.index >= generics.parent_count as u32
+            }
+            _ => unreachable!()
+        }
+    };
 
     // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
     // For example this forbids the declaration:
     // struct Foo<T = Vec<[u32]>> { .. }
     // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
-    for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
-        let ty = fcx.tcx.type_of(d);
-        // ignore dependent defaults -- that is, where the default of one type
-        // parameter includes another (e.g., <T, U = T>). In those cases, we can't
-        // be sure if it will error or not as user might always specify the other.
-        if !ty.needs_subst() {
-            fcx.register_wf_obligation(ty, fcx.tcx.def_span(d),
-                ObligationCauseCode::MiscObligation);
+    for param in &generics.params {
+        if let GenericParamDefKind::Type(_) = param.kind {
+            if is_our_default(&param) {
+                let ty = fcx.tcx.type_of(param.def_id);
+                // ignore dependent defaults -- that is, where the default of one type
+                // parameter includes another (e.g., <T, U = T>). In those cases, we can't
+                // be sure if it will error or not as user might always specify the other.
+                if !ty.needs_subst() {
+                    fcx.register_wf_obligation(ty, fcx.tcx.def_span(param.def_id),
+                        ObligationCauseCode::MiscObligation);
+                }
+            }
         }
     }
 
@@ -394,22 +405,27 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
     // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
     //
     // First we build the defaulted substitution.
-    let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
-            // All regions are identity.
-            fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
-        }, |def, _| {
-            // If the param has a default,
-            if is_our_default(def) {
-                let default_ty = fcx.tcx.type_of(def.def_id);
-                // and it's not a dependent default
-                if !default_ty.needs_subst() {
-                    // then substitute with the default.
-                    return default_ty;
+    let substs = Substs::for_item(fcx.tcx, def_id, |param, _| {
+        match param.kind {
+            GenericParamDefKind::Lifetime => {
+                // All regions are identity.
+                fcx.tcx.mk_param_from_def(param)
+            }
+            GenericParamDefKind::Type(_) => {
+                // If the param has a default,
+                if is_our_default(param) {
+                    let default_ty = fcx.tcx.type_of(param.def_id);
+                    // and it's not a dependent default
+                    if !default_ty.needs_subst() {
+                        // then substitute with the default.
+                        return default_ty.into();
+                    }
                 }
+                // Mark unwanted params as err.
+                fcx.tcx.types.err.into()
             }
-            // Mark unwanted params as err.
-            fcx.tcx.types.err
-        });
+        }
+    });
     // Now we build the substituted predicates.
     for &pred in predicates.predicates.iter() {
         struct CountParams { params: FxHashSet<u32> }
@@ -638,15 +654,25 @@ fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     err.emit();
 }
 
-fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
+fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
     let generics = tcx.generics_of(def_id);
     let parent = tcx.generics_of(generics.parent.unwrap());
-    let impl_params: FxHashMap<_, _> = parent.types
-                                       .iter()
-                                       .map(|tp| (tp.name, tp.def_id))
-                                       .collect();
-
-    for method_param in &generics.types {
+    let impl_params: FxHashMap<_, _> =
+        parent.params.iter()
+                     .flat_map(|param| {
+                         match param.kind {
+                             GenericParamDefKind::Lifetime => None,
+                             GenericParamDefKind::Type(_) => Some((param.name, param.def_id)),
+                         }
+                     })
+                     .collect();
+
+    for method_param in generics.params.iter() {
+        match method_param.kind {
+            // Shadowing is checked in resolve_lifetime.
+            GenericParamDefKind::Lifetime => continue,
+            _ => {},
+        };
         if impl_params.contains_key(&method_param.name) {
             // Tighten up the span to focus on only the shadowing type
             let type_span = tcx.def_span(method_param.def_id);
index f0f392a2458e9079389458bfd3aa7239299fb37f..c2dde2d2e014b1f7fb403adb82c5cc43e71055d5 100644 (file)
@@ -181,7 +181,7 @@ fn get_type_parameter_bounds(&self,
         self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
     }
 
-    fn re_infer(&self, _span: Span, _def: Option<&ty::RegionParameterDef>)
+    fn re_infer(&self, _span: Span, _def: Option<&ty::GenericParamDef>)
                 -> Option<ty::Region<'tcx>> {
         None
     }
@@ -243,8 +243,8 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let param_owner = tcx.hir.ty_param_owner(param_id);
     let param_owner_def_id = tcx.hir.local_def_id(param_owner);
     let generics = tcx.generics_of(param_owner_def_id);
-    let index = generics.type_param_to_index[&def_id];
-    let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_interned_str());
+    let index = generics.param_def_id_to_index[&def_id];
+    let ty = tcx.mk_ty_param(index, tcx.hir.ty_param_name(param_id).as_interned_str());
 
     // Don't look for bounds where the type parameter isn't in scope.
     let parent = if item_def_id == param_owner_def_id {
@@ -840,14 +840,16 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     // the node id for the Self type parameter.
                     let param_id = item.id;
 
-                    opt_self = Some(ty::TypeParameterDef {
+                    opt_self = Some(ty::GenericParamDef {
                         index: 0,
                         name: keywords::SelfType.name().as_interned_str(),
                         def_id: tcx.hir.local_def_id(param_id),
-                        has_default: false,
-                        object_lifetime_default: rl::Set1::Empty,
                         pure_wrt_drop: false,
-                        synthetic: None,
+                        kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
+                            has_default: false,
+                            object_lifetime_default: rl::Set1::Empty,
+                            synthetic: None,
+                        }),
                     });
 
                     allow_defaults = true;
@@ -876,31 +878,33 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let has_self = opt_self.is_some();
     let mut parent_has_self = false;
     let mut own_start = has_self as u32;
-    let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| {
+    let parent_count = parent_def_id.map_or(0, |def_id| {
         let generics = tcx.generics_of(def_id);
         assert_eq!(has_self, false);
         parent_has_self = generics.has_self;
         own_start = generics.count() as u32;
-        (generics.parent_regions + generics.regions.len() as u32,
-            generics.parent_types + generics.types.len() as u32)
+        generics.parent_count + generics.params.len()
     });
 
+    let mut params: Vec<_> = opt_self.into_iter().collect();
+
     let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
-    let regions = early_lifetimes.enumerate().map(|(i, l)| {
-        ty::RegionParameterDef {
+    params.extend(early_lifetimes.enumerate().map(|(i, l)| {
+        ty::GenericParamDef {
             name: l.lifetime.name.name().as_interned_str(),
             index: own_start + i as u32,
             def_id: tcx.hir.local_def_id(l.lifetime.id),
             pure_wrt_drop: l.pure_wrt_drop,
+            kind: ty::GenericParamDefKind::Lifetime,
         }
-    }).collect::<Vec<_>>();
+    }));
 
     let hir_id = tcx.hir.node_to_hir_id(node_id);
     let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id);
 
     // Now create the real type parameters.
-    let type_start = own_start + regions.len() as u32;
-    let types = ast_generics.ty_params().enumerate().map(|(i, p)| {
+    let type_start = own_start - has_self as u32 + params.len() as u32;
+    params.extend(ast_generics.ty_params().enumerate().map(|(i, p)| {
         if p.name == keywords::SelfType.name() {
             span_bug!(p.span, "`Self` should not be the name of a regular parameter");
         }
@@ -916,19 +920,19 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
 
-        ty::TypeParameterDef {
+        ty::GenericParamDef {
             index: type_start + i as u32,
             name: p.name.as_interned_str(),
             def_id: tcx.hir.local_def_id(p.id),
-            has_default: p.default.is_some(),
-            object_lifetime_default:
-                object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
             pure_wrt_drop: p.pure_wrt_drop,
-            synthetic: p.synthetic,
+            kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
+                has_default: p.default.is_some(),
+                object_lifetime_default:
+                    object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
+                synthetic: p.synthetic,
+            }),
         }
-    });
-
-    let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
+    }));
 
     // provide junk type parameter defs - the only place that
     // cares about anything but the length is instantiation,
@@ -941,43 +945,45 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
 
         for (i, &arg) in dummy_args.iter().enumerate() {
-            types.push(ty::TypeParameterDef {
+            params.push(ty::GenericParamDef {
                 index: type_start + i as u32,
                 name: Symbol::intern(arg).as_interned_str(),
                 def_id,
-                has_default: false,
-                object_lifetime_default: rl::Set1::Empty,
                 pure_wrt_drop: false,
-                synthetic: None,
+                kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
+                    has_default: false,
+                    object_lifetime_default: rl::Set1::Empty,
+                    synthetic: None,
+                }),
             });
         }
 
         tcx.with_freevars(node_id, |fv| {
-            types.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
-                ty::TypeParameterDef {
+            params.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
+                ty::GenericParamDef {
                     index: type_start + i,
                     name: Symbol::intern("<upvar>").as_interned_str(),
                     def_id,
-                    has_default: false,
-                    object_lifetime_default: rl::Set1::Empty,
                     pure_wrt_drop: false,
-                    synthetic: None,
+                    kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
+                        has_default: false,
+                        object_lifetime_default: rl::Set1::Empty,
+                        synthetic: None,
+                    }),
                 }
             }));
         });
     }
 
-    let type_param_to_index = types.iter()
-                                   .map(|param| (param.def_id, param.index))
-                                   .collect();
+    let param_def_id_to_index = params.iter()
+                                      .map(|param| (param.def_id, param.index))
+                                      .collect();
 
     tcx.alloc_generics(ty::Generics {
         parent: parent_def_id,
-        parent_regions,
-        parent_types,
-        regions,
-        types,
-        type_param_to_index,
+        parent_count,
+        params,
+        param_def_id_to_index,
         has_self: has_self || parent_has_self,
         has_late_bound_regions: has_late_bound_regions(tcx, node),
     })
@@ -1090,15 +1096,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
 
             let substs = ty::ClosureSubsts {
-                substs: Substs::for_item(
-                    tcx,
-                    def_id,
-                    |def, _| {
-                        let region = def.to_early_bound_region_data();
-                        tcx.mk_region(ty::ReEarlyBound(region))
-                    },
-                    |def, _| tcx.mk_param_from_def(def)
-                )
+                substs: Substs::identity_for_item(tcx, def_id),
             };
 
             tcx.mk_closure(def_id, substs)
@@ -1390,7 +1388,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
 
     let generics = tcx.generics_of(def_id);
-    let parent_count = generics.parent_count() as u32;
+    let parent_count = generics.parent_count as u32;
     let has_own_self = generics.has_self && parent_count == 0;
 
     let mut predicates = vec![];
index faf3ccb1133adcb89c9a18a168d0120f8aa5a228..80dde814c6638a529eee689fc4b0e552150f37cd 100644 (file)
@@ -72,10 +72,9 @@ struct ImplWfCheck<'a, 'tcx: 'a> {
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
-            hir::ItemImpl(.., ref generics, _, _, ref impl_item_refs) => {
+            hir::ItemImpl(.., ref impl_item_refs) => {
                 let impl_def_id = self.tcx.hir.local_def_id(item.id);
                 enforce_impl_params_are_constrained(self.tcx,
-                                                    generics,
                                                     impl_def_id,
                                                     impl_item_refs);
                 enforce_impl_items_are_distinct(self.tcx, impl_item_refs);
@@ -90,7 +89,6 @@ fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { }
 }
 
 fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                 impl_hir_generics: &hir::Generics,
                                                  impl_def_id: DefId,
                                                  impl_item_refs: &[hir::ImplItemRef])
 {
@@ -104,17 +102,9 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ctp::identify_constrained_type_params(
         tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
 
-    // Disallow ANY unconstrained type parameters.
-    for (ty_param, param) in impl_generics.types.iter().zip(impl_hir_generics.ty_params()) {
-        let param_ty = ty::ParamTy::for_def(ty_param);
-        if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
-            report_unused_parameter(tcx, param.span, "type", &param_ty.to_string());
-        }
-    }
-
     // Disallow unconstrained lifetimes, but only if they appear in assoc types.
     let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter()
-        .map(|item_ref|  tcx.hir.local_def_id(item_ref.id.node_id))
+        .map(|item_ref| tcx.hir.local_def_id(item_ref.id.node_id))
         .filter(|&def_id| {
             let item = tcx.associated_item(def_id);
             item.kind == ty::AssociatedKind::Type && item.defaultness.has_value()
@@ -122,17 +112,29 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         .flat_map(|def_id| {
             ctp::parameters_for(&tcx.type_of(def_id), true)
         }).collect();
-    for (ty_lifetime, lifetime) in impl_generics.regions.iter()
-        .zip(impl_hir_generics.lifetimes())
-    {
-        let param = ctp::Parameter::from(ty_lifetime.to_early_bound_region_data());
 
-        if
-            lifetimes_in_associated_types.contains(&param) && // (*)
-            !input_parameters.contains(&param)
-        {
-            report_unused_parameter(tcx, lifetime.lifetime.span,
-                                    "lifetime", &lifetime.lifetime.name.name().to_string());
+    for param in &impl_generics.params {
+        match param.kind {
+            // Disallow ANY unconstrained type parameters.
+            ty::GenericParamDefKind::Type(_) => {
+                let param_ty = ty::ParamTy::for_def(param);
+                if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
+                    report_unused_parameter(tcx,
+                                            tcx.def_span(param.def_id),
+                                            "type",
+                                            &param_ty.to_string());
+                }
+            }
+            ty::GenericParamDefKind::Lifetime => {
+                let param_lt = ctp::Parameter::from(param.to_early_bound_region_data());
+                if lifetimes_in_associated_types.contains(&param_lt) && // (*)
+                    !input_parameters.contains(&param_lt) {
+                    report_unused_parameter(tcx,
+                                            tcx.def_span(param.def_id),
+                                            "lifetime",
+                                            &param.name.to_string());
+                }
+            }
         }
     }
 
index 5a9539a8badf01ab87a6fbd1756733f39361f0fc..e711598c944c12ba0031efe79c08b8e8f656ac47 100644 (file)
@@ -353,7 +353,7 @@ fn insert_outlives_predicate<'tcx>(
                         // Vec<U>`.  Decomposing `Vec<U>` into
                         // components would yield `U`, and we add the
                         // where clause that `U: 'a`.
-                        let ty: Ty<'tcx> = tcx.mk_param(param_ty.idx, param_ty.name);
+                        let ty: Ty<'tcx> = tcx.mk_ty_param(param_ty.idx, param_ty.name);
                         required_predicates
                             .insert(ty::OutlivesPredicate(ty.into(), outlived_region));
                     }
index 722dcb7fe6a73f750b41f3aee6ca1dd891ee8d80..d7646ce7bfc5ca4fb24dded85c7ca43bfb765438 100644 (file)
@@ -224,42 +224,39 @@ fn get_auto_trait_impl_for(
     }
 
     fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters {
-        let lifetimes = HirVec::from_vec(
-            generics
-                .regions
-                .iter()
-                .map(|p| {
-                    let name = if p.name == "" {
+        let mut lifetimes = vec![];
+        let mut types = vec![];
+
+        for param in generics.params.iter() {
+            match param.kind {
+                ty::GenericParamDefKind::Lifetime => {
+                    let name = if param.name == "" {
                         hir::LifetimeName::Static
                     } else {
-                        hir::LifetimeName::Name(p.name.as_symbol())
+                        hir::LifetimeName::Name(param.name.as_symbol())
                     };
 
-                    hir::Lifetime {
+                    lifetimes.push(hir::Lifetime {
                         id: ast::DUMMY_NODE_ID,
                         span: DUMMY_SP,
                         name,
-                    }
-                })
-                .collect(),
-        );
-        let types = HirVec::from_vec(
-            generics
-                .types
-                .iter()
-                .map(|p| P(self.ty_param_to_ty(p.clone())))
-                .collect(),
-        );
+                    });
+                }
+                ty::GenericParamDefKind::Type(_) => {
+                    types.push(P(self.ty_param_to_ty(param.clone())));
+                }
+            }
+        }
 
         hir::PathParameters {
-            lifetimes: lifetimes,
-            types: types,
+            lifetimes: HirVec::from_vec(lifetimes),
+            types: HirVec::from_vec(types),
             bindings: HirVec::new(),
             parenthesized: false,
         }
     }
 
-    fn ty_param_to_ty(&self, param: ty::TypeParameterDef) -> hir::Ty {
+    fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty {
         debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id);
         hir::Ty {
             id: ast::DUMMY_NODE_ID,
@@ -494,7 +491,7 @@ fn extract_for_generics<'b, 'c, 'd>(
         &self,
         tcx: TyCtxt<'b, 'c, 'd>,
         pred: ty::Predicate<'d>,
-    ) -> FxHashSet<GenericParam> {
+    ) -> FxHashSet<GenericParamDef> {
         pred.walk_tys()
             .flat_map(|t| {
                 let mut regions = FxHashSet();
@@ -505,7 +502,7 @@ fn extract_for_generics<'b, 'c, 'd>(
                         // We only care about late bound regions, as we need to add them
                         // to the 'for<>' section
                         &ty::ReLateBound(_, ty::BoundRegion::BrNamed(_, name)) => {
-                            Some(GenericParam::Lifetime(Lifetime(name.to_string())))
+                            Some(GenericParamDef::Lifetime(Lifetime(name.to_string())))
                         }
                         &ty::ReVar(_) | &ty::ReEarlyBound(_) => None,
                         _ => panic!("Unexpected region type {:?}", r),
@@ -853,7 +850,7 @@ fn param_env_to_generics<'b, 'c, 'cx>(
 
         for p in generic_params.iter_mut() {
             match p {
-                &mut GenericParam::Type(ref mut ty) => {
+                &mut GenericParamDef::Type(ref mut ty) => {
                     // We never want something like 'impl<T=Foo>'
                     ty.default.take();
 
@@ -863,7 +860,7 @@ fn param_env_to_generics<'b, 'c, 'cx>(
                         ty.bounds.insert(0, TyParamBound::maybe_sized(self.cx));
                     }
                 }
-                _ => {}
+                GenericParamDef::Lifetime(_) => {}
             }
         }
 
index 386e6ca5c773c733bef4562c5af532a837dd9619..a1d77f4145b83f19f77a2c2bcf707035fce13bb0 100644 (file)
@@ -41,7 +41,7 @@
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::hir::def_id::DefIndexAddressSpace;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
+use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind, GenericParamCount};
 use rustc::middle::stability;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_typeck::hir_ty_to_ty;
@@ -1336,14 +1336,18 @@ fn clean(&self, cx: &DocContext) -> TyParam {
     }
 }
 
-impl<'tcx> Clean<TyParam> for ty::TypeParameterDef {
+impl<'tcx> Clean<TyParam> for ty::GenericParamDef {
     fn clean(&self, cx: &DocContext) -> TyParam {
         cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
+        let has_default = match self.kind {
+            ty::GenericParamDefKind::Type(ty) => ty.has_default,
+            _ => panic!("tried to convert a non-type GenericParamDef as a type")
+        };
         TyParam {
             name: self.name.clean(cx),
             did: self.def_id,
             bounds: vec![], // these are filled in from the where-clauses
-            default: if self.has_default {
+            default: if has_default {
                 Some(cx.tcx.type_of(self.def_id).clean(cx))
             } else {
                 None
@@ -1484,7 +1488,7 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
                         if let &ty::RegionKind::ReLateBound(..) = *reg {
                             debug!("  hit an ReLateBound {:?}", reg);
                             if let Some(lt) = reg.clean(cx) {
-                                late_bounds.push(GenericParam::Lifetime(lt));
+                                late_bounds.push(GenericParamDef::Lifetime(lt));
                             }
                         }
                     }
@@ -1577,8 +1581,8 @@ fn clean(&self, _: &DocContext) -> Lifetime {
     }
 }
 
-impl Clean<Lifetime> for ty::RegionParameterDef {
-    fn clean(&self, _: &DocContext) -> Lifetime {
+impl<'tcx> Clean<Lifetime> for ty::GenericParamDef {
+    fn clean(&self, _cx: &DocContext) -> Lifetime {
         Lifetime(self.name.to_string())
     }
 }
@@ -1718,26 +1722,25 @@ fn clean(&self, cx: &DocContext) -> Type {
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
-pub enum GenericParam {
+pub enum GenericParamDef {
     Lifetime(Lifetime),
     Type(TyParam),
 }
 
-impl GenericParam {
+impl GenericParamDef {
     pub fn is_synthetic_type_param(&self) -> bool {
-        if let GenericParam::Type(ref t) = *self {
-            t.synthetic.is_some()
-        } else {
-            false
+        match self {
+            GenericParamDef::Type(ty) => ty.synthetic.is_some(),
+            GenericParamDef::Lifetime(_) => false,
         }
     }
 }
 
-impl Clean<GenericParam> for hir::GenericParam {
-    fn clean(&self, cx: &DocContext) -> GenericParam {
+impl Clean<GenericParamDef> for hir::GenericParam {
+    fn clean(&self, cx: &DocContext) -> GenericParamDef {
         match *self {
-            hir::GenericParam::Lifetime(ref l) => GenericParam::Lifetime(l.clean(cx)),
-            hir::GenericParam::Type(ref t) => GenericParam::Type(t.clean(cx)),
+            hir::GenericParam::Lifetime(ref l) => GenericParamDef::Lifetime(l.clean(cx)),
+            hir::GenericParam::Type(ref t) => GenericParamDef::Type(t.clean(cx)),
         }
     }
 }
@@ -1745,7 +1748,7 @@ fn clean(&self, cx: &DocContext) -> GenericParam {
 // maybe use a Generic enum and use Vec<Generic>?
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
 pub struct Generics {
-    pub params: Vec<GenericParam>,
+    pub params: Vec<GenericParamDef>,
     pub where_predicates: Vec<WherePredicate>,
 }
 
@@ -1754,7 +1757,7 @@ fn clean(&self, cx: &DocContext) -> Generics {
         let mut params = Vec::with_capacity(self.params.len());
         for p in &self.params {
             let p = p.clean(cx);
-            if let GenericParam::Type(ref tp) = p {
+            if let GenericParamDef::Type(ref tp) = p {
                 if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
                     cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone());
                 }
@@ -1774,7 +1777,7 @@ fn clean(&self, cx: &DocContext) -> Generics {
                 WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
                     if bounds.is_empty() {
                         for param in &mut g.params {
-                            if let GenericParam::Type(ref mut type_param) = *param {
+                            if let GenericParamDef::Type(ref mut type_param) = *param {
                                 if &type_param.name == name {
                                     mem::swap(bounds, &mut type_param.bounds);
                                     break
@@ -1800,14 +1803,18 @@ fn clean(&self, cx: &DocContext) -> Generics {
         // Bounds in the type_params and lifetimes fields are repeated in the
         // predicates field (see rustc_typeck::collect::ty_generics), so remove
         // them.
-        let stripped_typarams = gens.types.iter().filter_map(|tp| {
-            if tp.name == keywords::SelfType.name().as_str() {
-                assert_eq!(tp.index, 0);
-                None
+        let stripped_typarams = gens.params.iter().filter_map(|param| {
+            if let ty::GenericParamDefKind::Type(_) = param.kind {
+                if param.name == keywords::SelfType.name().as_str() {
+                    assert_eq!(param.index, 0);
+                    None
+                } else {
+                    Some(param.clean(cx))
+                }
             } else {
-                Some(tp.clean(cx))
+                None
             }
-        }).collect::<Vec<_>>();
+        }).collect::<Vec<TyParam>>();
 
         let mut where_predicates = preds.predicates.to_vec().clean(cx);
 
@@ -1849,16 +1856,20 @@ fn clean(&self, cx: &DocContext) -> Generics {
         // and instead see `where T: Foo + Bar + Sized + 'a`
 
         Generics {
-            params: gens.regions
-                .clean(cx)
-                .into_iter()
-                .map(|lp| GenericParam::Lifetime(lp))
-                .chain(
-                    simplify::ty_params(stripped_typarams)
-                        .into_iter()
-                        .map(|tp| GenericParam::Type(tp))
-                )
-                .collect(),
+            params: gens.params
+                        .iter()
+                        .flat_map(|param| {
+                            if let ty::GenericParamDefKind::Lifetime = param.kind {
+                                Some(GenericParamDef::Lifetime(param.clean(cx)))
+                            } else {
+                                None
+                            }
+                        }).chain(
+                            simplify::ty_params(stripped_typarams)
+                                .into_iter()
+                                .map(|tp| GenericParamDef::Type(tp))
+                        )
+                        .collect(),
             where_predicates: simplify::where_clauses(cx, where_predicates),
         }
     }
@@ -2349,7 +2360,7 @@ fn clean(&self, cx: &DocContext) -> Item {
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
 pub struct PolyTrait {
     pub trait_: Type,
-    pub generic_params: Vec<GenericParam>,
+    pub generic_params: Vec<GenericParamDef>,
 }
 
 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
@@ -2676,20 +2687,34 @@ fn clean(&self, cx: &DocContext) -> Type {
                     let mut ty_substs = FxHashMap();
                     let mut lt_substs = FxHashMap();
                     provided_params.with_parameters(|provided_params| {
-                        for (i, ty_param) in generics.ty_params().enumerate() {
-                            let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
-                            if let Some(ty) = provided_params.types.get(i).cloned() {
-                                ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
-                            } else if let Some(default) = ty_param.default.clone() {
-                                ty_substs.insert(ty_param_def, default.into_inner().clean(cx));
-                            }
-                        }
-
-                        for (i, lt_param) in generics.lifetimes().enumerate() {
-                            if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
-                                if !lt.is_elided() {
-                                    let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
-                                    lt_substs.insert(lt_def_id, lt.clean(cx));
+                        let mut indices = GenericParamCount {
+                            lifetimes: 0,
+                            types: 0
+                        };
+                        for param in generics.params.iter() {
+                            match param {
+                                hir::GenericParam::Lifetime(lt_param) => {
+                                    if let Some(lt) = provided_params.lifetimes
+                                        .get(indices.lifetimes).cloned() {
+                                        if !lt.is_elided() {
+                                            let lt_def_id =
+                                                cx.tcx.hir.local_def_id(lt_param.lifetime.id);
+                                            lt_substs.insert(lt_def_id, lt.clean(cx));
+                                        }
+                                    }
+                                    indices.lifetimes += 1;
+                                }
+                                hir::GenericParam::Type(ty_param) => {
+                                    let ty_param_def =
+                                        Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
+                                    if let Some(ty) = provided_params.types
+                                        .get(indices.types).cloned() {
+                                        ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
+                                    } else if let Some(default) = ty_param.default.clone() {
+                                        ty_substs.insert(ty_param_def,
+                                                         default.into_inner().clean(cx));
+                                    }
+                                    indices.types += 1;
                                 }
                             }
                         }
@@ -3425,7 +3450,7 @@ fn clean(&self, cx: &DocContext) -> Item {
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
 pub struct BareFunctionDecl {
     pub unsafety: hir::Unsafety,
-    pub generic_params: Vec<GenericParam>,
+    pub generic_params: Vec<GenericParamDef>,
     pub decl: FnDecl,
     pub abi: Abi,
 }
@@ -4184,7 +4209,7 @@ struct RegionDeps<'tcx> {
 #[derive(Eq, PartialEq, Hash, Debug)]
 enum SimpleBound {
     RegionBound(Lifetime),
-    TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParam>, hir::TraitBoundModifier)
+    TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier)
 }
 
 enum AutoTraitResult {
index 2db57c97dd4667b33c6fd9bcf9acbfe2c518d4de..40dcd6e891fe8cfba1161c4335c4fd7c33c2b580 100644 (file)
@@ -117,11 +117,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl fmt::Display for clean::GenericParam {
+impl fmt::Display for clean::GenericParamDef {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            clean::GenericParam::Lifetime(ref lp) => write!(f, "{}", lp),
-            clean::GenericParam::Type(ref tp) => {
+            clean::GenericParamDef::Lifetime(ref lp) => write!(f, "{}", lp),
+            clean::GenericParamDef::Type(ref tp) => {
                 f.write_str(&tp.name)?;
 
                 if !tp.bounds.is_empty() {
index ab3af73cf17474a699d44160ac5502782227b754..109765b6711979899ac0513fe7a0990609101249 100644 (file)
@@ -1453,8 +1453,11 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
 impl<'a> Cache {
     fn generics(&mut self, generics: &clean::Generics) {
         for param in &generics.params {
-            if let clean::GenericParam::Type(ref typ) = *param {
-                self.typarams.insert(typ.did, typ.name.clone());
+            match *param {
+                clean::GenericParamDef::Type(ref typ) => {
+                    self.typarams.insert(typ.did, typ.name.clone());
+                }
+                clean::GenericParamDef::Lifetime(_) => {}
             }
         }
     }
index e7483dbd3b546ca1afe1c5a89dcc1c8c734925da..7ef155e5f2ebece26ddc962389863f4f1bc7d023 100644 (file)
@@ -28,7 +28,7 @@ trait BadAnnotation1
 {}
 
 #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
-//~^ ERROR there is no type parameter C on trait BadAnnotation2
+//~^ ERROR there is no parameter C on trait BadAnnotation2
 trait BadAnnotation2<A,B>
 {}
 
index c37383757384e4ed2797d50735cf5c068b460762..1c5d4d603afc662d6cae88914ec8a29104a74eb9 100644 (file)
@@ -6,7 +6,7 @@ LL | #[rustc_on_unimplemented] //~ ERROR `#[rustc_on_unimplemented]` requires a
    |
    = note: eg `#[rustc_on_unimplemented = "foo"]`
 
-error[E0230]: there is no type parameter C on trait BadAnnotation2
+error[E0230]: there is no parameter C on trait BadAnnotation2
   --> $DIR/bad-annotation.rs:30:1
    |
 LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]