about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2018-05-26 19:16:21 +0100
committervarkor <github@varkor.com>2018-06-20 12:21:08 +0100
commit2c6ff2469a94e37b9605a43bc861de66830a94d4 (patch)
tree36c1ad6aed0cceb2980e97878c48436fe2d9d757
parentfba1fe21084bf248334ad46b0b0a8c40a6d5ee7b (diff)
Refactor ast::GenericParam as a struct
-rw-r--r--src/librustc/hir/lowering.rs103
-rw-r--r--src/librustc/hir/map/def_collector.rs29
-rw-r--r--src/librustc_passes/ast_validation.rs88
-rw-r--r--src/librustc_resolve/lib.rs73
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs76
-rw-r--r--src/librustc_save_analysis/lib.rs6
-rw-r--r--src/librustc_save_analysis/sig.rs53
-rw-r--r--src/libsyntax/ast.rs47
-rw-r--r--src/libsyntax/ext/build.rs27
-rw-r--r--src/libsyntax/fold.rs27
-rw-r--r--src/libsyntax/parse/parser.rs50
-rw-r--r--src/libsyntax/print/pprust.rs36
-rw-r--r--src/libsyntax/visit.rs18
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs28
-rw-r--r--src/libsyntax_ext/deriving/generic/ty.rs23
-rw-r--r--src/libsyntax_ext/deriving/mod.rs9
16 files changed, 338 insertions, 355 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index ae7d8bd8403..68ceb39d575 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -759,20 +759,20 @@ impl<'a> LoweringContext<'a> {
         hir_name
     }
 
-    // Evaluates `f` with the lifetimes in `lt_defs` in-scope.
+    // Evaluates `f` with the lifetimes in `params` in-scope.
     // This is used to track which lifetimes have already been defined, and
     // which are new in-band lifetimes that need to have a definition created
     // for them.
     fn with_in_scope_lifetime_defs<'l, T, F>(
         &mut self,
-        lt_defs: impl Iterator<Item = &'l LifetimeDef>,
+        params: impl Iterator<Item = &'l GenericParamAST>,
         f: F,
     ) -> T
     where
         F: FnOnce(&mut LoweringContext) -> T,
     {
         let old_len = self.in_scope_lifetimes.len();
-        let lt_def_names = lt_defs.map(|lt_def| lt_def.lifetime.ident.name);
+        let lt_def_names = params.map(|param| param.ident.name);
         self.in_scope_lifetimes.extend(lt_def_names);
 
         let res = f(self);
@@ -781,8 +781,8 @@ impl<'a> LoweringContext<'a> {
         res
     }
 
-    // Same as the method above, but accepts `hir::LifetimeDef`s
-    // instead of `ast::LifetimeDef`s.
+    // Same as the method above, but accepts `hir::GenericParam`s
+    // instead of `ast::GenericParam`s.
     // This should only be used with generics that have already had their
     // in-band lifetimes added. In practice, this means that this function is
     // only used when lowering a child item of a trait or impl.
@@ -817,8 +817,8 @@ impl<'a> LoweringContext<'a> {
         F: FnOnce(&mut LoweringContext) -> T,
     {
         let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(
-            generics.params.iter().filter_map(|p| match p {
-                GenericParamAST::Lifetime(ld) => Some(ld),
+            generics.params.iter().filter_map(|param| match param.kind {
+                GenericParamKindAST::Lifetime { .. } => Some(param),
                 _ => None,
             }),
             |this| {
@@ -1076,8 +1076,8 @@ impl<'a> LoweringContext<'a> {
                 hir::TyRptr(lifetime, self.lower_mt(mt, itctx))
             }
             TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(
-                f.generic_params.iter().filter_map(|p| match p {
-                    GenericParamAST::Lifetime(ld) => Some(ld),
+                f.generic_params.iter().filter_map(|param| match param.kind {
+                    GenericParamKindAST::Lifetime { .. } => Some(param),
                     _ => None,
                 }),
                 |this| {
@@ -1940,21 +1940,19 @@ impl<'a> LoweringContext<'a> {
                            add_bounds: &NodeMap<Vec<TyParamBound>>,
                            itctx: ImplTraitContext)
                            -> hir::GenericParam {
-        match param {
-            GenericParamAST::Lifetime(ref lifetime_def) => {
+        match param.kind {
+            GenericParamKindAST::Lifetime { ref bounds, ref lifetime, .. } => {
                 let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
                 self.is_collecting_in_band_lifetimes = false;
 
-                let lifetime = self.lower_lifetime(&lifetime_def.lifetime);
+                let lifetime = self.lower_lifetime(lifetime);
                 let param = hir::GenericParam {
                     id: lifetime.id,
                     span: lifetime.span,
-                    pure_wrt_drop: attr::contains_name(&lifetime_def.attrs, "may_dangle"),
+                    pure_wrt_drop: attr::contains_name(&param.attrs, "may_dangle"),
                     kind: hir::GenericParamKind::Lifetime {
                         name: lifetime.name,
-                        bounds: lifetime_def.bounds
-                                            .iter()
-                                            .map(|lt| self.lower_lifetime(lt)).collect(),
+                        bounds: bounds.iter().map(|lt| self.lower_lifetime(lt)).collect(),
                         in_band: false,
                         lifetime_deprecated: lifetime,
                     }
@@ -1964,8 +1962,8 @@ impl<'a> LoweringContext<'a> {
 
                 param
             }
-            GenericParamAST::Type(ref ty_param) => {
-                let mut name = self.lower_ident(ty_param.ident);
+            GenericParamKindAST::Type { ref bounds, ref default } => {
+                let mut name = self.lower_ident(param.ident);
 
                 // Don't expose `Self` (recovered "keyword used as ident" parse error).
                 // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
@@ -1974,8 +1972,8 @@ impl<'a> LoweringContext<'a> {
                     name = Symbol::gensym("Self");
                 }
 
-                let mut bounds = self.lower_bounds(&ty_param.bounds, itctx);
-                let add_bounds = add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x);
+                let mut bounds = self.lower_bounds(bounds, itctx);
+                let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
                 if !add_bounds.is_empty() {
                     bounds = bounds
                         .into_iter()
@@ -1984,22 +1982,20 @@ impl<'a> LoweringContext<'a> {
                 }
 
                 hir::GenericParam {
-                    id: self.lower_node_id(ty_param.id).node_id,
-                    span: ty_param.ident.span,
-                    pure_wrt_drop: attr::contains_name(&ty_param.attrs, "may_dangle"),
+                    id: self.lower_node_id(param.id).node_id,
+                    span: param.ident.span,
+                    pure_wrt_drop: attr::contains_name(&param.attrs, "may_dangle"),
                     kind: hir::GenericParamKind::Type {
                         name,
                         bounds,
-                        default: ty_param.default.as_ref()
-                                         .map(|x| {
-                                             self.lower_ty(x, ImplTraitContext::Disallowed)
-                                         }),
-                        synthetic: ty_param.attrs
-                                           .iter()
-                                           .filter(|attr| attr.check_name("rustc_synthetic"))
-                                           .map(|_| hir::SyntheticTyParamKind::ImplTrait)
-                                           .nth(0),
-                        attrs: self.lower_attrs(&ty_param.attrs),
+                        default: default.as_ref().map(|x| {
+                            self.lower_ty(x, ImplTraitContext::Disallowed)
+                        }),
+                        synthetic: param.attrs.iter()
+                                              .filter(|attr| attr.check_name("rustc_synthetic"))
+                                              .map(|_| hir::SyntheticTyParamKind::ImplTrait)
+                                              .nth(0),
+                        attrs: self.lower_attrs(&param.attrs),
                     }
                 }
             }
@@ -2015,13 +2011,18 @@ impl<'a> LoweringContext<'a> {
         params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect()
     }
 
-    fn lower_generics(&mut self, g: &Generics, itctx: ImplTraitContext) -> hir::Generics {
+    fn lower_generics(
+        &mut self,
+        generics: &Generics,
+        itctx: ImplTraitContext)
+        -> hir::Generics
+    {
         // Collect `?Trait` bounds in where clause and move them to parameter definitions.
         // FIXME: This could probably be done with less rightward drift. Also looks like two control
         //        paths where report_error is called are also the only paths that advance to after
         //        the match statement, so the error reporting could probably just be moved there.
         let mut add_bounds = NodeMap();
-        for pred in &g.where_clause.predicates {
+        for pred in &generics.where_clause.predicates {
             if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
                 'next_bound: for bound in &bound_pred.bounds {
                     if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound {
@@ -2045,15 +2046,17 @@ impl<'a> LoweringContext<'a> {
                                     if let Some(node_id) =
                                         self.resolver.definitions().as_local_node_id(def_id)
                                     {
-                                        for param in &g.params {
-                                            if let GenericParamAST::Type(ref ty_param) = *param {
-                                                if node_id == ty_param.id {
-                                                    add_bounds
-                                                        .entry(ty_param.id)
-                                                        .or_insert(Vec::new())
-                                                        .push(bound.clone());
-                                                    continue 'next_bound;
+                                        for param in &generics.params {
+                                            match param.kind {
+                                                GenericParamKindAST::Type { .. } => {
+                                                    if node_id == param.id {
+                                                        add_bounds.entry(param.id)
+                                                            .or_insert(Vec::new())
+                                                            .push(bound.clone());
+                                                        continue 'next_bound;
+                                                    }
                                                 }
+                                                _ => {}
                                             }
                                         }
                                     }
@@ -2068,9 +2071,9 @@ impl<'a> LoweringContext<'a> {
         }
 
         hir::Generics {
-            params: self.lower_generic_params(&g.params, &add_bounds, itctx),
-            where_clause: self.lower_where_clause(&g.where_clause),
-            span: g.span,
+            params: self.lower_generic_params(&generics.params, &add_bounds, itctx),
+            where_clause: self.lower_where_clause(&generics.where_clause),
+            span: generics.span,
         }
     }
 
@@ -2093,8 +2096,8 @@ impl<'a> LoweringContext<'a> {
                 span,
             }) => {
                 self.with_in_scope_lifetime_defs(
-                    bound_generic_params.iter().filter_map(|p| match p {
-                        GenericParamAST::Lifetime(ld) => Some(ld),
+                    bound_generic_params.iter().filter_map(|param| match param.kind {
+                        GenericParamKindAST::Lifetime { .. } => Some(param),
                         _ => None,
                     }),
                     |this| {
@@ -2412,8 +2415,8 @@ impl<'a> LoweringContext<'a> {
                 );
 
                 let new_impl_items = self.with_in_scope_lifetime_defs(
-                    ast_generics.params.iter().filter_map(|p| match p {
-                        GenericParamAST::Lifetime(ld) => Some(ld),
+                    ast_generics.params.iter().filter_map(|param| match param.kind {
+                        GenericParamKindAST::Lifetime { .. } => Some(param),
                         _ => None,
                     }),
                     |this| {
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 7ab6e17ac35..6015063aa82 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -171,24 +171,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     }
 
     fn visit_generic_param(&mut self, param: &'a GenericParamAST) {
-        match *param {
-            GenericParamAST::Lifetime(ref lifetime_def) => {
-                self.create_def(
-                    lifetime_def.lifetime.id,
-                    DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()),
-                    REGULAR_SPACE,
-                    lifetime_def.lifetime.ident.span
-                );
-            }
-            GenericParamAST::Type(ref ty_param) => {
-                self.create_def(
-                    ty_param.id,
-                    DefPathData::TypeParam(ty_param.ident.name.as_interned_str()),
-                    REGULAR_SPACE,
-                    ty_param.ident.span
-                );
-            }
-        }
+        let name = param.ident.name.as_interned_str();
+        let def_path_data = match param.kind {
+            GenericParamKindAST::Lifetime { .. } => DefPathData::LifetimeDef(name),
+            GenericParamKindAST::Type { .. } => DefPathData::TypeParam(name),
+        };
+        self.create_def(
+            param.id,
+            def_path_data,
+            REGULAR_SPACE,
+            param.ident.span
+        );
 
         visit::walk_generic_param(self, param);
     }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index b50407c82d1..d7ebd40f49b 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -139,29 +139,23 @@ impl<'a> AstValidator<'a> {
     }
 
     fn check_late_bound_lifetime_defs(&self, params: &Vec<GenericParamAST>) {
-        // Check: Only lifetime parameters
-        let non_lifetime_param_spans : Vec<_> = params.iter()
-            .filter_map(|param| match *param {
-                GenericParamAST::Lifetime(_) => None,
-                GenericParamAST::Type(ref t) => Some(t.ident.span),
-            }).collect();
-        if !non_lifetime_param_spans.is_empty() {
-            self.err_handler().span_err(non_lifetime_param_spans,
-                "only lifetime parameters can be used in this context");
-        }
-
-        // Check: No bounds on lifetime parameters
-        for param in params.iter() {
-            match *param {
-                GenericParamAST::Lifetime(ref l) => {
-                    if !l.bounds.is_empty() {
-                        let spans: Vec<_> = l.bounds.iter().map(|b| b.ident.span).collect();
+        // Check only lifetime parameters are present and that the lifetime
+        // parameters that are present have no bounds.
+        let non_lifetime_param_spans: Vec<_> = params.iter()
+            .filter_map(|param| match param.kind {
+                GenericParamKindAST::Lifetime { ref bounds, .. } => {
+                    if !bounds.is_empty() {
+                        let spans: Vec<_> = bounds.iter().map(|b| b.ident.span).collect();
                         self.err_handler().span_err(spans,
                             "lifetime bounds cannot be used in this context");
                     }
+                    None
                 }
-                GenericParamAST::Type(_) => {}
-            }
+                _ => Some(param.ident.span),
+            }).collect();
+        if !non_lifetime_param_spans.is_empty() {
+            self.err_handler().span_err(non_lifetime_param_spans,
+                "only lifetime parameters can be used in this context");
         }
     }
 }
@@ -335,22 +329,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
             ItemKind::TraitAlias(Generics { ref params, .. }, ..) => {
                 for param in params {
-                    if let GenericParamAST::Type(TyParam {
-                        ident,
-                        ref bounds,
-                        ref default,
-                        ..
-                    }) = *param
-                    {
-                        if !bounds.is_empty() {
-                            self.err_handler().span_err(ident.span,
-                                                        "type parameters on the left side of a \
-                                                         trait alias cannot be bounded");
-                        }
-                        if !default.is_none() {
-                            self.err_handler().span_err(ident.span,
-                                                        "type parameters on the left side of a \
-                                                         trait alias cannot have defaults");
+                    match param.kind {
+                        GenericParamKindAST::Lifetime { .. } => {}
+                        GenericParamKindAST::Type { ref bounds, ref default, .. } => {
+                            if !bounds.is_empty() {
+                                self.err_handler().span_err(param.ident.span,
+                                                            "type parameters on the left side \
+                                                             of a trait alias cannot be \
+                                                             bounded");
+                            }
+                            if !default.is_none() {
+                                self.err_handler().span_err(param.ident.span,
+                                                            "type parameters on the left side \
+                                                             of a trait alias cannot have \
+                                                             defaults");
+                            }
                         }
                     }
                 }
@@ -413,24 +406,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         let mut seen_non_lifetime_param = false;
         let mut seen_default = None;
         for param in &g.params {
-            match (param, seen_non_lifetime_param) {
-                (&GenericParamAST::Lifetime(ref ld), true) => {
+            match (&param.kind, seen_non_lifetime_param) {
+                (GenericParamKindAST::Lifetime { .. }, true) => {
                     self.err_handler()
-                        .span_err(ld.lifetime.ident.span, "lifetime parameters must be leading");
+                        .span_err(param.ident.span, "lifetime parameters must be leading");
                 },
-                (&GenericParamAST::Lifetime(_), false) => {}
-                _ => {
+                (GenericParamKindAST::Lifetime { .. }, false) => {}
+                (GenericParamKindAST::Type { ref default, .. }, _) => {
                     seen_non_lifetime_param = true;
+                    if default.is_some() {
+                        seen_default = Some(param.ident.span);
+                    } else if let Some(span) = seen_default {
+                        self.err_handler()
+                            .span_err(span, "type parameters with a default must be trailing");
+                        break;
+                    }
                 }
             }
-
-            if let GenericParamAST::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param {
-                seen_default = Some(ty_param.ident.span);
-            } else if let Some(span) = seen_default {
-                self.err_handler()
-                    .span_err(span, "type parameters with a default must be trailing");
-                break
-            }
         }
         for predicate in &g.where_clause.predicates {
             if let WherePredicate::EqPredicate(ref predicate) = *predicate {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index d70a7e2b827..37264eb3382 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -56,7 +56,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit::{self, FnKind, Visitor};
 use syntax::attr;
 use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
-use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamAST, Generics};
+use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKindAST, Generics};
 use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
 use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
 use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
@@ -797,31 +797,43 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         // put all the parameters on the ban list and then remove
         // them one by one as they are processed and become available.
         let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
+        let mut found_default = false;
         default_ban_rib.bindings.extend(generics.params.iter()
-            .filter_map(|p| if let GenericParamAST::Type(ref tp) = *p { Some(tp) } else { None })
-            .skip_while(|p| p.default.is_none())
-            .map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err)));
+            .filter_map(|param| match param.kind {
+                GenericParamKindAST::Lifetime { .. } => None,
+                GenericParamKindAST::Type { ref default, .. } => {
+                    if default.is_some() {
+                        found_default = true;
+                    }
+                    if found_default {
+                        return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
+                    }
+                    None
+                }
+            }));
 
         for param in &generics.params {
-            match *param {
-                GenericParamAST::Lifetime(_) => self.visit_generic_param(param),
-                GenericParamAST::Type(ref ty_param) => {
-                    for bound in &ty_param.bounds {
+            match param.kind {
+                GenericParamKindAST::Lifetime { .. } => self.visit_generic_param(param),
+                GenericParamKindAST::Type { ref bounds, ref default, .. } => {
+                    for bound in bounds {
                         self.visit_ty_param_bound(bound);
                     }
 
-                    if let Some(ref ty) = ty_param.default {
+                    if let Some(ref ty) = default {
                         self.ribs[TypeNS].push(default_ban_rib);
                         self.visit_ty(ty);
                         default_ban_rib = self.ribs[TypeNS].pop().unwrap();
                     }
 
                     // Allow all following defaults to refer to this type parameter.
-                    default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name));
+                    default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
                 }
             }
         }
-        for p in &generics.where_clause.predicates { self.visit_where_predicate(p); }
+        for p in &generics.where_clause.predicates {
+            self.visit_where_predicate(p);
+        }
     }
 }
 
@@ -2198,25 +2210,28 @@ impl<'a> Resolver<'a> {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = FxHashMap();
                 for param in &generics.params {
-                    if let GenericParamAST::Type(ref type_parameter) = *param {
-                        let ident = type_parameter.ident.modern();
-                        debug!("with_type_parameter_rib: {}", type_parameter.id);
-
-                        if seen_bindings.contains_key(&ident) {
-                            let span = seen_bindings.get(&ident).unwrap();
-                            let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
-                                ident.name,
-                                span,
-                            );
-                            resolve_error(self, type_parameter.ident.span, err);
-                        }
-                        seen_bindings.entry(ident).or_insert(type_parameter.ident.span);
+                    match param.kind {
+                        GenericParamKindAST::Type { .. } => {
+                            let ident = param.ident.modern();
+                            debug!("with_type_parameter_rib: {}", param.id);
+
+                            if seen_bindings.contains_key(&ident) {
+                                let span = seen_bindings.get(&ident).unwrap();
+                                let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
+                                    ident.name,
+                                    span,
+                                );
+                                resolve_error(self, param.ident.span, err);
+                            }
+                            seen_bindings.entry(ident).or_insert(param.ident.span);
 
-                        // plain insert (no renaming)
-                        let def_id = self.definitions.local_def_id(type_parameter.id);
-                        let def = Def::TyParam(def_id);
-                        function_type_rib.bindings.insert(ident, def);
-                        self.record_def(type_parameter.id, PathResolution::new(def));
+                            // plain insert (no renaming)
+                            let def_id = self.definitions.local_def_id(param.id);
+                            let def = Def::TyParam(def_id);
+                            function_type_rib.bindings.insert(ident, def);
+                            self.record_def(param.id, PathResolution::new(def));
+                        }
+                        _ => {}
                     }
                 }
                 self.ribs[TypeNS].push(function_type_rib);
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 303406dac76..94552e08a8c 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -370,35 +370,38 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         id: NodeId,
     ) {
         for param in &generics.params {
-            if let ast::GenericParamAST::Type(ref ty_param) = *param {
-                let param_ss = ty_param.ident.span;
-                let name = escape(self.span.snippet(param_ss));
-                // Append $id to name to make sure each one is unique
-                let qualname = format!("{}::{}${}", prefix, name, id);
-                if !self.span.filter_generated(Some(param_ss), full_span) {
-                    let id = ::id_from_node_id(ty_param.id, &self.save_ctxt);
-                    let span = self.span_from_span(param_ss);
+            match param.kind {
+                ast::GenericParamKindAST::Lifetime { .. } => {}
+                ast::GenericParamKindAST::Type { .. } => {
+                    let param_ss = param.ident.span;
+                    let name = escape(self.span.snippet(param_ss));
+                    // Append $id to name to make sure each one is unique.
+                    let qualname = format!("{}::{}${}", prefix, name, id);
+                    if !self.span.filter_generated(Some(param_ss), full_span) {
+                        let id = ::id_from_node_id(param.id, &self.save_ctxt);
+                        let span = self.span_from_span(param_ss);
 
-                    self.dumper.dump_def(
-                        &Access {
-                            public: false,
-                            reachable: false,
-                        },
-                        Def {
-                            kind: DefKind::Type,
-                            id,
-                            span,
-                            name,
-                            qualname,
-                            value: String::new(),
-                            parent: None,
-                            children: vec![],
-                            decl_id: None,
-                            docs: String::new(),
-                            sig: None,
-                            attributes: vec![],
-                        },
-                    );
+                        self.dumper.dump_def(
+                            &Access {
+                                public: false,
+                                reachable: false,
+                            },
+                            Def {
+                                kind: DefKind::Type,
+                                id,
+                                span,
+                                name,
+                                qualname,
+                                value: String::new(),
+                                parent: None,
+                                children: vec![],
+                                decl_id: None,
+                                docs: String::new(),
+                                sig: None,
+                                attributes: vec![],
+                            },
+                        );
+                    }
                 }
             }
         }
@@ -1479,14 +1482,17 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
 
     fn visit_generics(&mut self, generics: &'l ast::Generics) {
         for param in &generics.params {
-            if let ast::GenericParamAST::Type(ref ty_param) = *param {
-                for bound in ty_param.bounds.iter() {
-                    if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
-                        self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
+            match param.kind {
+                ast::GenericParamKindAST::Lifetime { .. } => {}
+                ast::GenericParamKindAST::Type { ref bounds, ref default, .. } => {
+                    for bound in bounds {
+                        if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
+                            self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
+                        }
+                    }
+                    if let Some(ref ty) = default {
+                        self.visit_ty(&ty);
                     }
-                }
-                if let Some(ref ty) = ty_param.default {
-                    self.visit_ty(&ty);
                 }
             }
         }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index a634e979363..f656b013c0a 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -934,9 +934,9 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
         sig.push_str(&generics
             .params
             .iter()
-            .map(|param| match *param {
-                ast::GenericParamAST::Lifetime(ref l) => l.lifetime.ident.name.to_string(),
-                ast::GenericParamAST::Type(ref t) => t.ident.to_string(),
+            .map(|param| match param.kind {
+                ast::GenericParamKindAST::Lifetime { .. } => param.ident.name.to_string(),
+                ast::GenericParamKindAST::Type { .. } => param.ident.to_string(),
             })
             .collect::<Vec<_>>()
             .join(", "));
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index f5384683506..8e8e0dfa182 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -223,9 +223,9 @@ impl Sig for ast::Ty {
                     text.push_str("for<");
                     text.push_str(&f.generic_params
                         .iter()
-                        .filter_map(|p| match *p {
-                            ast::GenericParamAST::Lifetime(ref l) => {
-                                Some(l.lifetime.ident.to_string())
+                        .filter_map(|param| match param.kind {
+                            ast::GenericParamKindAST::Lifetime { .. } => {
+                                Some(param.ident.to_string())
                             }
                             _ => None,
                         })
@@ -617,45 +617,34 @@ impl Sig for ast::Generics {
 
         let mut defs = vec![];
         for param in &self.params {
-            match *param {
-                ast::GenericParamAST::Lifetime(ref l) => {
-                    let mut l_text = l.lifetime.ident.to_string();
-                    defs.push(SigElement {
-                        id: id_from_node_id(l.lifetime.id, scx),
-                        start: offset + text.len(),
-                        end: offset + text.len() + l_text.len(),
-                    });
-
-                    if !l.bounds.is_empty() {
-                        l_text.push_str(": ");
-                        let bounds = l.bounds
-                            .iter()
+            let mut param_text = param.ident.to_string();
+            defs.push(SigElement {
+                id: id_from_node_id(param.id, scx),
+                start: offset + text.len(),
+                end: offset + text.len() + param_text.len(),
+            });
+            match param.kind {
+                ast::GenericParamKindAST::Lifetime { ref bounds, .. } => {
+                    if !bounds.is_empty() {
+                        param_text.push_str(": ");
+                        let bounds = bounds.iter()
                             .map(|l| l.ident.to_string())
                             .collect::<Vec<_>>()
                             .join(" + ");
-                        l_text.push_str(&bounds);
+                        param_text.push_str(&bounds);
                         // FIXME add lifetime bounds refs.
                     }
-                    text.push_str(&l_text);
-                    text.push(',');
                 }
-                ast::GenericParamAST::Type(ref t) => {
-                    let mut t_text = t.ident.to_string();
-                    defs.push(SigElement {
-                        id: id_from_node_id(t.id, scx),
-                        start: offset + text.len(),
-                        end: offset + text.len() + t_text.len(),
-                    });
-
-                    if !t.bounds.is_empty() {
-                        t_text.push_str(": ");
-                        t_text.push_str(&pprust::bounds_to_string(&t.bounds));
+                ast::GenericParamKindAST::Type { ref bounds, .. } => {
+                    if !bounds.is_empty() {
+                        param_text.push_str(": ");
+                        param_text.push_str(&pprust::bounds_to_string(bounds));
                         // FIXME descend properly into bounds.
                     }
-                    text.push_str(&t_text);
-                    text.push(',');
                 }
             }
+            text.push_str(&param_text);
+            text.push(',');
         }
 
         text.push('>');
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 17df8dd7027..c354edc5aaf 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -58,14 +58,6 @@ impl fmt::Debug for Lifetime {
     }
 }
 
-/// A lifetime definition, e.g. `'a: 'b+'c+'d`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct LifetimeDef {
-    pub attrs: ThinVec<Attribute>,
-    pub lifetime: Lifetime,
-    pub bounds: Vec<Lifetime>
-}
-
 /// A "Path" is essentially Rust's notion of a name.
 ///
 /// It's represented as a sequence of identifiers,
@@ -329,31 +321,38 @@ pub enum TraitBoundModifier {
 pub type TyParamBounds = Vec<TyParamBound>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct TyParam {
-    pub attrs: ThinVec<Attribute>,
-    pub ident: Ident,
-    pub id: NodeId,
-    pub bounds: TyParamBounds,
-    pub default: Option<P<Ty>>,
+pub enum GenericParamKindAST {
+    /// A lifetime definition, e.g. `'a: 'b+'c+'d`.
+    Lifetime {
+        bounds: Vec<Lifetime>,
+        lifetime: Lifetime,
+    },
+    Type {
+        bounds: TyParamBounds,
+        default: Option<P<Ty>>,
+    }
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum GenericParamAST {
-    Lifetime(LifetimeDef),
-    Type(TyParam),
+pub struct GenericParamAST {
+    pub ident: Ident,
+    pub id: NodeId,
+    pub attrs: ThinVec<Attribute>,
+
+    pub kind: GenericParamKindAST,
 }
 
 impl GenericParamAST {
     pub fn is_lifetime_param(&self) -> bool {
-        match *self {
-            GenericParamAST::Lifetime(_) => true,
+        match self.kind {
+            GenericParamKindAST::Lifetime { .. } => true,
             _ => false,
         }
     }
 
     pub fn is_type_param(&self) -> bool {
-        match *self {
-            GenericParamAST::Type(_) => true,
+        match self.kind {
+            GenericParamKindAST::Type { .. } => true,
             _ => false,
         }
     }
@@ -383,10 +382,8 @@ impl Generics {
 
     pub fn span_for_name(&self, name: &str) -> Option<Span> {
         for param in &self.params {
-            if let GenericParamAST::Type(ref t) = *param {
-                if t.ident.name == name {
-                    return Some(t.ident.span);
-                }
+            if param.ident.name == name {
+                return Some(param.ident.span);
             }
         }
         None
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 1c74a2bd5be..42745c14965 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -69,7 +69,7 @@ pub trait AstBuilder {
                id: ast::Ident,
                attrs: Vec<ast::Attribute>,
                bounds: ast::TyParamBounds,
-               default: Option<P<ast::Ty>>) -> ast::TyParam;
+               default: Option<P<ast::Ty>>) -> ast::GenericParamAST;
 
     fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
     fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef;
@@ -80,7 +80,7 @@ pub trait AstBuilder {
                     ident: ast::Ident,
                     attrs: Vec<ast::Attribute>,
                     bounds: Vec<ast::Lifetime>)
-                    -> ast::LifetimeDef;
+                    -> ast::GenericParamAST;
 
     // statements
     fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt;
@@ -437,13 +437,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                ident: ast::Ident,
                attrs: Vec<ast::Attribute>,
                bounds: ast::TyParamBounds,
-               default: Option<P<ast::Ty>>) -> ast::TyParam {
-        ast::TyParam {
+               default: Option<P<ast::Ty>>) -> ast::GenericParamAST {
+        ast::GenericParamAST {
             ident: ident.with_span_pos(span),
             id: ast::DUMMY_NODE_ID,
             attrs: attrs.into(),
-            bounds,
-            default,
+            kind: ast::GenericParamKindAST::Type {
+                bounds,
+                default,
+            }
         }
     }
 
@@ -475,11 +477,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                     ident: ast::Ident,
                     attrs: Vec<ast::Attribute>,
                     bounds: Vec<ast::Lifetime>)
-                    -> ast::LifetimeDef {
-        ast::LifetimeDef {
+                    -> ast::GenericParamAST {
+        let lifetime = self.lifetime(span, ident);
+        ast::GenericParamAST {
+            ident: lifetime.ident,
+            id: lifetime.id,
             attrs: attrs.into(),
-            lifetime: self.lifetime(span, ident),
-            bounds,
+            kind: ast::GenericParamKindAST::Lifetime {
+                lifetime,
+                bounds,
+            }
         }
     }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 1e09c7b2206..2f43487e036 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -687,38 +687,23 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
     }
 }
 
-pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
-    let TyParam {attrs, id, ident, bounds, default} = tp;
-    let attrs: Vec<_> = attrs.into();
-    TyParam {
-        attrs: attrs.into_iter()
-            .flat_map(|x| fld.fold_attribute(x).into_iter())
-            .collect::<Vec<_>>()
-            .into(),
-        id: fld.new_id(id),
-        ident: fld.fold_ident(ident),
-        bounds: fld.fold_bounds(bounds),
-        default: default.map(|x| fld.fold_ty(x)),
-    }
-}
-
 pub fn noop_fold_generic_param<T: Folder>(param: GenericParamAST, fld: &mut T) -> GenericParamAST {
     match param {
-        GenericParamAST::Lifetime(l) => {
-            let attrs: Vec<_> = l.attrs.into();
+        GenericParamAST::Lifetime { bounds, lifetime } => {
+            let attrs: Vec<_> = param.attrs.into();
             GenericParamAST::Lifetime(LifetimeDef {
                 attrs: attrs.into_iter()
                     .flat_map(|x| fld.fold_attribute(x).into_iter())
                     .collect::<Vec<_>>()
                     .into(),
                 lifetime: Lifetime {
-                    id: fld.new_id(l.lifetime.id),
-                    ident: fld.fold_ident(l.lifetime.ident),
+                    id: fld.new_id(param.id),
+                    ident: fld.fold_ident(param.ident),
                 },
-                bounds: l.bounds.move_map(|l| noop_fold_lifetime(l, fld)),
+                bounds: bounds.move_map(|l| noop_fold_lifetime(l, fld)),
             })
         }
-        GenericParamAST::Type(t) => GenericParamAST::Type(fld.fold_ty_param(t)),
+        GenericParamAST::Type { .. } => GenericParamAST::Type(fld.fold_ty_param(param)),
     }
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index be4a4b8b11f..2a1fc6b291c 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -21,10 +21,10 @@ use ast::EnumDef;
 use ast::{Expr, ExprKind, RangeLimits};
 use ast::{Field, FnDecl};
 use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
-use ast::GenericParamAST;
+use ast::{GenericParamAST, GenericParamKindAST};
 use ast::GenericArgAST;
 use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
-use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind};
+use ast::{Label, Lifetime, Lit, LitKind};
 use ast::Local;
 use ast::MacStmtStyle;
 use ast::{Mac, Mac_, MacDelimiter};
@@ -36,7 +36,7 @@ use ast::{VariantData, StructField};
 use ast::StrStyle;
 use ast::SelfKind;
 use ast::{TraitItem, TraitRef, TraitObjectSyntax};
-use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
+use ast::{Ty, TyKind, TypeBinding, TyParamBounds};
 use ast::{Visibility, VisibilityKind, WhereClause, CrateSugar};
 use ast::{UseTree, UseTreeKind};
 use ast::{BinOpKind, UnOp};
@@ -1311,9 +1311,7 @@ impl<'a> Parser<'a> {
         let lo = self.span;
 
         let (name, node, generics) = if self.eat_keyword(keywords::Type) {
-            let (generics, TyParam {ident, bounds, default, ..}) =
-                self.parse_trait_item_assoc_ty(vec![])?;
-            (ident, TraitItemKind::Type(bounds, default), generics)
+            self.parse_trait_item_assoc_ty()?
         } else if self.is_const_item() {
             self.expect_keyword(keywords::Const)?;
             let ident = self.parse_ident()?;
@@ -4805,7 +4803,9 @@ impl<'a> Parser<'a> {
     }
 
     /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?
-    fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, TyParam> {
+    fn parse_ty_param(&mut self,
+                      preceding_attrs: Vec<Attribute>)
+                      -> PResult<'a, GenericParamAST> {
         let ident = self.parse_ident()?;
 
         // Parse optional colon and param bounds.
@@ -4821,19 +4821,21 @@ impl<'a> Parser<'a> {
             None
         };
 
-        Ok(TyParam {
-            attrs: preceding_attrs.into(),
+        Ok(GenericParamAST {
             ident,
+            attrs: preceding_attrs.into(),
             id: ast::DUMMY_NODE_ID,
-            bounds,
-            default,
+            kind: GenericParamKindAST::Type {
+                bounds,
+                default,
+            }
         })
     }
 
     /// Parses the following grammar:
     ///     TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty]
-    fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>)
-        -> PResult<'a, (ast::Generics, TyParam)> {
+    fn parse_trait_item_assoc_ty(&mut self)
+        -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -4852,13 +4854,7 @@ impl<'a> Parser<'a> {
         };
         self.expect(&token::Semi)?;
 
-        Ok((generics, TyParam {
-            attrs: preceding_attrs.into(),
-            ident,
-            id: ast::DUMMY_NODE_ID,
-            bounds,
-            default,
-        }))
+        Ok((ident, TraitItemKind::Type(bounds, default), generics))
     }
 
     /// Parses (possibly empty) list of lifetime and type parameters, possibly including
@@ -4876,18 +4872,22 @@ impl<'a> Parser<'a> {
                 } else {
                     Vec::new()
                 };
-                params.push(ast::GenericParamAST::Lifetime(LifetimeDef {
+                params.push(ast::GenericParamAST {
+                    ident: lifetime.ident,
+                    id: lifetime.id,
                     attrs: attrs.into(),
-                    lifetime,
-                    bounds,
-                }));
+                    kind: ast::GenericParamKindAST::Lifetime {
+                        lifetime,
+                        bounds,
+                    }
+                });
                 if seen_ty_param {
                     self.span_err(self.prev_span,
                         "lifetime parameters must be declared prior to type parameters");
                 }
             } else if self.check_ident() {
                 // Parse type parameter.
-                params.push(ast::GenericParamAST::Type(self.parse_ty_param(attrs)?));
+                params.push(self.parse_ty_param(attrs)?);
                 seen_ty_param = true;
             } else {
                 // Check for trailing attributes and stop parsing.
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index a7a85a4c71f..1626135400d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2878,12 +2878,24 @@ impl<'a> State<'a> {
         self.s.word("<")?;
 
         self.commasep(Inconsistent, &generic_params, |s, param| {
-            match *param {
-                ast::GenericParamAST::Lifetime(ref lifetime_def) => {
-                    s.print_outer_attributes_inline(&lifetime_def.attrs)?;
-                    s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)
+            match param.kind {
+                ast::GenericParamKindAST::Lifetime { ref bounds, ref lifetime } => {
+                    s.print_outer_attributes_inline(&param.attrs)?;
+                    s.print_lifetime_bounds(lifetime, bounds)
                 },
-                ast::GenericParamAST::Type(ref ty_param) => s.print_ty_param(ty_param),
+                ast::GenericParamKindAST::Type { ref bounds, ref default } => {
+                    s.print_outer_attributes_inline(&param.attrs)?;
+                    s.print_ident(param.ident)?;
+                    s.print_bounds(":", bounds)?;
+                    match default {
+                        Some(ref default) => {
+                            s.s.space()?;
+                            s.word_space("=")?;
+                            s.print_type(default)
+                        }
+                        _ => Ok(())
+                    }
+                }
             }
         })?;
 
@@ -2891,20 +2903,6 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> {
-        self.print_outer_attributes_inline(&param.attrs)?;
-        self.print_ident(param.ident)?;
-        self.print_bounds(":", &param.bounds)?;
-        match param.default {
-            Some(ref default) => {
-                self.s.space()?;
-                self.word_space("=")?;
-                self.print_type(default)
-            }
-            _ => Ok(())
-        }
-    }
-
     pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
                               -> io::Result<()> {
         if where_clause.predicates.is_empty() {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 091673bfba9..c919f6c355c 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -491,17 +491,17 @@ pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyPar
 }
 
 pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParamAST) {
-    match *param {
-        GenericParamAST::Lifetime(ref l) => {
-            visitor.visit_ident(l.lifetime.ident);
-            walk_list!(visitor, visit_lifetime, &l.bounds);
-            walk_list!(visitor, visit_attribute, &*l.attrs);
+    match param.kind {
+        GenericParamKindAST::Lifetime { ref bounds, ref lifetime, .. } => {
+            visitor.visit_ident(param.ident);
+            walk_list!(visitor, visit_lifetime, bounds);
+            walk_list!(visitor, visit_attribute, param.attrs.iter());
         }
-        GenericParamAST::Type(ref t) => {
+        GenericParamKindAST::Type { ref bounds, ref default, .. } => {
             visitor.visit_ident(t.ident);
-            walk_list!(visitor, visit_ty_param_bound, &t.bounds);
-            walk_list!(visitor, visit_ty, &t.default);
-            walk_list!(visitor, visit_attribute, &*t.attrs);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_ty, default);
+            walk_list!(visitor, visit_attribute, param.attrs.iter());
         }
     }
 }
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 4bc8d208bab..cbf7b1e0876 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -192,8 +192,8 @@ use std::collections::HashSet;
 use std::vec;
 
 use rustc_target::spec::abi::Abi;
-use syntax::ast::{self, BinOpKind, EnumDef, Expr, GenericParamAST, Generics, Ident, PatKind};
-use syntax::ast::{VariantData, GenericArgAST};
+use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
+use syntax::ast::{VariantData, GenericParamKindAST, GenericArgAST};
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
@@ -547,9 +547,9 @@ impl<'a> TraitDef<'a> {
 
         // Create the generic parameters
         params.extend(generics.params.iter().map(|param| {
-            match *param {
-                ref l @ GenericParamAST::Lifetime(_) => l.clone(),
-                GenericParamAST::Type(ref ty_param) => {
+            match param.kind {
+                GenericParamKindAST::Lifetime { .. } => param.clone(),
+                GenericParamKindAST::Type { bounds: ref ty_bounds, .. } => {
                     // I don't think this can be moved out of the loop, since
                     // a TyParamBound requires an ast id
                     let mut bounds: Vec<_> =
@@ -564,12 +564,11 @@ impl<'a> TraitDef<'a> {
                     bounds.push(cx.typarambound(trait_path.clone()));
 
                     // also add in any bounds from the declaration
-                    for declared_bound in ty_param.bounds.iter() {
+                    for declared_bound in ty_bounds {
                         bounds.push((*declared_bound).clone());
                     }
 
-                    let ty_param = cx.typaram(self.span, ty_param.ident, vec![], bounds, None);
-                    GenericParamAST::Type(ty_param)
+                    cx.typaram(self.span, param.ident, vec![], bounds, None)
                 }
             }
         }));
@@ -607,8 +606,8 @@ impl<'a> TraitDef<'a> {
             // Extra scope required here so ty_params goes out of scope before params is moved
 
             let mut ty_params = params.iter()
-                .filter_map(|param| match *param {
-                    ast::GenericParamAST::Type(ref t) => Some(t),
+                .filter_map(|param| match param.kind {
+                    ast::GenericParamKindAST::Type { .. } => Some(param),
                     _ => None,
                 })
                 .peekable();
@@ -668,17 +667,16 @@ impl<'a> TraitDef<'a> {
         // Create the type parameters on the `self` path.
         let self_ty_params: Vec<P<ast::Ty>> = generics.params
             .iter()
-            .filter_map(|param| match *param {
-                GenericParamAST::Type(ref ty_param)
-                    => Some(cx.ty_ident(self.span, ty_param.ident)),
+            .filter_map(|param| match param.kind {
+                GenericParamKindAST::Type { .. } => Some(cx.ty_ident(self.span, param.ident)),
                 _ => None,
             })
             .collect();
 
         let self_lifetimes: Vec<ast::Lifetime> = generics.params
             .iter()
-            .filter_map(|param| match *param {
-                GenericParamAST::Lifetime(ref ld) => Some(ld.lifetime),
+            .filter_map(|param| match param.kind {
+                GenericParamKindAST::Lifetime { ref lifetime, .. } => Some(*lifetime),
                 _ => None,
             })
             .collect();
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index 22487e7bfe3..c9f274ed210 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, GenericParamAST, Generics, Ident, SelfKind, GenericArgAST};
+use syntax::ast::{Expr, GenericParamKindAST, Generics, Ident, SelfKind, GenericArgAST};
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::build::AstBuilder;
 use syntax::codemap::{respan, DUMMY_SP};
@@ -191,9 +191,9 @@ impl<'a> Ty<'a> {
             Self_ => {
                 let ty_params: Vec<P<ast::Ty>> = self_generics.params
                     .iter()
-                    .filter_map(|param| match *param {
-                        GenericParamAST::Type(ref ty_param) => {
-                            Some(cx.ty_ident(span, ty_param.ident))
+                    .filter_map(|param| match param.kind {
+                        GenericParamKindAST::Type { .. } => {
+                            Some(cx.ty_ident(span, param.ident))
                         }
                         _ => None,
                     })
@@ -201,8 +201,8 @@ impl<'a> Ty<'a> {
 
                 let lifetimes: Vec<ast::Lifetime> = self_generics.params
                     .iter()
-                    .filter_map(|param| match *param {
-                        GenericParamAST::Lifetime(ref ld) => Some(ld.lifetime),
+                    .filter_map(|param| match param.kind {
+                        GenericParamKindAST::Lifetime { ref lifetime, .. } => Some(*lifetime),
                         _ => None,
                     })
                     .collect();
@@ -234,7 +234,7 @@ fn mk_ty_param(cx: &ExtCtxt,
                bounds: &[Path],
                self_ident: Ident,
                self_generics: &Generics)
-               -> ast::TyParam {
+               -> ast::GenericParamAST {
     let bounds = bounds.iter()
         .map(|b| {
             let path = b.to_path(cx, span, self_ident, self_generics);
@@ -244,7 +244,7 @@ fn mk_ty_param(cx: &ExtCtxt,
     cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None)
 }
 
-fn mk_generics(params: Vec<GenericParamAST>, span: Span) -> Generics {
+fn mk_generics(params: Vec<ast::GenericParamAST>, span: Span) -> Generics {
     Generics {
         params,
         where_clause: ast::WhereClause {
@@ -282,16 +282,13 @@ impl<'a> LifetimeBounds<'a> {
                 let bounds = bounds.iter()
                     .map(|b| cx.lifetime(span, Ident::from_str(b)))
                     .collect();
-                let lifetime_def = cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds);
-                GenericParamAST::Lifetime(lifetime_def)
+                cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds)
             })
             .chain(self.bounds
                 .iter()
                 .map(|t| {
                     let (name, ref bounds) = *t;
-                    GenericParamAST::Type(mk_ty_param(
-                        cx, span, name, &[], &bounds, self_ty, self_generics
-                    ))
+                    mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics)
                 })
             )
             .collect();
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 9bc19bb5ede..6813ce4c265 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -134,9 +134,12 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
         match item.node {
             ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
             ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
-                for param in params.iter() {
-                    if let ast::GenericParamAST::Type(ref ty) = *param {
-                        typaram.push_str(&ty.ident.as_str());
+                for param in params {
+                    match param.kind {
+                        ast::GenericParamKindAST::Type { .. } => {
+                            typaram.push_str(&param.ident.as_str());
+                        }
+                        _ => {}
                     }
                 }
             }