about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2018-02-08 08:58:13 +0000
committervarkor <github@varkor.com>2018-06-20 12:19:03 +0100
commit494859e8dde5080534e94aba6d98affb921552f8 (patch)
tree661fcf1caa265de43643abf07b854460d966b862
parentcca43a7f977963ee497ca091fbdf3cea95abdf47 (diff)
downloadrust-494859e8dde5080534e94aba6d98affb921552f8.tar.gz
rust-494859e8dde5080534e94aba6d98affb921552f8.zip
Consolidate PathParameters and AngleBracketedParameterData
-rw-r--r--src/librustc/hir/intravisit.rs4
-rw-r--r--src/librustc/hir/lowering.rs59
-rw-r--r--src/librustc/hir/mod.rs40
-rw-r--r--src/librustc/hir/print.rs44
-rw-r--r--src/librustc/ich/impls_hir.rs8
-rw-r--r--src/librustc/middle/resolve_lifetime.rs18
-rw-r--r--src/librustc/ty/mod.rs95
-rw-r--r--src/librustc_driver/pretty.rs2
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs4
-rw-r--r--src/librustc_typeck/astconv.rs42
-rw-r--r--src/librustc_typeck/check/method/confirm.rs5
-rw-r--r--src/librustc_typeck/check/mod.rs14
-rw-r--r--src/librustc_typeck/collect.rs7
-rw-r--r--src/libsyntax/ast.rs34
-rw-r--r--src/libsyntax/ext/build.rs33
-rw-r--r--src/libsyntax/fold.rs22
-rw-r--r--src/libsyntax/parse/parser.rs20
-rw-r--r--src/libsyntax/print/pprust.rs29
-rw-r--r--src/libsyntax/visit.rs4
-rw-r--r--src/libsyntax_ext/deriving/clone.rs3
-rw-r--r--src/libsyntax_ext/deriving/cmp/eq.rs4
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs17
-rw-r--r--src/libsyntax_ext/deriving/generic/ty.rs26
-rw-r--r--src/libsyntax_ext/env.rs5
24 files changed, 364 insertions, 175 deletions
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 12ccb329e06..79b433e3cb2 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -650,8 +650,8 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
                                                 _path_span: Span,
                                                 path_parameters: &'v PathParameters) {
-    walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes);
-    walk_list!(visitor, visit_ty, &path_parameters.types);
+    walk_list!(visitor, visit_lifetime, path_parameters.lifetimes());
+    walk_list!(visitor, visit_ty, path_parameters.types());
     walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
 }
 
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index dd12edb7302..8e66ce3fd18 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -46,6 +46,7 @@ use hir::HirVec;
 use hir::map::{DefKey, DefPathData, Definitions};
 use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX};
 use hir::def::{Def, PathResolution, PerNS};
+use hir::GenericPathParam;
 use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES};
 use middle::cstore::CrateStore;
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -1037,6 +1038,20 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
+    fn lower_param(&mut self,
+                   p: &GenericAngleBracketedParam,
+                   itctx: ImplTraitContext)
+                   -> GenericPathParam {
+        match p {
+            GenericAngleBracketedParam::Lifetime(lt) => {
+                GenericPathParam::Lifetime(self.lower_lifetime(&lt))
+            }
+            GenericAngleBracketedParam::Type(ty) => {
+                GenericPathParam::Type(self.lower_ty(&ty, itctx))
+            }
+        }
+    }
+
     fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
         let kind = match t.node {
             TyKind::Infer => hir::TyInfer,
@@ -1552,7 +1567,7 @@ impl<'a> LoweringContext<'a> {
                         assert!(!def_id.is_local());
                         let item_generics =
                             self.cstore.item_generics_cloned_untracked(def_id, self.sess);
-                        let n = item_generics.own_counts().lifetimes;
+                        let n = item_generics.own_counts().lifetimes();
                         self.type_def_lifetime_params.insert(def_id, n);
                         n
                     });
@@ -1671,7 +1686,7 @@ impl<'a> LoweringContext<'a> {
     ) -> hir::PathSegment {
         let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
             let msg = "parenthesized parameters may only be used with a trait";
-            match **parameters {
+            match **path_params {
                 PathParameters::AngleBracketed(ref data) => {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
                 }
@@ -1699,12 +1714,14 @@ impl<'a> LoweringContext<'a> {
         };
 
         if !parameters.parenthesized && parameters.lifetimes.is_empty() {
-            parameters.lifetimes = self.elided_path_lifetimes(path_span, expected_lifetimes);
+            path_params.parameters = (0..expected_lifetimes).map(|_| {
+                GenericPathParam::Lifetime(self.elided_lifetime(path_span))
+            }).chain(path_params.parameters.into_iter()).collect();
         }
 
         hir::PathSegment::new(
             self.lower_ident(segment.ident),
-            parameters,
+            path_params,
             infer_types,
         )
     }
@@ -1715,24 +1732,13 @@ impl<'a> LoweringContext<'a> {
         param_mode: ParamMode,
         itctx: ImplTraitContext,
     ) -> (hir::PathParameters, bool) {
-        let &AngleBracketedParameterData {
-            ref lifetimes,
-            ref types,
-            ref bindings,
-            ..
-        } = data;
-        (
-            hir::PathParameters {
-                lifetimes: self.lower_lifetimes(lifetimes),
-                types: types.iter().map(|ty| self.lower_ty(ty, itctx)).collect(),
-                bindings: bindings
-                    .iter()
-                    .map(|b| self.lower_ty_binding(b, itctx))
-                    .collect(),
-                parenthesized: false,
-            },
-            types.is_empty() && param_mode == ParamMode::Optional,
-        )
+        let &AngleBracketedParameterData { ref parameters, ref bindings, .. } = data;
+        (hir::PathParameters {
+            parameters: parameters.iter().map(|p| self.lower_param(p, itctx)).collect(),
+            bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(),
+            parenthesized: false,
+        },
+        types.is_empty() && param_mode == ParamMode::Optional)
     }
 
     fn lower_parenthesized_parameter_data(
@@ -1769,8 +1775,7 @@ impl<'a> LoweringContext<'a> {
 
                 (
                     hir::PathParameters {
-                        lifetimes: hir::HirVec::new(),
-                        types: hir_vec![mk_tup(this, inputs, span)],
+                        parameters: hir_vec![GenericPathParam::Type(mk_tup(this, inputs, span))],
                         bindings: hir_vec![
                             hir::TypeBinding {
                                 id: this.next_id().node_id,
@@ -1971,7 +1976,7 @@ impl<'a> LoweringContext<'a> {
 
         let def = hir::LifetimeDef {
             lifetime: self.lower_lifetime(&l.lifetime),
-            bounds: self.lower_lifetimes(&l.bounds),
+            bounds: l.bounds.iter().map(|l| self.lower_lifetime(l)).collect(),
             pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"),
             in_band: false,
         };
@@ -1981,10 +1986,6 @@ impl<'a> LoweringContext<'a> {
         def
     }
 
-    fn lower_lifetimes(&mut self, lts: &Vec<Lifetime>) -> hir::HirVec<hir::Lifetime> {
-        lts.iter().map(|l| self.lower_lifetime(l)).collect()
-    }
-
     fn lower_generic_params(
         &mut self,
         params: &Vec<GenericParam>,
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 833090c3ee0..e69b824e779 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -373,11 +373,15 @@ impl PathSegment {
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum GenericPathParam {
+    Lifetime(Lifetime),
+    Type(P<Ty>),
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct PathParameters {
-    /// The lifetime parameters for this path segment.
-    pub lifetimes: HirVec<Lifetime>,
-    /// The type parameters for this path segment, if present.
-    pub types: HirVec<P<Ty>>,
+    /// The generic parameters for this path segment.
+    pub parameters: HirVec<GenericPathParam>,
     /// Bindings (equality constraints) on associated types, if present.
     /// E.g., `Foo<A=Bar>`.
     pub bindings: HirVec<TypeBinding>,
@@ -390,21 +394,19 @@ pub struct PathParameters {
 impl PathParameters {
     pub fn none() -> Self {
         Self {
-            lifetimes: HirVec::new(),
-            types: HirVec::new(),
+            parameters: HirVec::new(),
             bindings: HirVec::new(),
             parenthesized: false,
         }
     }
 
     pub fn is_empty(&self) -> bool {
-        self.lifetimes.is_empty() && self.types.is_empty() &&
-            self.bindings.is_empty() && !self.parenthesized
+        self.parameters.is_empty() && self.bindings.is_empty() && !self.parenthesized
     }
 
     pub fn inputs(&self) -> &[P<Ty>] {
         if self.parenthesized {
-            if let Some(ref ty) = self.types.get(0) {
+            if let Some(ref ty) = self.types().get(0) {
                 if let TyTup(ref tys) = ty.node {
                     return tys;
                 }
@@ -412,6 +414,26 @@ impl PathParameters {
         }
         bug!("PathParameters::inputs: not a `Fn(T) -> U`");
     }
+
+    pub fn lifetimes(&self) -> Vec<&Lifetime> {
+        self.parameters.iter().filter_map(|p| {
+            if let GenericPathParam::Lifetime(lt) = p {
+                Some(lt)
+            } else {
+                None
+            }
+        }).collect()
+    }
+
+    pub fn types(&self) -> Vec<&P<Ty>> {
+        self.parameters.iter().filter_map(|p| {
+            if let GenericPathParam::Type(ty) = p {
+                Some(ty)
+            } else {
+                None
+            }
+        }).collect()
+    }
 }
 
 /// The AST represents all type param bounds as types.
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 1beef3f715e..9e3c103b978 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -25,6 +25,7 @@ use syntax_pos::{self, BytePos, FileName};
 
 use hir;
 use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd};
+use hir::GenericPathParam;
 
 use std::cell::Cell;
 use std::io::{self, Write, Read};
@@ -1269,8 +1270,7 @@ impl<'a> State<'a> {
         self.print_name(segment.name)?;
 
         segment.with_parameters(|parameters| {
-            if !parameters.lifetimes.is_empty() ||
-                !parameters.types.is_empty() ||
+            if !parameters.parameters.is_empty() ||
                 !parameters.bindings.is_empty()
             {
                 self.print_path_parameters(&parameters, segment.infer_types, true)
@@ -1707,18 +1707,18 @@ impl<'a> State<'a> {
     }
 
     fn print_path_parameters(&mut self,
-                             parameters: &hir::PathParameters,
+                             path_params: &hir::PathParameters,
                              infer_types: bool,
                              colons_before_params: bool)
                              -> io::Result<()> {
-        if parameters.parenthesized {
+        if path_params.parenthesized {
             self.s.word("(")?;
-            self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
+            self.commasep(Inconsistent, path_params.inputs(), |s, ty| s.print_type(&ty))?;
             self.s.word(")")?;
 
             self.space_if_not_bol()?;
             self.word_space("->")?;
-            self.print_type(&parameters.bindings[0].ty)?;
+            self.print_type(&path_params.bindings[0].ty)?;
         } else {
             let start = if colons_before_params { "::<" } else { "<" };
             let empty = Cell::new(true);
@@ -1731,17 +1731,27 @@ impl<'a> State<'a> {
                 }
             };
 
-            if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
-                for lifetime in &parameters.lifetimes {
-                    start_or_comma(self)?;
-                    self.print_lifetime(lifetime)?;
+            let elide_lifetimes = path_params.parameters.iter().all(|p| {
+                if let GenericPathParam::Lifetime(lt) = p {
+                    if !lt.is_elided() {
+                        return false;
+                    }
                 }
-            }
-
-            if !parameters.types.is_empty() {
-                start_or_comma(self)?;
-                self.commasep(Inconsistent, &parameters.types, |s, ty| s.print_type(&ty))?;
-            }
+                true
+            });
+
+            self.commasep(Inconsistent, &path_params.parameters, |s, p| {
+                match p {
+                    GenericPathParam::Lifetime(lt) => {
+                        if !elide_lifetimes {
+                            s.print_lifetime(lt)
+                        } else {
+                            Ok(())
+                        }
+                    }
+                    GenericPathParam::Type(ty) => s.print_type(ty),
+                }
+            })?;
 
             // FIXME(eddyb) This would leak into error messages, e.g.:
             // "non-exhaustive patterns: `Some::<..>(_)` not covered".
@@ -1750,7 +1760,7 @@ impl<'a> State<'a> {
                 self.s.word("..")?;
             }
 
-            for binding in parameters.bindings.iter() {
+            for binding in path_params.bindings.iter() {
                 start_or_comma(self)?;
                 self.print_name(binding.name)?;
                 self.s.space()?;
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index ed259b28545..54e6989d55a 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -180,9 +180,13 @@ impl_stable_hash_for!(struct hir::PathSegment {
     parameters
 });
 
+impl_stable_hash_for!(enum hir::GenericPathParam {
+    Lifetime(lt),
+    Type(ty)
+});
+
 impl_stable_hash_for!(struct hir::PathParameters {
-    lifetimes,
-    types,
+    parameters,
     bindings,
     parenthesized
 });
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index f251a3d5f38..477c4c213ce 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -155,7 +155,7 @@ impl Region {
         }
     }
 
-    fn subst(self, params: &[hir::Lifetime], map: &NamedRegionMap) -> Option<Region> {
+    fn subst(self, params: Vec<&hir::Lifetime>, map: &NamedRegionMap) -> Option<Region> {
         if let Region::EarlyBound(index, _, _) = self {
             params
                 .get(index as usize)
@@ -820,7 +820,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         if lifetime_ref.is_elided() {
-            self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false);
+            self.resolve_elided_lifetimes(vec![lifetime_ref], false);
             return;
         }
         if lifetime_ref.is_static() {
@@ -1613,10 +1613,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             return;
         }
 
-        if params.lifetimes.iter().all(|l| l.is_elided()) {
-            self.resolve_elided_lifetimes(&params.lifetimes, true);
+        if params.lifetimes().iter().all(|l| l.is_elided()) {
+            self.resolve_elided_lifetimes(params.lifetimes(), true);
         } else {
-            for l in &params.lifetimes {
+            for l in &params.lifetimes() {
                 self.visit_lifetime(l);
             }
         }
@@ -1688,13 +1688,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     } else {
                         Some(Region::Static)
                     },
-                    Set1::One(r) => r.subst(&params.lifetimes, map),
+                    Set1::One(r) => r.subst(params.lifetimes(), map),
                     Set1::Many => None,
                 })
                 .collect()
         });
 
-        for (i, ty) in params.types.iter().enumerate() {
+        for (i, ty) in params.types().iter().enumerate() {
             if let Some(&lt) = object_lifetime_defaults.get(i) {
                 let scope = Scope::ObjectLifetimeDefault {
                     lifetime: lt,
@@ -1981,7 +1981,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         }
     }
 
-    fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) {
+    fn resolve_elided_lifetimes(&mut self,
+                                lifetime_refs: Vec<&'tcx hir::Lifetime>,
+                                deprecated: bool) {
         if lifetime_refs.is_empty() {
             return;
         }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 4f5f0c9d740..d09be8e5c45 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -885,6 +885,73 @@ pub struct GenericParamCount {
     pub types: usize,
 }
 
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub enum GenericParameterDef {
+    Lifetime(RegionParameterDef),
+    Type(TypeParameterDef),
+}
+
+impl GenericParameterDef {
+    pub fn index(&self) -> u32 {
+        match self {
+            GenericParameterDef::Lifetime(lt) => lt.index,
+            GenericParameterDef::Type(ty)     => ty.index,
+        }
+    }
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub enum KindIndex {
+    Lifetime,
+    Type,
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct KindIndexed<L, T> {
+    pub lt: L,
+    pub ty: T,
+}
+
+impl<T> KindIndexed<T, T> {
+    pub fn get(&self, idx: KindIndex) -> &T {
+        match idx {
+            KindIndex::Lifetime => &self.lt,
+            KindIndex::Type     => &self.ty,
+        }
+    }
+
+    pub fn iter(&self) -> KindIndexIterator<T> {
+        KindIndexIterator {
+            index: self,
+            next: Some(KindIndex::Lifetime),
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct KindIndexIterator<'a, T: 'a> {
+    pub index: &'a KindIndexed<T, T>,
+    pub next: Option<KindIndex>,
+}
+
+impl<'a, T> Iterator for KindIndexIterator<'a, T> {
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.next {
+            Some(KindIndex::Lifetime) => {
+                self.next = Some(KindIndex::Type);
+                Some(&self.index.lt)
+            }
+            Some(KindIndex::Type) => {
+                self.next = None;
+                Some(&self.index.ty)
+            },
+            None => None,
+        }
+    }
+}
+
 /// Information about the formal type/lifetime parameters associated
 /// with an item or method. Analogous to hir::Generics.
 ///
@@ -942,6 +1009,34 @@ impl<'a, 'gcx, 'tcx> Generics {
         }
     }
 
+    pub fn lifetimes(&self) -> Vec<&RegionParameterDef> {
+        self.parameters.iter().filter_map(|p| {
+            if let GenericParameterDef::Lifetime(lt) = p {
+                Some(lt)
+            } else {
+                None
+            }
+        }).collect()
+    }
+
+    pub fn types(&self) -> Vec<&TypeParameterDef> {
+        self.parameters.iter().filter_map(|p| {
+            if let GenericParameterDef::Type(ty) = p {
+                Some(ty)
+            } else {
+                None
+            }
+        }).collect()
+    }
+
+    pub fn parent_lifetimes(&self) -> u32 {
+        *self.parent_parameters.get(KindIndex::Lifetime)
+    }
+
+    pub fn parent_types(&self) -> u32 {
+        *self.parent_parameters.get(KindIndex::Type)
+    }
+
     pub fn region_param(&'tcx self,
                         param: &EarlyBoundRegion,
                         tcx: TyCtxt<'a, 'gcx, 'tcx>)
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index f1ad14237ee..71ecc893806 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -680,7 +680,7 @@ impl<'a> ReplaceBodyWithLoop<'a> {
                         match seg.parameters.as_ref().map(|p| &**p) {
                             None => false,
                             Some(&ast::PathParameters::AngleBracketed(ref data)) =>
-                                any_involves_impl_trait(data.types.iter()) ||
+                                any_involves_impl_trait(data.types().into_iter()) ||
                                 any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)),
                             Some(&ast::PathParameters::Parenthesized(ref data)) =>
                                 any_involves_impl_trait(data.inputs.iter()) ||
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 279ee403cc6..81a3617f0aa 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -822,7 +822,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         for seg in &path.segments {
             if let Some(ref params) = seg.parameters {
                 match **params {
-                    ast::PathParameters::AngleBracketed(ref data) => for t in &data.types {
+                    ast::PathParameters::AngleBracketed(ref data) => for t in data.types() {
                         self.visit_ty(t);
                     },
                     ast::PathParameters::Parenthesized(ref data) => {
@@ -907,7 +907,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         // Explicit types in the turbo-fish.
         if let Some(ref params) = seg.parameters {
             if let ast::PathParameters::AngleBracketed(ref data) = **params {
-                for t in &data.types {
+                for t in data.types() {
                     self.visit_ty(t);
                 }
             }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 18911b47ed1..005d088c478 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -214,8 +214,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
         let decl_generics = tcx.generics_of(def_id);
-        let ty_provided = parameters.types.len();
-        let lt_provided = parameters.lifetimes.len();
+        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 };
@@ -269,7 +269,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             match param.kind {
                 GenericParamDefKind::Lifetime => {
                     let i = param.index as usize - own_self;
-                    if let Some(lifetime) = parameters.lifetimes.get(i) {
+                    if let Some(lifetime) = parameters.lifetimes().get(i) {
                         self.ast_region_to_region(lifetime, Some(param)).into()
                     } else {
                         tcx.types.re_static.into()
@@ -286,7 +286,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     let i = i - (lt_accepted + own_self);
                     if i < ty_provided {
                         // A provided type parameter.
-                        self.ast_ty_to_ty(&parameters.types[i]).into()
+                        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) {
@@ -970,23 +970,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
     pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
         for segment in segments {
-            segment.with_parameters(|parameters| {
-                for typ in &parameters.types {
-                    struct_span_err!(self.tcx().sess, typ.span, E0109,
-                                     "type parameters are not allowed on this type")
-                        .span_label(typ.span, "type parameter not allowed")
-                        .emit();
-                    break;
-                }
-                for lifetime in &parameters.lifetimes {
-                    struct_span_err!(self.tcx().sess, lifetime.span, E0110,
-                                     "lifetime parameters are not allowed on this type")
-                        .span_label(lifetime.span,
-                                    "lifetime parameter not allowed on this type")
-                        .emit();
+            segment.with_parameters(|params| {
+                for p in &params.parameters {
+                    let (mut span_err, span, kind) = match p {
+                        hir::GenericPathParam::Lifetime(lt) => {
+                            (struct_span_err!(self.tcx().sess, lt.span, E0110,
+                                              "lifetime parameters are not allowed on this type"),
+                             lt.span,
+                             "lifetime")
+                        }
+                        hir::GenericPathParam::Type(ty) => {
+                            (struct_span_err!(self.tcx().sess, ty.span, E0109,
+                                              "type parameters are not allowed on this type"),
+                             ty.span,
+                             "type")
+                        }
+                    };
+                    span_err.span_label(span, format!("{} parameter not allowed", kind))
+                            .emit();
                     break;
                 }
-                for binding in &parameters.bindings {
+                for binding in &params.bindings {
                     self.prohibit_projection(binding.span);
                     break;
                 }
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index f3a3c30fe5a..33102757925 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                 match param.kind {
                     GenericParamDefKind::Lifetime => {
                         if let Some(lifetime) = provided.as_ref().and_then(|p| {
-                            p.lifetimes.get(i - parent_substs.len())
+                            p.lifetimes().get(i - parent_substs.len())
                         }) {
                             return AstConv::ast_region_to_region(
                                 self.fcx, lifetime, Some(param)).into();
@@ -339,7 +339,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                     }
                     GenericParamDefKind::Type {..} => {
                         if let Some(ast_ty) = provided.as_ref().and_then(|p| {
-                            p.types.get(i - parent_substs.len() - own_counts.lifetimes)
+                            p.types().get(i - parent_substs.len() - own_counts.lifetimes)
                         }) {
                             return self.to_ty(ast_ty).into();
                         }
@@ -347,6 +347,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                 }
                 self.var_for_def(self.span, param)
             }
+            self.type_var_for_def(self.span, def, cur_substs)
         })
     }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index b70b61d1915..0f1b739cddf 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4833,8 +4833,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
             match param.kind {
                 GenericParamDefKind::Lifetime => {
-                    let lifetimes = segment.map_or(&[][..], |(s, _)| {
-                        s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
+                    let lifetimes = segment.map_or(vec![], |(s, _)| {
+                        s.parameters.as_ref().map_or(vec![], |p| p.lifetimes())
                     });
 
                     if let Some(lifetime) = lifetimes.get(i) {
@@ -4844,8 +4844,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     }
                 }
                 GenericParamDefKind::Type {..} => {
-                    let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
-                        (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
+                    let (types, infer_types) = segment.map_or((vec![], true), |(s, _)| {
+                        (s.parameters.as_ref().map_or(vec![], |p| |p| p.types()), s.infer_types)
                     });
 
                     // Skip over the lifetimes in the same segment.
@@ -4961,10 +4961,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                   is_method_call: bool,
                                   supress_mismatch_error: bool) {
         let (lifetimes, types, infer_types, bindings) = segment.map_or(
-            (&[][..], &[][..], true, &[][..]),
+            (vec![], vec![], true, &[][..]),
             |(s, _)| s.parameters.as_ref().map_or(
-                (&[][..], &[][..], s.infer_types, &[][..]),
-                |p| (&p.lifetimes[..], &p.types[..],
+                (vec![], vec![], s.infer_types, &[][..]),
+                |p| (p.lifetimes(), p.types(),
                      s.infer_types, &p.bindings[..])));
         let infer_lifetimes = lifetimes.len() == 0;
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 58e804fc13f..6e323e5913a 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -973,6 +973,13 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       .map(|param| (param.def_id, param.index))
                                       .collect();
 
+    let parent_parameters = ty::KindIndexed { lt: parent_regions, ty: parent_types };
+    let lifetimes: Vec<ty::GenericParameterDef> =
+        regions.into_iter().map(|lt| ty::GenericParameterDef::Lifetime(lt)).collect();
+    let types: Vec<ty::GenericParameterDef> =
+        types.into_iter().map(|ty| ty::GenericParameterDef::Type(ty)).collect();
+    let parameters = lifetimes.into_iter().chain(types.into_iter()).collect();
+
     tcx.alloc_generics(ty::Generics {
         parent: parent_def_id,
         parent_count,
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 76fa463a631..1af4743cfe4 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -167,21 +167,47 @@ impl PathParameters {
     }
 }
 
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum GenericAngleBracketedParam {
+    Lifetime(Lifetime),
+    Type(P<Ty>),
+}
+
 /// A path like `Foo<'a, T>`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
 pub struct AngleBracketedParameterData {
     /// Overall span
     pub span: Span,
-    /// The lifetime parameters for this path segment.
-    pub lifetimes: Vec<Lifetime>,
-    /// The type parameters for this path segment, if present.
-    pub types: Vec<P<Ty>>,
+    /// The parameters for this path segment.
+    pub parameters: Vec<GenericAngleBracketedParam>,
     /// Bindings (equality constraints) on associated types, if present.
     ///
     /// E.g., `Foo<A=Bar>`.
     pub bindings: Vec<TypeBinding>,
 }
 
+impl AngleBracketedParameterData {
+    pub fn lifetimes(&self) -> Vec<&Lifetime> {
+        self.parameters.iter().filter_map(|p| {
+            if let GenericAngleBracketedParam::Lifetime(lt) = p {
+                Some(lt)
+            } else {
+                None
+            }
+        }).collect()
+    }
+
+    pub fn types(&self) -> Vec<&P<Ty>> {
+        self.parameters.iter().filter_map(|p| {
+            if let GenericAngleBracketedParam::Type(ty) = p {
+                Some(ty)
+            } else {
+                None
+            }
+        }).collect()
+    }
+}
+
 impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
     fn into(self) -> Option<P<PathParameters>> {
         Some(P(PathParameters::AngleBracketed(self)))
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 4a6f06dcc17..02112517827 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -30,10 +30,9 @@ pub trait AstBuilder {
     fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path;
     fn path_all(&self, sp: Span,
                 global: bool,
-                idents: Vec<ast::Ident> ,
-                lifetimes: Vec<ast::Lifetime>,
-                types: Vec<P<ast::Ty>>,
-                bindings: Vec<ast::TypeBinding> )
+                idents: Vec<ast::Ident>,
+                parameters: Vec<ast::GenericAngleBracketedParam>,
+                bindings: Vec<ast::TypeBinding>)
         -> ast::Path;
 
     fn qpath(&self, self_type: P<ast::Ty>,
@@ -43,8 +42,7 @@ pub trait AstBuilder {
     fn qpath_all(&self, self_type: P<ast::Ty>,
                 trait_path: ast::Path,
                 ident: ast::Ident,
-                lifetimes: Vec<ast::Lifetime>,
-                types: Vec<P<ast::Ty>>,
+                parameters: Vec<ast::GenericAngleBracketedParam>,
                 bindings: Vec<ast::TypeBinding>)
                 -> (ast::QSelf, ast::Path);
 
@@ -304,20 +302,19 @@ pub trait AstBuilder {
 
 impl<'a> AstBuilder for ExtCtxt<'a> {
     fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
-        self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
+        self.path_all(span, false, strs, Vec::new(), Vec::new())
     }
     fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path {
         self.path(span, vec![id])
     }
     fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path {
-        self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
+        self.path_all(span, true, strs, Vec::new(), Vec::new())
     }
     fn path_all(&self,
                 span: Span,
                 global: bool,
                 mut idents: Vec<ast::Ident> ,
-                lifetimes: Vec<ast::Lifetime>,
-                types: Vec<P<ast::Ty>>,
+                parameters: Vec<ast::GenericAngleBracketedParam>,
                 bindings: Vec<ast::TypeBinding> )
                 -> ast::Path {
         let last_ident = idents.pop().unwrap();
@@ -326,8 +323,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         segments.extend(idents.into_iter().map(|ident| {
             ast::PathSegment::from_ident(ident.with_span_pos(span))
         }));
-        let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
-            ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
+        let parameters = if !parameters.is_empty() !bindings.is_empty() {
+            ast::AngleBracketedParameterData { parameters, bindings, span }.into()
         } else {
             None
         };
@@ -349,7 +346,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
              trait_path: ast::Path,
              ident: ast::Ident)
              -> (ast::QSelf, ast::Path) {
-        self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
+        self.qpath_all(self_type, trait_path, ident, vec![], vec![])
     }
 
     /// Constructs a qualified path.
@@ -359,13 +356,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                  self_type: P<ast::Ty>,
                  trait_path: ast::Path,
                  ident: ast::Ident,
-                 lifetimes: Vec<ast::Lifetime>,
-                 types: Vec<P<ast::Ty>>,
+                 parameters: Vec<ast::GenericAngleBracketedParam>,
                  bindings: Vec<ast::TypeBinding>)
                  -> (ast::QSelf, ast::Path) {
         let mut path = trait_path;
-        let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() {
-            ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into()
+        let parameters = if !parameters.is_empty() || !bindings.is_empty() {
+            ast::AngleBracketedParameterData { parameters, bindings, span: ident.span }.into()
         } else {
             None
         };
@@ -428,8 +424,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             self.path_all(DUMMY_SP,
                           true,
                           self.std_path(&["option", "Option"]),
-                          Vec::new(),
-                          vec![ ty ],
+                          vec![ ast::GenericAngleBracketedParam::Type(ty) ],
                           Vec::new()))
     }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8544ef330dc..b935425cdd4 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -132,6 +132,10 @@ pub trait Folder : Sized {
         noop_fold_exprs(es, self)
     }
 
+    fn fold_param(&mut self, p: GenericAngleBracketedParam) -> GenericAngleBracketedParam {
+        noop_fold_param(p, self)
+    }
+
     fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
         noop_fold_ty(t, self)
     }
@@ -353,6 +357,19 @@ pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBindi
     }
 }
 
+pub fn noop_fold_param<T: Folder>(p: GenericAngleBracketedParam,
+                                  fld: &mut T)
+                                  -> GenericAngleBracketedParam {
+    match p {
+        GenericAngleBracketedParam::Lifetime(lt) => {
+            GenericAngleBracketedParam::Lifetime(noop_fold_lifetime(lt, fld))
+        }
+        GenericAngleBracketedParam::Type(ty) => {
+            GenericAngleBracketedParam::Type(noop_fold_ty(ty, fld))
+        }
+    }
+}
+
 pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
     t.map(|Ty {id, node, span}| Ty {
         id: fld.new_id(id),
@@ -469,9 +486,8 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedP
                                                            fld: &mut T)
                                                            -> AngleBracketedParameterData
 {
-    let AngleBracketedParameterData { lifetimes, types, bindings, span } = data;
-    AngleBracketedParameterData { lifetimes: lifetimes.move_map(|l| noop_fold_lifetime(l, fld)),
-                                  types: types.move_map(|ty| fld.fold_ty(ty)),
+    let AngleBracketedParameterData { parameters, bindings, span } = data;
+    AngleBracketedParameterData { parameters: parameters.move_map(|p| fld.fold_param(p)),
                                   bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
                                   span: fld.new_span(span) }
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 1735951da2f..c205e937611 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -22,6 +22,7 @@ use ast::{Expr, ExprKind, RangeLimits};
 use ast::{Field, FnDecl};
 use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
 use ast::GenericParam;
+use ast::GenericAngleBracketedParam;
 use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
 use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind};
 use ast::Local;
@@ -1971,10 +1972,10 @@ impl<'a> Parser<'a> {
 
             let parameters = if self.eat_lt() {
                 // `<'a, T, A = U>`
-                let (lifetimes, types, bindings) = self.parse_generic_args()?;
+                let (parameters, bindings) = self.parse_generic_args()?;
                 self.expect_gt()?;
                 let span = lo.to(self.prev_span);
-                AngleBracketedParameterData { lifetimes, types, bindings, span }.into()
+                AngleBracketedParameterData { parameters, bindings, span }.into()
             } else {
                 // `(T, U) -> R`
                 self.bump(); // `(`
@@ -4936,16 +4937,16 @@ impl<'a> Parser<'a> {
 
     /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
     /// possibly including trailing comma.
-    fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<TypeBinding>)> {
-        let mut lifetimes = Vec::new();
-        let mut types = Vec::new();
+    fn parse_generic_args(&mut self)
+                          -> PResult<'a, (Vec<GenericAngleBracketedParam>, Vec<TypeBinding>)> {
+        let mut parameters = Vec::new();
         let mut bindings = Vec::new();
         let mut seen_type = false;
         let mut seen_binding = false;
         loop {
             if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
                 // Parse lifetime argument.
-                lifetimes.push(self.expect_lifetime());
+                parameters.push(GenericAngleBracketedParam::Lifetime(self.expect_lifetime()));
                 if seen_type || seen_binding {
                     self.span_err(self.prev_span,
                         "lifetime parameters must be declared prior to type parameters");
@@ -4965,11 +4966,12 @@ impl<'a> Parser<'a> {
                 seen_binding = true;
             } else if self.check_type() {
                 // Parse type argument.
-                types.push(self.parse_ty()?);
+                let ty_param = self.parse_ty()?;
                 if seen_binding {
-                    self.span_err(types[types.len() - 1].span,
+                    self.span_err(ty_param.span,
                         "type parameters must be declared prior to associated type bindings");
                 }
+                parameters.push(GenericAngleBracketedParam::Type(ty_param));
                 seen_type = true;
             } else {
                 break
@@ -4979,7 +4981,7 @@ impl<'a> Parser<'a> {
                 break
             }
         }
-        Ok((lifetimes, types, bindings))
+        Ok((parameters, bindings))
     }
 
     /// Parses an optional `where` clause and places it in `generics`.
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 87edfd69e2b..dc204e3d0ef 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -13,7 +13,7 @@ pub use self::AnnNode::*;
 use rustc_target::spec::abi::{self, Abi};
 use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
 use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
-use ast::{Attribute, MacDelimiter};
+use ast::{Attribute, MacDelimiter, GenericAngleBracketedParam};
 use util::parser::{self, AssocOp, Fixity};
 use attr;
 use codemap::{self, CodeMap};
@@ -1017,6 +1017,13 @@ impl<'a> State<'a> {
         Ok(())
     }
 
+    pub fn print_param(&mut self, param: &GenericAngleBracketedParam) -> io::Result<()> {
+        match param {
+            GenericAngleBracketedParam::Lifetime(lt) => self.print_lifetime(lt),
+            GenericAngleBracketedParam::Type(ty) => self.print_type(ty),
+        }
+    }
+
     pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
         self.maybe_print_comment(ty.span.lo())?;
         self.ibox(0)?;
@@ -2474,25 +2481,9 @@ impl<'a> State<'a> {
             ast::PathParameters::AngleBracketed(ref data) => {
                 self.s.word("<")?;
 
-                let mut comma = false;
-                for lifetime in &data.lifetimes {
-                    if comma {
-                        self.word_space(",")?
-                    }
-                    self.print_lifetime(lifetime)?;
-                    comma = true;
-                }
+                self.commasep(Inconsistent, &data.parameters, |s, p| s.print_param(p))?;
 
-                if !data.types.is_empty() {
-                    if comma {
-                        self.word_space(",")?
-                    }
-                    self.commasep(
-                        Inconsistent,
-                        &data.types,
-                        |s, ty| s.print_type(ty))?;
-                        comma = true;
-                }
+                let mut comma = data.parameters.len() != 0;
 
                 for binding in data.bindings.iter() {
                     if comma {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index adda39c62ed..a4b9e3d7d45 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -387,8 +387,8 @@ pub fn walk_path_parameters<'a, V>(visitor: &mut V,
 {
     match *path_parameters {
         PathParameters::AngleBracketed(ref data) => {
-            walk_list!(visitor, visit_ty, &data.types);
-            walk_list!(visitor, visit_lifetime, &data.lifetimes);
+            walk_list!(visitor, visit_lifetime, data.lifetimes());
+            walk_list!(visitor, visit_ty, data.types());
             walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
         }
         PathParameters::Parenthesized(ref data) => {
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs
index dec24d13c9b..3a83922bc90 100644
--- a/src/libsyntax_ext/deriving/clone.rs
+++ b/src/libsyntax_ext/deriving/clone.rs
@@ -13,6 +13,7 @@ use deriving::generic::*;
 use deriving::generic::ty::*;
 
 use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData};
+use syntax::ast::GenericAngleBracketedParam;
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
@@ -123,7 +124,7 @@ fn cs_clone_shallow(name: &str,
         let span = span.with_ctxt(cx.backtrace());
         let assert_path = cx.path_all(span, true,
                                         cx.std_path(&["clone", helper_name]),
-                                        vec![], vec![ty], vec![]);
+                                        vec![GenericAngleBracketedParam::Type(ty)], vec![]);
         stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
     }
     fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>, variant: &VariantData) {
diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs
index 237c8654edf..61b7e5b482d 100644
--- a/src/libsyntax_ext/deriving/cmp/eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/eq.rs
@@ -12,7 +12,7 @@ use deriving::path_std;
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{self, Expr, MetaItem};
+use syntax::ast::{self, Expr, MetaItem, GenericAngleBracketedParam};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
@@ -62,7 +62,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
         let span = span.with_ctxt(cx.backtrace());
         let assert_path = cx.path_all(span, true,
                                         cx.std_path(&["cmp", helper_name]),
-                                        vec![], vec![ty], vec![]);
+                                        vec![GenericAngleBracketedParam::Type(ty)], vec![]);
         stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
     }
     fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>, variant: &ast::VariantData) {
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 80f65957c39..7ab0acda408 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -192,10 +192,8 @@ use std::collections::HashSet;
 use std::vec;
 
 use rustc_target::spec::abi::Abi;
-use syntax::ast::{
-    self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData
-};
-
+use syntax::ast::{self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind};
+use syntax::ast::{VariantData, GenericAngleBracketedParam};
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
@@ -667,7 +665,7 @@ impl<'a> TraitDef<'a> {
         let trait_ref = cx.trait_ref(trait_path);
 
         // Create the type parameters on the `self` path.
-        let self_ty_params = generics.params
+        let self_ty_params: Vec<P<ast::Ty>> = generics.params
             .iter()
             .filter_map(|param| match *param {
                 GenericParam::Type(ref ty_param)
@@ -684,12 +682,17 @@ impl<'a> TraitDef<'a> {
             })
             .collect();
 
+        let self_params = self_lifetimes.into_iter()
+                                        .map(|lt| GenericAngleBracketedParam::Lifetime(lt))
+                                        .chain(self_ty_params.into_iter().map(|ty|
+                                            GenericAngleBracketedParam::Type(ty)))
+                                        .collect();
+
         // Create the type of `self`.
         let self_type = cx.ty_path(cx.path_all(self.span,
                                                false,
                                                vec![type_ident],
-                                               self_lifetimes,
-                                               self_ty_params,
+                                               self_params,
                                                Vec::new()));
 
         let attr = cx.attribute(self.span,
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index 25a29694488..6387f2d8d98 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -15,7 +15,7 @@ pub use self::PtrTy::*;
 pub use self::Ty::*;
 
 use syntax::ast;
-use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind};
+use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind, GenericAngleBracketedParam};
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::build::AstBuilder;
 use syntax::codemap::{respan, DUMMY_SP};
@@ -86,15 +86,20 @@ impl<'a> Path<'a> {
                    -> ast::Path {
         let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
         let lt = mk_lifetimes(cx, span, &self.lifetime);
-        let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
+        let tys: Vec<P<ast::Ty>> =
+            self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
+        let params = lt.into_iter()
+                       .map(|lt| GenericAngleBracketedParam::Lifetime(lt))
+                       .chain(tys.into_iter().map(|ty| GenericAngleBracketedParam::Type(ty)))
+                       .collect();
 
         match self.kind {
-            PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()),
-            PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()),
+            PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()),
+            PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()),
             PathKind::Std => {
                 let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark);
                 idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site));
-                cx.path_all(span, false, idents, lt, tys, Vec::new())
+                cx.path_all(span, false, idents, params, Vec::new())
             }
         }
 
@@ -184,7 +189,7 @@ impl<'a> Ty<'a> {
                    -> ast::Path {
         match *self {
             Self_ => {
-                let self_params = self_generics.params
+                let ty_params: Vec<P<ast::Ty>> = self_generics.params
                     .iter()
                     .filter_map(|param| match *param {
                         GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)),
@@ -200,11 +205,16 @@ impl<'a> Ty<'a> {
                     })
                     .collect();
 
+                let params = lifetimes.into_iter()
+                                      .map(|lt| GenericAngleBracketedParam::Lifetime(lt))
+                                      .chain(ty_params.into_iter().map(|ty|
+                                            GenericAngleBracketedParam::Type(ty)))
+                                      .collect();
+
                 cx.path_all(span,
                             false,
                             vec![self_ty],
-                            lifetimes,
-                            self_params,
+                            params,
                             Vec::new())
             }
             Literal(ref p) => p.to_path(cx, span, self_ty, self_generics),
diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs
index 4e1af108ab4..c904cfcfdbf 100644
--- a/src/libsyntax_ext/env.rs
+++ b/src/libsyntax_ext/env.rs
@@ -13,7 +13,7 @@
 // interface.
 //
 
-use syntax::ast::{self, Ident};
+use syntax::ast::{self, Ident, GenericAngleBracketedParam};
 use syntax::ext::base::*;
 use syntax::ext::base;
 use syntax::ext::build::AstBuilder;
@@ -39,8 +39,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
             cx.expr_path(cx.path_all(sp,
                                      true,
                                      cx.std_path(&["option", "Option", "None"]),
-                                     Vec::new(),
-                                     vec![cx.ty_rptr(sp,
+                                     vec![GenericAngleBracketedParam::Type(cx.ty_rptr(sp,
                                                      cx.ty_ident(sp, Ident::from_str("str")),
                                                      Some(lt),
                                                      ast::Mutability::Immutable)],