Update generic arguments to be stored similar to generic parameters
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index b6996f4..6b61ccc 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -204,6 +204,8 @@
 # [ cfg ( feature = "full" ) ]
 fn fold_foreign_item_type(&mut self, i: ForeignItemType) -> ForeignItemType { fold_foreign_item_type(self, i) }
 
+fn fold_generic_arg(&mut self, i: GenericArg) -> GenericArg { fold_generic_arg(self, i) }
+
 fn fold_generic_param(&mut self, i: GenericParam) -> GenericParam { fold_generic_param(self, i) }
 
 fn fold_generics(&mut self, i: Generics) -> Generics { fold_generics(self, i) }
@@ -428,9 +430,7 @@
     AngleBracketedParameterData {
         turbofish: _i . turbofish,
         lt_token: _i . lt_token,
-        lifetimes: _i . lifetimes,
-        types: FoldHelper::lift(_i . types, |it| { _visitor.fold_type(it) }),
-        bindings: FoldHelper::lift(_i . bindings, |it| { _visitor.fold_type_binding(it) }),
+        args: FoldHelper::lift(_i . args, |it| { _visitor.fold_generic_arg(it) }),
         gt_token: _i . gt_token,
     }
 }
@@ -1452,6 +1452,27 @@
     }
 }
 
+pub fn fold_generic_arg<V: Folder + ?Sized>(_visitor: &mut V, _i: GenericArg) -> GenericArg {
+    use ::GenericArg::*;
+    match _i {
+        Lifetime(_binding_0, ) => {
+            Lifetime (
+                _binding_0,
+            )
+        }
+        Type(_binding_0, ) => {
+            Type (
+                _visitor.fold_type(_binding_0),
+            )
+        }
+        TypeBinding(_binding_0, ) => {
+            TypeBinding (
+                _visitor.fold_type_binding(_binding_0),
+            )
+        }
+    }
+}
+
 pub fn fold_generic_param<V: Folder + ?Sized>(_visitor: &mut V, _i: GenericParam) -> GenericParam {
     use ::GenericParam::*;
     match _i {
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index ec40662..72f2861 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -177,6 +177,8 @@
 # [ cfg ( feature = "full" ) ]
 fn visit_foreign_item_type(&mut self, i: &'ast ForeignItemType) { visit_foreign_item_type(self, i) }
 
+fn visit_generic_arg(&mut self, i: &'ast GenericArg) { visit_generic_arg(self, i) }
+
 fn visit_generic_param(&mut self, i: &'ast GenericParam) { visit_generic_param(self, i) }
 
 fn visit_generics(&mut self, i: &'ast Generics) { visit_generics(self, i) }
@@ -396,9 +398,7 @@
 pub fn visit_angle_bracketed_parameter_data<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast AngleBracketedParameterData) {
     // Skipped field _i . turbofish;
     // Skipped field _i . lt_token;
-    // Skipped field _i . lifetimes;
-    for el in (_i . types).iter() { let it = el.item(); _visitor.visit_type(&it) };
-    for el in (_i . bindings).iter() { let it = el.item(); _visitor.visit_type_binding(&it) };
+    for el in (_i . args).iter() { let it = el.item(); _visitor.visit_generic_arg(&it) };
     // Skipped field _i . gt_token;
 }
 # [ cfg ( feature = "full" ) ]
@@ -1131,6 +1131,21 @@
     // Skipped field _i . semi_token;
 }
 
+pub fn visit_generic_arg<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericArg) {
+    use ::GenericArg::*;
+    match *_i {
+        Lifetime(ref _binding_0, ) => {
+            // Skipped field * _binding_0;
+        }
+        Type(ref _binding_0, ) => {
+            _visitor.visit_type(&* _binding_0);
+        }
+        TypeBinding(ref _binding_0, ) => {
+            _visitor.visit_type_binding(&* _binding_0);
+        }
+    }
+}
+
 pub fn visit_generic_param<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast GenericParam) {
     use ::GenericParam::*;
     match *_i {
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index 80329b0..2a4cb11 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -177,6 +177,8 @@
 # [ cfg ( feature = "full" ) ]
 fn visit_foreign_item_type_mut(&mut self, i: &mut ForeignItemType) { visit_foreign_item_type_mut(self, i) }
 
+fn visit_generic_arg_mut(&mut self, i: &mut GenericArg) { visit_generic_arg_mut(self, i) }
+
 fn visit_generic_param_mut(&mut self, i: &mut GenericParam) { visit_generic_param_mut(self, i) }
 
 fn visit_generics_mut(&mut self, i: &mut Generics) { visit_generics_mut(self, i) }
@@ -396,9 +398,7 @@
 pub fn visit_angle_bracketed_parameter_data_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut AngleBracketedParameterData) {
     // Skipped field _i . turbofish;
     // Skipped field _i . lt_token;
-    // Skipped field _i . lifetimes;
-    for mut el in (_i . types).iter_mut() { let mut it = el.item_mut(); _visitor.visit_type_mut(&mut it) };
-    for mut el in (_i . bindings).iter_mut() { let mut it = el.item_mut(); _visitor.visit_type_binding_mut(&mut it) };
+    for mut el in (_i . args).iter_mut() { let mut it = el.item_mut(); _visitor.visit_generic_arg_mut(&mut it) };
     // Skipped field _i . gt_token;
 }
 # [ cfg ( feature = "full" ) ]
@@ -1131,6 +1131,21 @@
     // Skipped field _i . semi_token;
 }
 
+pub fn visit_generic_arg_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut GenericArg) {
+    use ::GenericArg::*;
+    match *_i {
+        Lifetime(ref mut _binding_0, ) => {
+            // Skipped field * _binding_0;
+        }
+        Type(ref mut _binding_0, ) => {
+            _visitor.visit_type_mut(&mut * _binding_0);
+        }
+        TypeBinding(ref mut _binding_0, ) => {
+            _visitor.visit_type_binding_mut(&mut * _binding_0);
+        }
+    }
+}
+
 pub fn visit_generic_param_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut GenericParam) {
     use ::GenericParam::*;
     match *_i {
diff --git a/src/lib.rs b/src/lib.rs
index f88112d..bd59686 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -87,7 +87,7 @@
              ReturnType, MutType, Mutability, ParenthesizedParameterData, Path,
              PathParameters, PathSegment, PolyTraitRef, QSelf, Type, TypeBinding, Unsafety,
              TypeSlice, TypeArray, TypePtr, TypeReference, TypeBareFn, TypeNever, TypeTup, TypePath,
-             TypeTraitObject, TypeImplTrait, TypeParen, TypeInfer, TypeGroup};
+             TypeTraitObject, TypeImplTrait, TypeParen, TypeInfer, TypeGroup, GenericArg};
 #[cfg(feature = "printing")]
 pub use ty::PathTokens;
 
diff --git a/src/ty.rs b/src/ty.rs
index 009e081..77a43fb 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -184,28 +184,32 @@
     pub fn is_empty(&self) -> bool {
         match *self {
             PathParameters::None => true,
-            PathParameters::AngleBracketed(ref bracketed) => {
-                bracketed.lifetimes.is_empty() && bracketed.types.is_empty() &&
-                bracketed.bindings.is_empty()
-            }
+            PathParameters::AngleBracketed(ref bracketed) => bracketed.args.is_empty(),
             PathParameters::Parenthesized(_) => false,
         }
     }
 }
 
+ast_enum! {
+    /// A individual generic argument, like `'a`, `T`, or `Item=T`.
+    pub enum GenericArg {
+        /// The lifetime parameters for this path segment.
+        Lifetime(Lifetime),
+        /// The type parameters for this path segment, if present.
+        Type(Type),
+        /// Bindings (equality constraints) on associated types, if present.
+        ///
+        /// E.g., `Foo<A=Bar>`.
+        TypeBinding(TypeBinding),
+    }
+}
+
 ast_struct! {
     /// A path like `Foo<'a, T>`
     pub struct AngleBracketedParameterData {
         pub turbofish: Option<Token![::]>,
         pub lt_token: Token![<],
-        /// The lifetime parameters for this path segment.
-        pub lifetimes: Delimited<Lifetime, Token![,]>,
-        /// The type parameters for this path segment, if present.
-        pub types: Delimited<Type, Token![,]>,
-        /// Bindings (equality constraints) on associated types, if present.
-        ///
-        /// E.g., `Foo<A=Bar>`.
-        pub bindings: Delimited<TypeBinding, Token![,]>,
+        pub args: Delimited<GenericArg, Token![,]>,
         pub gt_token: Token![>],
     }
 }
@@ -687,38 +691,39 @@
         }
     }
 
+    impl Synom for GenericArg {
+        named!(parse -> Self, alt!(
+            call!(ty_no_eq_after) => { GenericArg::Type }
+            |
+            syn!(Lifetime) => { GenericArg::Lifetime }
+            |
+            syn!(TypeBinding) => { GenericArg::TypeBinding }
+        ));
+    }
+
+    impl Synom for AngleBracketedParameterData {
+        named!(parse -> Self, do_parse!(
+            turbofish: option!(punct!(::)) >>
+            lt: punct!(<) >>
+            args: call!(Delimited::parse_terminated) >>
+            gt: punct!(>) >>
+            (AngleBracketedParameterData {
+                turbofish: turbofish,
+                lt_token: lt,
+                args: args,
+                gt_token: gt,
+            })
+        ));
+    }
+
     impl Synom for PathSegment {
         named!(parse -> Self, alt!(
             do_parse!(
                 ident: syn!(Ident) >>
-                turbofish: option!(punct!(::)) >>
-                lt: punct!(<) >>
-                lifetimes: call!(Delimited::parse_terminated) >>
-                types: cond!(
-                    lifetimes.is_empty() || lifetimes.trailing_delim(),
-                    call!(Delimited::parse_terminated_with,
-                            ty_no_eq_after)
-                ) >>
-                bindings: cond!(
-                    match types {
-                        Some(ref t) => t.is_empty() || t.trailing_delim(),
-                        None => lifetimes.is_empty() || lifetimes.trailing_delim(),
-                    },
-                    call!(Delimited::parse_terminated)
-                ) >>
-                gt: punct!(>) >>
+                parameters: syn!(AngleBracketedParameterData) >>
                 (PathSegment {
                     ident: ident,
-                    parameters: PathParameters::AngleBracketed(
-                        AngleBracketedParameterData {
-                            turbofish: turbofish,
-                            lt_token: lt,
-                            lifetimes: lifetimes,
-                            types: types.unwrap_or_default(),
-                            bindings: bindings.unwrap_or_default(),
-                            gt_token: gt,
-                        }
-                    ),
+                    parameters: PathParameters::AngleBracketed(parameters),
                 })
             )
             |
@@ -1018,27 +1023,21 @@
         }
     }
 
+    impl ToTokens for GenericArg {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            match *self {
+                GenericArg::Lifetime(ref lt) => lt.to_tokens(tokens),
+                GenericArg::Type(ref ty) => ty.to_tokens(tokens),
+                GenericArg::TypeBinding(ref tb) => tb.to_tokens(tokens),
+            }
+        }
+    }
+
     impl ToTokens for AngleBracketedParameterData {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.turbofish.to_tokens(tokens);
             self.lt_token.to_tokens(tokens);
-            self.lifetimes.to_tokens(tokens);
-            if !self.lifetimes.empty_or_trailing() && !self.types.is_empty() {
-                <Token![,]>::default().to_tokens(tokens);
-            }
-            self.types.to_tokens(tokens);
-            if (
-                // If we have no trailing delimiter after a non-empty types list, or
-                !self.types.empty_or_trailing() ||
-                // If we have no trailing delimiter after a non-empty lifetimes
-                // list before an empty types list, and
-                (self.types.is_empty() && !self.lifetimes.empty_or_trailing())) &&
-                // We have some bindings, then we need a comma.
-                !self.bindings.is_empty()
-            {
-                <Token![,]>::default().to_tokens(tokens);
-            }
-            self.bindings.to_tokens(tokens);
+            self.args.to_tokens(tokens);
             self.gt_token.to_tokens(tokens);
         }
     }
diff --git a/syn_codegen/src/main.rs b/syn_codegen/src/main.rs
index 4125774..a1757d2 100644
--- a/syn_codegen/src/main.rs
+++ b/syn_codegen/src/main.rs
@@ -314,7 +314,10 @@
             _ => panic!("Expected at least 1 type parameter here"),
         };
 
-        data.types.first().expect("Expected at least 1 type parameter here").item()
+        match *data.args.first().expect("Expected at least 1 type parameter here").item() {
+            &GenericArg::Type(ref ty) => ty,
+            _ => panic!("Expected at least 1 type parmeter here"),
+        }
     }
 
     fn simple_visit(
diff --git a/tests/test_derive_input.rs b/tests/test_derive_input.rs
index d4e0ada..c56d59a 100644
--- a/tests/test_derive_input.rs
+++ b/tests/test_derive_input.rs
@@ -118,12 +118,12 @@
                                         AngleBracketedParameterData {
                                             turbofish: None,
                                             lt_token: Default::default(),
-                                            lifetimes: Default::default(),
-                                            types: vec![Type::from(TypePath {
-                                                qself: None,
-                                                path: "Attribute".into(),
-                                            })].into(),
-                                            bindings: Default::default(),
+                                            args: vec![
+                                                GenericArg::Type(Type::from(TypePath {
+                                                    qself: None,
+                                                    path: "Attribute".into(),
+                                                })),
+                                            ].into(),
                                             gt_token: Default::default(),
                                         },
                                     ),