]> git.lizzy.rs Git - rust.git/commitdiff
Generalise cases of explicit iteration of specific kinds
authorvarkor <github@varkor.com>
Thu, 12 Apr 2018 23:57:38 +0000 (00:57 +0100)
committervarkor <github@varkor.com>
Tue, 15 May 2018 13:21:03 +0000 (14:21 +0100)
src/librustc/hir/lowering.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/ty/mod.rs
src/librustc/util/ppaux.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/mod.rs

index fd2a328f2fdfaf1f744f181826c0153bf34fc7b3..5b6b0284de5204deb88103ed8e617682da1fb588 100644 (file)
@@ -374,8 +374,8 @@ fn visit_item(&mut self, item: &'lcx Item) {
 
                 if item_lowered {
                     let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
-                        hir::Item_::ItemImpl(_, _, _, ref generics, ..)
-                        | hir::Item_::ItemTrait(_, _, ref generics, ..) => {
+                        hir::Item_::ItemImpl(_, _, _, ref generics, .. ) |
+                        hir::Item_::ItemTrait(_, _, ref generics, .. ) => {
                             generics.lifetimes().cloned().collect::<Vec<_>>()
                         }
                         _ => Vec::new(),
index 225384ed0cb4769082fee338f81e92ba4ea16f22..a12506afb21f3e1017b60f13fba7759ee1e6929b 100644 (file)
@@ -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);
index 00a0d4dc554d57a2b6a474e42cdd7280511c3101..0dfb4572c35affca5ad0f22b2c375f2833b775b4 100644 (file)
@@ -382,8 +382,7 @@ fn on_unimplemented_note(
             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.clone(), Some(ty_str.clone())));
         }
 
         if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {
index a44dcc7c274e575cc39dce4b14f62dc4ddd86d7d..3fc95e9518fb427e7baa5b461781d566832fc703 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, GenericParamDef};
 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 mut types = generics.types();
         let mut result = Ok(());
         for token in parser {
             match token {
@@ -254,8 +253,12 @@ 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.find(|t| {
-                        t.name == s
+                    Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
+                        if let GenericParamDef::Type(ty) = param {
+                            ty.name == s
+                        } else {
+                            false
+                        }
                     }) {
                         Some(_) => (),
                         None => {
@@ -289,8 +292,7 @@ pub fn format(&self,
         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().map(|param| {
-            (param.name.to_string(),
-             trait_ref.substs.type_for_def(param).to_string())
+            (param.name.to_string(), trait_ref.substs.type_for_def(param).to_string())
         }).collect::<FxHashMap<String, String>>();
 
         let parser = Parser::new(&self.0);
index 59b88567a0d1cbf20ba882d3f5469de0d3f4c2e2..f7d09b5070c1074f18d55e4df0d30dcce4366895 100644 (file)
@@ -757,6 +757,18 @@ pub fn to_bound_region(&self) -> ty::BoundRegion {
     }
 }
 
+#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
+pub enum Kind {
+    Lifetime,
+    Type,
+}
+
+impl Kind {
+    pub fn iter<'a>() -> impl Iterator<Item = &'a Kind> {
+        [Kind::Lifetime, Kind::Type].into_iter()
+    }
+}
+
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum GenericParamDef {
     Lifetime(RegionParamDef),
@@ -799,6 +811,23 @@ pub fn count(&self) -> usize {
         self.parent_count + self.params.len()
     }
 
+    pub fn param_counts(&self) -> FxHashMap<Kind, usize> {
+        let mut param_counts: FxHashMap<_, _> = FxHashMap();
+        Kind::iter().for_each(|kind| {
+            param_counts.insert(*kind, 0);
+        });
+
+        for param in self.params.iter() {
+            let key = match param {
+                GenericParamDef::Type(_) => Kind::Type,
+                GenericParamDef::Lifetime(_) => Kind::Lifetime,
+            };
+            *param_counts.get_mut(&key).unwrap() += 1;
+        }
+
+        param_counts
+    }
+
     pub fn lifetimes(&self) -> impl DoubleEndedIterator<Item = &RegionParamDef> {
         self.params.iter().filter_map(|p| {
             if let GenericParamDef::Lifetime(lt) = p {
index 1a0c5f4a78a4236f8d4664b6d765065d3ea5ed37..c6a2dccac4952c64ad6c935066eb83ae9e9fa66b 100644 (file)
@@ -19,8 +19,8 @@
 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 util::nodemap::FxHashSet;
+use ty::{self, Ty, TyCtxt, TypeFoldable, Kind};
+use util::nodemap::{FxHashSet, FxHashMap};
 
 use std::cell::Cell;
 use std::fmt;
@@ -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 param_counts = FxHashMap();
+        Kind::iter().for_each(|kind| {
+            param_counts.insert(*kind, 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_param_counts = generics.param_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().count();
+                child_types = child_param_counts[&Kind::Type];
                 generics = tcx.generics_of(def_id);
-                num_regions = generics.lifetimes().count();
-                num_types = generics.types().count();
+                param_counts = generics.param_counts();
 
                 if has_self {
                     print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
@@ -328,8 +330,7 @@ fn parameterized<F: fmt::Write>(&mut self,
                     assert_eq!(has_self, false);
                 } else {
                     // Types and traits.
-                    num_regions = generics.lifetimes().count();
-                    num_types = generics.types().count();
+                    param_counts = child_param_counts;
                 }
             }
 
@@ -401,10 +402,11 @@ fn parameterized<F: fmt::Write>(&mut self,
             Ok(())
         };
 
-        print_regions(f, "<", 0, num_regions)?;
+        print_regions(f, "<", 0, param_counts[&Kind::Lifetime])?;
 
-        let tps = substs.types().take(num_types - num_supplied_defaults)
-                                .skip(has_self as usize);
+        let tps = substs.types()
+                        .take(param_counts[&Kind::Type] - num_supplied_defaults)
+                        .skip(has_self as usize);
 
         for ty in tps {
             start_or_continue(f, "<", ", ")?;
@@ -435,10 +437,10 @@ fn parameterized<F: fmt::Write>(&mut self,
                 write!(f, "::{}", item_name)?;
             }
 
-            print_regions(f, "::<", num_regions, usize::MAX)?;
+            print_regions(f, "::<", param_counts[&Kind::Lifetime], usize::MAX)?;
 
             // FIXME: consider being smart with defaults here too
-            for ty in substs.types().skip(num_types) {
+            for ty in substs.types().skip(param_counts[&Kind::Type]) {
                 start_or_continue(f, "::<", ", ")?;
                 ty.print_display(f, self)?;
             }
index 1282626974df03ea41c4a05168381e3f262a3182..d50c74da31302a1638b369f7cd746cdb20dcb1ed 100644 (file)
@@ -26,6 +26,7 @@
 use rustc::hir::TransFnAttrFlags;
 use rustc::hir::def_id::{DefId, CrateNum};
 use rustc::ty::subst::Substs;
+use rustc::ty::{Kind, GenericParamDef};
 
 use abi::Abi;
 use common::CodegenCx;
@@ -390,7 +391,14 @@ 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);
+            let names = get_parameter_names(cx, generics);
+            let names = names.iter().flat_map(|(kind, param)| {
+                if kind == &Kind::Type {
+                    Some(param)
+                } else {
+                    None
+                }
+            });
             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);
@@ -413,11 +421,18 @@ 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<(Kind, 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().map(|param| param.name));
+        names.extend(generics.params.iter().map(|param| {
+            match param {
+                GenericParamDef::Lifetime(lt) => (Kind::Lifetime, lt.name.as_str()),
+                GenericParamDef::Type(ty) => (Kind::Type, ty.name),
+            }
+        }));
         names
     }
 
index b427020908dc141a8bf14249266c241dde675cc3..44b0ebf7f01167b4704f080b7ce0540c8e5d3ab6 100644 (file)
@@ -96,7 +96,7 @@
 use rustc::mir::interpret::{GlobalId};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
-use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
+use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate, GenericParamDef};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::maps::Providers;
@@ -1239,7 +1239,8 @@ 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().count() != 0 {
+                let param_counts = generics.param_counts();
+                if generics.params.len() - param_counts[&ty::Kind::Lifetime] != 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");
@@ -4799,7 +4800,7 @@ pub fn instantiate_value_path(&self,
 
             // Skip over the lifetimes in the same segment.
             if let Some((_, generics)) = segment {
-                i -= generics.lifetimes().count();
+                i -= generics.param_counts()[&ty::Kind::Lifetime];
             }
 
             if let Some(ast_ty) = types.get(i) {
@@ -4917,18 +4918,28 @@ 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(vec![], |(_, generics)| {
-            if generics.parent.is_none() {
-                generics.types().skip(generics.has_self as usize).collect()
-            } else {
-                generics.types().collect()
-            }
-        });
-        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_non_def_req_len, ty_req_len, lt_req_len) =
+            segment.map_or((0, 0, 0), |(_, generics)| {
+                let params_count = generics.param_counts();
+
+                let offset_type_params = generics.parent.is_none() && generics.has_self;
+                let type_params = params_count[&ty::Kind::Type] - offset_type_params as usize;
+                let type_params_barring_defaults =
+                    type_params - generics.params.iter().filter(|param| {
+                        if let GenericParamDef::Type(ty) = param {
+                            ty.has_default
+                        } else {
+                            false
+                        }
+                    }).count();
+
+                (type_params_barring_defaults, type_params, params_count[&ty::Kind::Lifetime])
+            });
+
+        if types.len() > ty_req_len {
+            let span = types[ty_req_len].span;
+            let expected_text = count_type_params(ty_req_len);
             let actual_text = count_type_params(types.len());
             struct_span_err!(self.tcx.sess, span, E0087,
                              "too many type parameters provided: \
@@ -4941,8 +4952,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_non_def_req_len && !infer_types && !supress_mismatch_error {
+            let expected_text = count_type_params(ty_non_def_req_len);
             let actual_text = count_type_params(types.len());
             struct_span_err!(self.tcx.sess, span, E0089,
                              "too few type parameters provided: \
@@ -4956,10 +4967,6 @@ fn check_path_parameter_count(&self,
             AstConv::prohibit_projection(self, bindings[0].span);
         }
 
-        // Check provided lifetime parameters.
-        let lifetime_defs = segment.map_or(vec![], |(_, generics)| generics.lifetimes().collect());
-        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 +4975,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() > required_len ||
-                                   lifetimes.len() < required_len && !infer_lifetimes) {
+            if !is_method_call && (lifetimes.len() > lt_req_len ||
+                                   lifetimes.len() < lt_req_len && !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 +4990,9 @@ fn check_path_parameter_count(&self,
             return;
         }
 
-        if lifetimes.len() > required_len {
-            let span = lifetimes[required_len].span;
-            let expected_text = count_lifetime_params(required_len);
+        if lifetimes.len() > lt_req_len {
+            let span = lifetimes[lt_req_len].span;
+            let expected_text = count_lifetime_params(lt_req_len);
             let actual_text = count_lifetime_params(lifetimes.len());
             struct_span_err!(self.tcx.sess, span, E0088,
                              "too many lifetime parameters provided: \
@@ -4993,8 +5000,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(required_len);
+        } else if lifetimes.len() < lt_req_len && !infer_lifetimes {
+            let expected_text = count_lifetime_params(lt_req_len);
             let actual_text = count_lifetime_params(lifetimes.len());
             struct_span_err!(self.tcx.sess, span, E0090,
                              "too few lifetime parameters provided: \
@@ -5010,16 +5017,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().any(|ty_param| {
-                                                 match ty_param.synthetic {
-                                                     Some(ImplTrait) => true,
-                                                     _ => false,
-                                                 }
-                                             });
+            let impl_trait = generics.params.iter().any(|param| {
+                if let ty::GenericParamDef::Type(ty) = param {
+                    if let Some(hir::SyntheticTyParamKind::ImplTrait) = ty.synthetic {
+                        return true;
+                    }
+                }
+                false
+            });
 
             if explicit && impl_trait {
                 let mut err = struct_span_err! {
@@ -5086,12 +5093,22 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if generics.ty_params().next().is_none() { return; }
     let mut tps_used = vec![false; generics.ty_params().count()];
 
-    let lifetime_count = generics.lifetimes().count();
+    let mut param_counts = FxHashMap();
+    param_counts.insert(ty::Kind::Type, 0);
+    param_counts.insert(ty::Kind::Lifetime, 0);
+
+    for param in generics.params.iter() {
+        let key = match param {
+            hir::GenericParamDef::Type(_) => ty::Kind::Type,
+            hir::GenericParamDef::Lifetime(_) => ty::Kind::Lifetime,
+        };
+        *param_counts.get_mut(&key).unwrap() += 1;
+    }
 
     for leaf_ty in ty.walk() {
-        if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty {
+        if let ty::TyParam(ty::ParamTy {idx, .. }) = leaf_ty.sty {
             debug!("Found use of ty param num {}", idx);
-            tps_used[idx as usize - lifetime_count] = true;
+            tps_used[idx as usize - param_counts[&ty::Kind::Lifetime]] = true;
         } else if let ty::TyError = leaf_ty.sty {
             // If there already another error, do not emit an error for not using a type Parameter
             assert!(tcx.sess.err_count() > 0);
index ae778966687447efeeed37cb0465598ce55ab90b..fa1ac49232ac02a9dee06ddeee28bdee0a351821 100644 (file)
@@ -11,6 +11,8 @@
 use check::{Inherited, FnCtxt};
 use constrained_type_params::{identify_constrained_type_params, Parameter};
 
+use ty::GenericParamDef;
+
 use hir::def_id::DefId;
 use rustc::traits::{self, ObligationCauseCode};
 use rustc::ty::{self, Lift, Ty, TyCtxt};
@@ -187,7 +189,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,
@@ -638,23 +640,37 @@ 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()
-                                             .map(|tp| (tp.name, tp.def_id))
-                                             .collect();
-
-    for method_param in generics.types() {
-        if impl_params.contains_key(&method_param.name) {
+    let impl_params: FxHashMap<_, _> =
+        parent.params.iter()
+                     .flat_map(|param| {
+                         match param {
+                             GenericParamDef::Lifetime(_) => None,
+                             GenericParamDef::Type(ty) => Some((ty.name, ty.def_id)),
+                         }
+                     })
+                     .collect();
+
+    for method_param in generics.params.iter() {
+        // Shadowing is currently permitted with lifetimes.
+        if let GenericParamDef::Lifetime(_) = method_param {
+            continue;
+        }
+        let (name, def_id) = match method_param {
+            GenericParamDef::Lifetime(_) => continue,
+            GenericParamDef::Type(ty) => (ty.name, ty.def_id),
+        };
+        if impl_params.contains_key(&name) {
             // Tighten up the span to focus on only the shadowing type
-            let type_span = tcx.def_span(method_param.def_id);
+            let type_span = tcx.def_span(def_id);
 
             // The expectation here is that the original trait declaration is
             // local so it should be okay to just unwrap everything.
-            let trait_def_id = impl_params[&method_param.name];
+            let trait_def_id = impl_params[&name];
             let trait_decl_span = tcx.def_span(trait_def_id);
-            error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]);
+            error_194(tcx, type_span, trait_decl_span, &name[..]);
         }
     }
 }
index 11bcbc1fe7e30951f2a4fa3ac973b1c9fed621b3..b1981c0650441b3691fca5c396fde43581e90f70 100644 (file)
@@ -224,33 +224,33 @@ fn get_auto_trait_impl_for(
     }
 
     fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters {
-        let lifetimes = HirVec::from_vec(
-            generics.lifetimes()
-                    .map(|p| {
-                        let name = if p.name == "" {
-                            hir::LifetimeName::Static
-                        } else {
-                            hir::LifetimeName::Name(p.name.as_symbol())
-                        };
+        let mut lifetimes = vec![];
+        let mut types = vec![];
+
+        for param in generics.params.iter() {
+            match param {
+                ty::GenericParamDef::Lifetime(lt) => {
+                    let name = if lt.name == "" {
+                        hir::LifetimeName::Static
+                    } else {
+                        hir::LifetimeName::Name(lt.name.as_symbol())
+                    };
 
-                        hir::Lifetime {
-                            id: ast::DUMMY_NODE_ID,
-                            span: DUMMY_SP,
-                            name,
-                        }
-                    })
-                    .collect(),
-        );
-        let types = HirVec::from_vec(
-            generics.types()
-                    .into_iter()
-                    .map(|p| P(self.ty_param_to_ty(p.clone())))
-                    .collect(),
-        );
+                    lifetimes.push(hir::Lifetime {
+                        id: ast::DUMMY_NODE_ID,
+                        span: DUMMY_SP,
+                        name,
+                    });
+                }
+                ty::GenericParamDef::Type(ty) => {
+                    types.push(P(self.ty_param_to_ty(ty.clone())));
+                }
+            }
+        }
 
         hir::PathParameters {
-            lifetimes: lifetimes,
-            types: types,
+            lifetimes: HirVec::from_vec(lifetimes),
+            types: HirVec::from_vec(types),
             bindings: HirVec::new(),
             parenthesized: false,
         }
index 31f227373cb93575eea518998706af25ec810e1d..d1db5185f194a9996ef2cde86a0edaebbadfda61 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, Kind};
 use rustc::middle::stability;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_typeck::hir_ty_to_ty;
@@ -2675,20 +2675,31 @@ 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 = FxHashMap();
+                        for param in generics.params.iter() {
+                            match param {
+                                GenericParamDef::Type(ty_param) => {
+                                    let i = indices.entry(Kind::Type).or_insert(0);
+                                    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));
+                                    }
+                                    *i += 1;
+                                }
+                                GenericParamDef::Lifetime(lt_param) => {
+                                    let i = indices.entry(Kind::Type).or_insert(0);
+                                    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));
+                                        }
+                                    }
+                                    *i += 1;
                                 }
                             }
                         }