Reorganize DeriveInput
diff --git a/src/data.rs b/src/data.rs
index f1e0c76..6777767 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -10,25 +10,32 @@
         /// Name of the variant.
         pub ident: Ident,
 
-        /// Type of variant.
-        pub data: VariantData,
+        /// Content stored in the variant.
+        pub fields: Fields,
 
         /// Explicit discriminant, e.g. `Foo = 1`
         pub discriminant: Option<(Token![=], Expr)>,
     }
 }
 
-ast_enum! {
+ast_enum_of_structs! {
     /// Data stored within an enum variant or struct.
-    pub enum VariantData {
-        /// Struct variant, e.g. `Point { x: f64, y: f64 }`.
-        Struct(token::Brace, Delimited<Field, Token![,]>),
+    pub enum Fields {
+        /// Named fields of a struct or struct variant such as `Point { x: f64,
+        /// y: f64 }`.
+        pub Named(FieldsNamed {
+            pub brace_token: token::Brace,
+            pub fields: Delimited<Field, Token![,]>,
+        }),
 
-        /// Tuple variant, e.g. `Some(T)`.
-        Tuple(token::Paren, Delimited<Field, Token![,]>),
+        /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
+        pub Unnamed(FieldsUnnamed {
+            pub paren_token: token::Paren,
+            pub fields: Delimited<Field, Token![,]>,
+        }),
 
-        /// Unit variant, e.g. `None`.
-        Unit,
+        /// Unit struct or unit variant such as `None`.
+        pub Unit,
     }
 }
 
@@ -87,8 +94,53 @@
 
     use synom::Synom;
 
+    impl Synom for Variant {
+        named!(parse -> Self, do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
+            id: syn!(Ident) >>
+            fields: alt!(
+                syn!(FieldsNamed) => { Fields::Named }
+                |
+                syn!(FieldsUnnamed) => { Fields::Unnamed }
+                |
+                epsilon!() => { |_| Fields::Unit }
+            ) >>
+            disr: option!(tuple!(punct!(=), syn!(Expr))) >>
+            (Variant {
+                ident: id,
+                attrs: attrs,
+                fields: fields,
+                discriminant: disr,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("enum variant")
+        }
+    }
+
+    impl Synom for FieldsNamed {
+        named!(parse -> Self, map!(
+            braces!(call!(Delimited::parse_terminated_with, Field::parse_named)),
+            |(brace, fields)| FieldsNamed {
+                brace_token: brace,
+                fields: fields,
+            }
+        ));
+    }
+
+    impl Synom for FieldsUnnamed {
+        named!(parse -> Self, map!(
+            parens!(call!(Delimited::parse_terminated_with, Field::parse_unnamed)),
+            |(paren, fields)| FieldsUnnamed {
+                paren_token: paren,
+                fields: fields,
+            }
+        ));
+    }
+
     impl Field {
-        named!(pub parse_struct -> Self, do_parse!(
+        named!(pub parse_named -> Self, do_parse!(
             attrs: many0!(Attribute::parse_outer) >>
             vis: syn!(Visibility) >>
             id: syn!(Ident) >>
@@ -103,7 +155,7 @@
             })
         ));
 
-        named!(pub parse_tuple -> Self, do_parse!(
+        named!(pub parse_unnamed -> Self, do_parse!(
             attrs: many0!(Attribute::parse_outer) >>
             vis: syn!(Visibility) >>
             ty: syn!(Type) >>
@@ -190,7 +242,7 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(&self.attrs);
             self.ident.to_tokens(tokens);
-            self.data.to_tokens(tokens);
+            self.fields.to_tokens(tokens);
             if let Some((ref eq_token, ref disc)) = self.discriminant {
                 eq_token.to_tokens(tokens);
                 disc.to_tokens(tokens);
@@ -198,21 +250,19 @@
         }
     }
 
-    impl ToTokens for VariantData {
+    impl ToTokens for FieldsNamed {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            match *self {
-                VariantData::Struct(ref brace, ref fields) => {
-                    brace.surround(tokens, |tokens| {
-                        fields.to_tokens(tokens);
-                    });
-                }
-                VariantData::Tuple(ref paren, ref fields) => {
-                    paren.surround(tokens, |tokens| {
-                        fields.to_tokens(tokens);
-                    });
-                }
-                VariantData::Unit => {}
-            }
+            self.brace_token.surround(tokens, |tokens| {
+                self.fields.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for FieldsUnnamed {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            self.paren_token.surround(tokens, |tokens| {
+                self.fields.to_tokens(tokens);
+            });
         }
     }
 
diff --git a/src/derive.rs b/src/derive.rs
index cf4a3d1..7b58523 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -2,7 +2,7 @@
 use delimited::Delimited;
 
 ast_struct! {
-    /// Struct or enum sent to a `proc_macro_derive` macro.
+    /// Data structure sent to a `proc_macro_derive` macro.
     pub struct DeriveInput {
         /// Attributes tagged on the whole struct or enum.
         pub attrs: Vec<Attribute>,
@@ -17,25 +17,31 @@
         pub generics: Generics,
 
         /// Data within the struct or enum.
-        pub body: Body,
+        pub data: Data,
     }
 }
 
 ast_enum_of_structs! {
-    /// Body of a derived struct or enum.
-    pub enum Body {
+    /// The storage of a struct, enum or union data structure.
+    pub enum Data {
+        /// It's a struct.
+        pub Struct(DataStruct {
+            pub struct_token: Token![struct],
+            pub fields: Fields,
+            pub semi_token: Option<Token![;]>,
+        }),
+
         /// It's an enum.
-        pub Enum(BodyEnum {
+        pub Enum(DataEnum {
             pub enum_token: Token![enum],
             pub brace_token: token::Brace,
             pub variants: Delimited<Variant, Token![,]>,
         }),
 
-        /// It's a struct.
-        pub Struct(BodyStruct {
-            pub data: VariantData,
-            pub struct_token: Token![struct],
-            pub semi_token: Option<Token![;]>,
+        /// It's an untagged union.
+        pub Union(DataUnion {
+            pub union_token: Token![union],
+            pub fields: FieldsNamed,
         }),
     }
 
@@ -60,7 +66,7 @@
             id: syn!(Ident) >>
             generics: syn!(Generics) >>
             item: switch!(value!(which),
-                Ok(s) => map!(struct_body, move |(wh, body, semi)| DeriveInput {
+                Ok(s) => map!(data_struct, move |(wh, fields, semi)| DeriveInput {
                     ident: id,
                     vis: vis,
                     attrs: attrs,
@@ -68,14 +74,14 @@
                         where_clause: wh,
                         .. generics
                     },
-                    body: Body::Struct(BodyStruct {
+                    data: Data::Struct(DataStruct {
                         struct_token: s,
-                        data: body,
+                        fields: fields,
                         semi_token: semi,
                     }),
                 })
                 |
-                Err(e) => map!(enum_body, move |(wh, brace, body)| DeriveInput {
+                Err(e) => map!(data_enum, move |(wh, brace, variants)| DeriveInput {
                     ident: id,
                     vis: vis,
                     attrs: attrs,
@@ -83,8 +89,8 @@
                         where_clause: wh,
                         .. generics
                     },
-                    body: Body::Enum(BodyEnum {
-                        variants: body,
+                    data: Data::Enum(DataEnum {
+                        variants: variants,
                         brace_token: brace,
                         enum_token: e,
                     }),
@@ -98,70 +104,38 @@
         }
     }
 
-    named!(struct_body -> (Option<WhereClause>, VariantData, Option<Token![;]>), alt!(
+    named!(data_struct -> (Option<WhereClause>, Fields, Option<Token![;]>), alt!(
         do_parse!(
             wh: option!(syn!(WhereClause)) >>
-            body: struct_like_body >>
-            (wh, VariantData::Struct(body.0, body.1), None)
+            fields: syn!(FieldsNamed) >>
+            (wh, Fields::Named(fields), None)
         )
         |
         do_parse!(
-            body: tuple_like_body >>
+            fields: syn!(FieldsUnnamed) >>
             wh: option!(syn!(WhereClause)) >>
             semi: punct!(;) >>
-            (wh, VariantData::Tuple(body.0, body.1), Some(semi))
+            (wh, Fields::Unnamed(fields), Some(semi))
         )
         |
         do_parse!(
             wh: option!(syn!(WhereClause)) >>
             semi: punct!(;) >>
-            (wh, VariantData::Unit, Some(semi))
+            (wh, Fields::Unit, Some(semi))
         )
     ));
 
-    named!(enum_body -> (Option<WhereClause>, token::Brace, Delimited<Variant, Token![,]>), do_parse!(
+    named!(data_enum -> (Option<WhereClause>, token::Brace, Delimited<Variant, Token![,]>), do_parse!(
         wh: option!(syn!(WhereClause)) >>
         data: braces!(Delimited::parse_terminated) >>
         (wh, data.0, data.1)
     ));
-
-    impl Synom for Variant {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            id: syn!(Ident) >>
-            data: alt!(
-                struct_like_body => { |(b, d)| VariantData::Struct(b, d) }
-                |
-                tuple_like_body => { |(b, d)| VariantData::Tuple(b, d) }
-                |
-                epsilon!() => { |_| VariantData::Unit }
-            ) >>
-            disr: option!(tuple!(punct!(=), syn!(Expr))) >>
-            (Variant {
-                ident: id,
-                attrs: attrs,
-                data: data,
-                discriminant: disr,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("enum variant")
-        }
-    }
-
-    named!(struct_like_body -> (token::Brace, Delimited<Field, Token![,]>),
-           braces!(call!(Delimited::parse_terminated_with, Field::parse_struct)));
-
-    named!(tuple_like_body -> (token::Paren, Delimited<Field, Token![,]>),
-           parens!(call!(Delimited::parse_terminated_with, Field::parse_tuple)));
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
     use attr::FilterAttrs;
-    use data::VariantData;
     use quote::{ToTokens, Tokens};
 
     impl ToTokens for DeriveInput {
@@ -170,34 +144,40 @@
                 attr.to_tokens(tokens);
             }
             self.vis.to_tokens(tokens);
-            match self.body {
-                Body::Enum(ref d) => d.enum_token.to_tokens(tokens),
-                Body::Struct(ref d) => d.struct_token.to_tokens(tokens),
+            match self.data {
+                Data::Struct(ref d) => d.struct_token.to_tokens(tokens),
+                Data::Enum(ref d) => d.enum_token.to_tokens(tokens),
+                Data::Union(ref d) => d.union_token.to_tokens(tokens),
             }
             self.ident.to_tokens(tokens);
             self.generics.to_tokens(tokens);
-            match self.body {
-                Body::Enum(ref data) => {
+            match self.data {
+                Data::Struct(ref data) => {
+                    match data.fields {
+                        Fields::Named(ref fields) => {
+                            self.generics.where_clause.to_tokens(tokens);
+                            fields.to_tokens(tokens);
+                        }
+                        Fields::Unnamed(ref fields) => {
+                            fields.to_tokens(tokens);
+                            self.generics.where_clause.to_tokens(tokens);
+                            TokensOrDefault(&data.semi_token).to_tokens(tokens);
+                        }
+                        Fields::Unit => {
+                            self.generics.where_clause.to_tokens(tokens);
+                            TokensOrDefault(&data.semi_token).to_tokens(tokens);
+                        }
+                    }
+                }
+                Data::Enum(ref data) => {
                     self.generics.where_clause.to_tokens(tokens);
                     data.brace_token.surround(tokens, |tokens| {
                         data.variants.to_tokens(tokens);
                     });
                 }
-                Body::Struct(ref data) => {
-                    match data.data {
-                        VariantData::Struct(..) => {
-                            self.generics.where_clause.to_tokens(tokens);
-                            data.data.to_tokens(tokens);
-                        }
-                        VariantData::Tuple(..) => {
-                            data.data.to_tokens(tokens);
-                            self.generics.where_clause.to_tokens(tokens);
-                        }
-                        VariantData::Unit => {
-                            self.generics.where_clause.to_tokens(tokens);
-                        }
-                    }
-                    data.semi_token.to_tokens(tokens);
+                Data::Union(ref data) => {
+                    self.generics.where_clause.to_tokens(tokens);
+                    data.fields.to_tokens(tokens);
                 }
             }
         }
diff --git a/src/expr.rs b/src/expr.rs
index fbc3033..013a69e 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1279,22 +1279,20 @@
         mut e: call!(atom_expr, allow_struct, allow_block) >>
         many0!(alt!(
             tap!(args: and_call => {
-                let (paren, args) = args;
                 e = ExprCall {
                     attrs: Vec::new(),
                     func: Box::new(e),
-                    args: args,
-                    paren_token: paren,
+                    paren_token: args.0,
+                    args: args.1,
                 }.into();
             })
             |
             tap!(i: and_index => {
-                let (i, token) = i;
                 e = ExprIndex {
                     attrs: Vec::new(),
                     expr: Box::new(e),
-                    bracket_token: token,
-                    index: Box::new(i),
+                    bracket_token: i.0,
+                    index: Box::new(i.1),
                 }.into();
             })
         )) >>
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index 14e4575..a7438b9 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -66,16 +66,18 @@
 # [ cfg ( feature = "full" ) ]
 fn fold_block(&mut self, i: Block) -> Block { fold_block(self, i) }
 
-fn fold_body(&mut self, i: Body) -> Body { fold_body(self, i) }
-
-fn fold_body_enum(&mut self, i: BodyEnum) -> BodyEnum { fold_body_enum(self, i) }
-
-fn fold_body_struct(&mut self, i: BodyStruct) -> BodyStruct { fold_body_struct(self, i) }
-
 fn fold_bound_lifetimes(&mut self, i: BoundLifetimes) -> BoundLifetimes { fold_bound_lifetimes(self, i) }
 
 fn fold_const_param(&mut self, i: ConstParam) -> ConstParam { fold_const_param(self, i) }
 
+fn fold_data(&mut self, i: Data) -> Data { fold_data(self, i) }
+
+fn fold_data_enum(&mut self, i: DataEnum) -> DataEnum { fold_data_enum(self, i) }
+
+fn fold_data_struct(&mut self, i: DataStruct) -> DataStruct { fold_data_struct(self, i) }
+
+fn fold_data_union(&mut self, i: DataUnion) -> DataUnion { fold_data_union(self, i) }
+
 fn fold_derive_input(&mut self, i: DeriveInput) -> DeriveInput { fold_derive_input(self, i) }
 
 fn fold_expr(&mut self, i: Expr) -> Expr { fold_expr(self, i) }
@@ -165,6 +167,12 @@
 fn fold_field_pat(&mut self, i: FieldPat) -> FieldPat { fold_field_pat(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn fold_field_value(&mut self, i: FieldValue) -> FieldValue { fold_field_value(self, i) }
+
+fn fold_fields(&mut self, i: Fields) -> Fields { fold_fields(self, i) }
+
+fn fold_fields_named(&mut self, i: FieldsNamed) -> FieldsNamed { fold_fields_named(self, i) }
+
+fn fold_fields_unnamed(&mut self, i: FieldsUnnamed) -> FieldsUnnamed { fold_fields_unnamed(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn fold_file(&mut self, i: File) -> File { fold_file(self, i) }
 # [ cfg ( feature = "full" ) ]
@@ -378,8 +386,6 @@
 
 fn fold_variant(&mut self, i: Variant) -> Variant { fold_variant(self, i) }
 
-fn fold_variant_data(&mut self, i: VariantData) -> VariantData { fold_variant_data(self, i) }
-
 fn fold_vis_crate(&mut self, i: VisCrate) -> VisCrate { fold_vis_crate(self, i) }
 
 fn fold_vis_public(&mut self, i: VisPublic) -> VisPublic { fold_vis_public(self, i) }
@@ -672,37 +678,6 @@
     }
 }
 
-pub fn fold_body<V: Folder + ?Sized>(_visitor: &mut V, _i: Body) -> Body {
-    match _i {
-        Body::Enum(_binding_0, ) => {
-            Body::Enum (
-                _visitor.fold_body_enum(_binding_0),
-            )
-        }
-        Body::Struct(_binding_0, ) => {
-            Body::Struct (
-                _visitor.fold_body_struct(_binding_0),
-            )
-        }
-    }
-}
-
-pub fn fold_body_enum<V: Folder + ?Sized>(_visitor: &mut V, _i: BodyEnum) -> BodyEnum {
-    BodyEnum {
-        enum_token: Token ! [ enum ](tokens_helper(_visitor, &(_i . enum_token).0)),
-        brace_token: Brace(tokens_helper(_visitor, &(_i . brace_token).0)),
-        variants: FoldHelper::lift(_i . variants, |it| { _visitor.fold_variant(it) }),
-    }
-}
-
-pub fn fold_body_struct<V: Folder + ?Sized>(_visitor: &mut V, _i: BodyStruct) -> BodyStruct {
-    BodyStruct {
-        data: _visitor.fold_variant_data(_i . data),
-        struct_token: Token ! [ struct ](tokens_helper(_visitor, &(_i . struct_token).0)),
-        semi_token: (_i . semi_token).map(|it| { Token ! [ ; ](tokens_helper(_visitor, &(it).0)) }),
-    }
-}
-
 pub fn fold_bound_lifetimes<V: Folder + ?Sized>(_visitor: &mut V, _i: BoundLifetimes) -> BoundLifetimes {
     BoundLifetimes {
         for_token: Token ! [ for ](tokens_helper(_visitor, &(_i . for_token).0)),
@@ -724,13 +699,56 @@
     }
 }
 
+pub fn fold_data<V: Folder + ?Sized>(_visitor: &mut V, _i: Data) -> Data {
+    match _i {
+        Data::Struct(_binding_0, ) => {
+            Data::Struct (
+                _visitor.fold_data_struct(_binding_0),
+            )
+        }
+        Data::Enum(_binding_0, ) => {
+            Data::Enum (
+                _visitor.fold_data_enum(_binding_0),
+            )
+        }
+        Data::Union(_binding_0, ) => {
+            Data::Union (
+                _visitor.fold_data_union(_binding_0),
+            )
+        }
+    }
+}
+
+pub fn fold_data_enum<V: Folder + ?Sized>(_visitor: &mut V, _i: DataEnum) -> DataEnum {
+    DataEnum {
+        enum_token: Token ! [ enum ](tokens_helper(_visitor, &(_i . enum_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &(_i . brace_token).0)),
+        variants: FoldHelper::lift(_i . variants, |it| { _visitor.fold_variant(it) }),
+    }
+}
+
+pub fn fold_data_struct<V: Folder + ?Sized>(_visitor: &mut V, _i: DataStruct) -> DataStruct {
+    DataStruct {
+        struct_token: Token ! [ struct ](tokens_helper(_visitor, &(_i . struct_token).0)),
+        fields: _visitor.fold_fields(_i . fields),
+        semi_token: (_i . semi_token).map(|it| { Token ! [ ; ](tokens_helper(_visitor, &(it).0)) }),
+    }
+}
+
+pub fn fold_data_union<V: Folder + ?Sized>(_visitor: &mut V, _i: DataUnion) -> DataUnion {
+    DataUnion {
+        union_token: Token ! [ union ](tokens_helper(_visitor, &(_i . union_token).0)),
+        fields: _visitor.fold_fields_named(_i . fields),
+    }
+}
+
 pub fn fold_derive_input<V: Folder + ?Sized>(_visitor: &mut V, _i: DeriveInput) -> DeriveInput {
     DeriveInput {
         attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         vis: _visitor.fold_visibility(_i . vis),
         ident: _visitor.fold_ident(_i . ident),
         generics: _visitor.fold_generics(_i . generics),
-        body: _visitor.fold_body(_i . body),
+        data: _visitor.fold_data(_i . data),
     }
 }
 
@@ -1334,6 +1352,36 @@
         expr: _visitor.fold_expr(_i . expr),
     }
 }
+
+pub fn fold_fields<V: Folder + ?Sized>(_visitor: &mut V, _i: Fields) -> Fields {
+    match _i {
+        Fields::Named(_binding_0, ) => {
+            Fields::Named (
+                _visitor.fold_fields_named(_binding_0),
+            )
+        }
+        Fields::Unnamed(_binding_0, ) => {
+            Fields::Unnamed (
+                _visitor.fold_fields_unnamed(_binding_0),
+            )
+        }
+        Fields::Unit => { Fields::Unit }
+    }
+}
+
+pub fn fold_fields_named<V: Folder + ?Sized>(_visitor: &mut V, _i: FieldsNamed) -> FieldsNamed {
+    FieldsNamed {
+        brace_token: Brace(tokens_helper(_visitor, &(_i . brace_token).0)),
+        fields: FoldHelper::lift(_i . fields, |it| { _visitor.fold_field(it) }),
+    }
+}
+
+pub fn fold_fields_unnamed<V: Folder + ?Sized>(_visitor: &mut V, _i: FieldsUnnamed) -> FieldsUnnamed {
+    FieldsUnnamed {
+        paren_token: Paren(tokens_helper(_visitor, &(_i . paren_token).0)),
+        fields: FoldHelper::lift(_i . fields, |it| { _visitor.fold_field(it) }),
+    }
+}
 # [ cfg ( feature = "full" ) ]
 pub fn fold_file<V: Folder + ?Sized>(_visitor: &mut V, _i: File) -> File {
     File {
@@ -1649,16 +1697,16 @@
                 _visitor.fold_item_type(_binding_0),
             )
         }
-        Item::Enum(_binding_0, ) => {
-            Item::Enum (
-                _visitor.fold_item_enum(_binding_0),
-            )
-        }
         Item::Struct(_binding_0, ) => {
             Item::Struct (
                 _visitor.fold_item_struct(_binding_0),
             )
         }
+        Item::Enum(_binding_0, ) => {
+            Item::Enum (
+                _visitor.fold_item_enum(_binding_0),
+            )
+        }
         Item::Union(_binding_0, ) => {
             Item::Union (
                 _visitor.fold_item_union(_binding_0),
@@ -1831,7 +1879,7 @@
         struct_token: Token ! [ struct ](tokens_helper(_visitor, &(_i . struct_token).0)),
         ident: _visitor.fold_ident(_i . ident),
         generics: _visitor.fold_generics(_i . generics),
-        data: _visitor.fold_variant_data(_i . data),
+        fields: _visitor.fold_fields(_i . fields),
         semi_token: (_i . semi_token).map(|it| { Token ! [ ; ](tokens_helper(_visitor, &(it).0)) }),
     }
 }
@@ -1872,7 +1920,7 @@
         union_token: Token ! [ union ](tokens_helper(_visitor, &(_i . union_token).0)),
         ident: _visitor.fold_ident(_i . ident),
         generics: _visitor.fold_generics(_i . generics),
-        data: _visitor.fold_variant_data(_i . data),
+        fields: _visitor.fold_fields_named(_i . fields),
     }
 }
 # [ cfg ( feature = "full" ) ]
@@ -2715,7 +2763,7 @@
     Variant {
         attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         ident: _visitor.fold_ident(_i . ident),
-        data: _visitor.fold_variant_data(_i . data),
+        fields: _visitor.fold_fields(_i . fields),
         discriminant: (_i . discriminant).map(|it| { (
             Token ! [ = ](tokens_helper(_visitor, &(( it ) . 0).0)),
             _visitor.fold_expr(( it ) . 1),
@@ -2723,24 +2771,6 @@
     }
 }
 
-pub fn fold_variant_data<V: Folder + ?Sized>(_visitor: &mut V, _i: VariantData) -> VariantData {
-    match _i {
-        VariantData::Struct(_binding_0, _binding_1, ) => {
-            VariantData::Struct (
-                Brace(tokens_helper(_visitor, &(_binding_0).0)),
-                FoldHelper::lift(_binding_1, |it| { _visitor.fold_field(it) }),
-            )
-        }
-        VariantData::Tuple(_binding_0, _binding_1, ) => {
-            VariantData::Tuple (
-                Paren(tokens_helper(_visitor, &(_binding_0).0)),
-                FoldHelper::lift(_binding_1, |it| { _visitor.fold_field(it) }),
-            )
-        }
-        VariantData::Unit => { VariantData::Unit }
-    }
-}
-
 pub fn fold_vis_crate<V: Folder + ?Sized>(_visitor: &mut V, _i: VisCrate) -> VisCrate {
     VisCrate {
         pub_token: Token ! [ pub ](tokens_helper(_visitor, &(_i . pub_token).0)),
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index 4f73cb2..ca97b32 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -62,16 +62,18 @@
 # [ cfg ( feature = "full" ) ]
 fn visit_block(&mut self, i: &'ast Block) { visit_block(self, i) }
 
-fn visit_body(&mut self, i: &'ast Body) { visit_body(self, i) }
-
-fn visit_body_enum(&mut self, i: &'ast BodyEnum) { visit_body_enum(self, i) }
-
-fn visit_body_struct(&mut self, i: &'ast BodyStruct) { visit_body_struct(self, i) }
-
 fn visit_bound_lifetimes(&mut self, i: &'ast BoundLifetimes) { visit_bound_lifetimes(self, i) }
 
 fn visit_const_param(&mut self, i: &'ast ConstParam) { visit_const_param(self, i) }
 
+fn visit_data(&mut self, i: &'ast Data) { visit_data(self, i) }
+
+fn visit_data_enum(&mut self, i: &'ast DataEnum) { visit_data_enum(self, i) }
+
+fn visit_data_struct(&mut self, i: &'ast DataStruct) { visit_data_struct(self, i) }
+
+fn visit_data_union(&mut self, i: &'ast DataUnion) { visit_data_union(self, i) }
+
 fn visit_derive_input(&mut self, i: &'ast DeriveInput) { visit_derive_input(self, i) }
 
 fn visit_expr(&mut self, i: &'ast Expr) { visit_expr(self, i) }
@@ -161,6 +163,12 @@
 fn visit_field_pat(&mut self, i: &'ast FieldPat) { visit_field_pat(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_field_value(&mut self, i: &'ast FieldValue) { visit_field_value(self, i) }
+
+fn visit_fields(&mut self, i: &'ast Fields) { visit_fields(self, i) }
+
+fn visit_fields_named(&mut self, i: &'ast FieldsNamed) { visit_fields_named(self, i) }
+
+fn visit_fields_unnamed(&mut self, i: &'ast FieldsUnnamed) { visit_fields_unnamed(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_file(&mut self, i: &'ast File) { visit_file(self, i) }
 # [ cfg ( feature = "full" ) ]
@@ -374,8 +382,6 @@
 
 fn visit_variant(&mut self, i: &'ast Variant) { visit_variant(self, i) }
 
-fn visit_variant_data(&mut self, i: &'ast VariantData) { visit_variant_data(self, i) }
-
 fn visit_vis_crate(&mut self, i: &'ast VisCrate) { visit_vis_crate(self, i) }
 
 fn visit_vis_public(&mut self, i: &'ast VisPublic) { visit_vis_public(self, i) }
@@ -576,29 +582,6 @@
     for it in & _i . stmts { _visitor.visit_stmt(it) };
 }
 
-pub fn visit_body<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Body) {
-    match *_i {
-        Body::Enum(ref _binding_0, ) => {
-            _visitor.visit_body_enum(_binding_0);
-        }
-        Body::Struct(ref _binding_0, ) => {
-            _visitor.visit_body_struct(_binding_0);
-        }
-    }
-}
-
-pub fn visit_body_enum<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast BodyEnum) {
-    tokens_helper(_visitor, &(& _i . enum_token).0);
-    tokens_helper(_visitor, &(& _i . brace_token).0);
-    for el in & _i . variants { let it = el.item(); _visitor.visit_variant(it) };
-}
-
-pub fn visit_body_struct<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast BodyStruct) {
-    _visitor.visit_variant_data(& _i . data);
-    tokens_helper(_visitor, &(& _i . struct_token).0);
-    if let Some(ref it) = _i . semi_token { tokens_helper(_visitor, &(it).0) };
-}
-
 pub fn visit_bound_lifetimes<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast BoundLifetimes) {
     tokens_helper(_visitor, &(& _i . for_token).0);
     tokens_helper(_visitor, &(& _i . lt_token).0);
@@ -616,12 +599,43 @@
     if let Some(ref it) = _i . default { _visitor.visit_expr(it) };
 }
 
+pub fn visit_data<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Data) {
+    match *_i {
+        Data::Struct(ref _binding_0, ) => {
+            _visitor.visit_data_struct(_binding_0);
+        }
+        Data::Enum(ref _binding_0, ) => {
+            _visitor.visit_data_enum(_binding_0);
+        }
+        Data::Union(ref _binding_0, ) => {
+            _visitor.visit_data_union(_binding_0);
+        }
+    }
+}
+
+pub fn visit_data_enum<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DataEnum) {
+    tokens_helper(_visitor, &(& _i . enum_token).0);
+    tokens_helper(_visitor, &(& _i . brace_token).0);
+    for el in & _i . variants { let it = el.item(); _visitor.visit_variant(it) };
+}
+
+pub fn visit_data_struct<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DataStruct) {
+    tokens_helper(_visitor, &(& _i . struct_token).0);
+    _visitor.visit_fields(& _i . fields);
+    if let Some(ref it) = _i . semi_token { tokens_helper(_visitor, &(it).0) };
+}
+
+pub fn visit_data_union<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DataUnion) {
+    tokens_helper(_visitor, &(& _i . union_token).0);
+    _visitor.visit_fields_named(& _i . fields);
+}
+
 pub fn visit_derive_input<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DeriveInput) {
     for it in & _i . attrs { _visitor.visit_attribute(it) };
     _visitor.visit_visibility(& _i . vis);
     _visitor.visit_ident(& _i . ident);
     _visitor.visit_generics(& _i . generics);
-    _visitor.visit_body(& _i . body);
+    _visitor.visit_data(& _i . data);
 }
 
 pub fn visit_expr<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Expr) {
@@ -1058,6 +1072,28 @@
     if let Some(ref it) = _i . colon_token { tokens_helper(_visitor, &(it).0) };
     _visitor.visit_expr(& _i . expr);
 }
+
+pub fn visit_fields<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Fields) {
+    match *_i {
+        Fields::Named(ref _binding_0, ) => {
+            _visitor.visit_fields_named(_binding_0);
+        }
+        Fields::Unnamed(ref _binding_0, ) => {
+            _visitor.visit_fields_unnamed(_binding_0);
+        }
+        Fields::Unit => { }
+    }
+}
+
+pub fn visit_fields_named<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast FieldsNamed) {
+    tokens_helper(_visitor, &(& _i . brace_token).0);
+    for el in & _i . fields { let it = el.item(); _visitor.visit_field(it) };
+}
+
+pub fn visit_fields_unnamed<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast FieldsUnnamed) {
+    tokens_helper(_visitor, &(& _i . paren_token).0);
+    for el in & _i . fields { let it = el.item(); _visitor.visit_field(it) };
+}
 # [ cfg ( feature = "full" ) ]
 pub fn visit_file<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast File) {
     // Skipped field _i . shebang;
@@ -1290,12 +1326,12 @@
         Item::Type(ref _binding_0, ) => {
             _visitor.visit_item_type(_binding_0);
         }
-        Item::Enum(ref _binding_0, ) => {
-            _visitor.visit_item_enum(_binding_0);
-        }
         Item::Struct(ref _binding_0, ) => {
             _visitor.visit_item_struct(_binding_0);
         }
+        Item::Enum(ref _binding_0, ) => {
+            _visitor.visit_item_enum(_binding_0);
+        }
         Item::Union(ref _binding_0, ) => {
             _visitor.visit_item_union(_binding_0);
         }
@@ -1435,7 +1471,7 @@
     tokens_helper(_visitor, &(& _i . struct_token).0);
     _visitor.visit_ident(& _i . ident);
     _visitor.visit_generics(& _i . generics);
-    _visitor.visit_variant_data(& _i . data);
+    _visitor.visit_fields(& _i . fields);
     if let Some(ref it) = _i . semi_token { tokens_helper(_visitor, &(it).0) };
 }
 # [ cfg ( feature = "full" ) ]
@@ -1470,7 +1506,7 @@
     tokens_helper(_visitor, &(& _i . union_token).0);
     _visitor.visit_ident(& _i . ident);
     _visitor.visit_generics(& _i . generics);
-    _visitor.visit_variant_data(& _i . data);
+    _visitor.visit_fields_named(& _i . fields);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_item_use<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemUse) {
@@ -2087,27 +2123,13 @@
 pub fn visit_variant<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Variant) {
     for it in & _i . attrs { _visitor.visit_attribute(it) };
     _visitor.visit_ident(& _i . ident);
-    _visitor.visit_variant_data(& _i . data);
+    _visitor.visit_fields(& _i . fields);
     if let Some(ref it) = _i . discriminant { 
             tokens_helper(_visitor, &(& ( it ) . 0).0);
             _visitor.visit_expr(& ( it ) . 1);
          };
 }
 
-pub fn visit_variant_data<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast VariantData) {
-    match *_i {
-        VariantData::Struct(ref _binding_0, ref _binding_1, ) => {
-            tokens_helper(_visitor, &(_binding_0).0);
-            for el in _binding_1 { let it = el.item(); _visitor.visit_field(it) };
-        }
-        VariantData::Tuple(ref _binding_0, ref _binding_1, ) => {
-            tokens_helper(_visitor, &(_binding_0).0);
-            for el in _binding_1 { let it = el.item(); _visitor.visit_field(it) };
-        }
-        VariantData::Unit => { }
-    }
-}
-
 pub fn visit_vis_crate<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast VisCrate) {
     tokens_helper(_visitor, &(& _i . pub_token).0);
     tokens_helper(_visitor, &(& _i . paren_token).0);
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index 812a4f1..c8b8ceb 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -62,16 +62,18 @@
 # [ cfg ( feature = "full" ) ]
 fn visit_block_mut(&mut self, i: &mut Block) { visit_block_mut(self, i) }
 
-fn visit_body_mut(&mut self, i: &mut Body) { visit_body_mut(self, i) }
-
-fn visit_body_enum_mut(&mut self, i: &mut BodyEnum) { visit_body_enum_mut(self, i) }
-
-fn visit_body_struct_mut(&mut self, i: &mut BodyStruct) { visit_body_struct_mut(self, i) }
-
 fn visit_bound_lifetimes_mut(&mut self, i: &mut BoundLifetimes) { visit_bound_lifetimes_mut(self, i) }
 
 fn visit_const_param_mut(&mut self, i: &mut ConstParam) { visit_const_param_mut(self, i) }
 
+fn visit_data_mut(&mut self, i: &mut Data) { visit_data_mut(self, i) }
+
+fn visit_data_enum_mut(&mut self, i: &mut DataEnum) { visit_data_enum_mut(self, i) }
+
+fn visit_data_struct_mut(&mut self, i: &mut DataStruct) { visit_data_struct_mut(self, i) }
+
+fn visit_data_union_mut(&mut self, i: &mut DataUnion) { visit_data_union_mut(self, i) }
+
 fn visit_derive_input_mut(&mut self, i: &mut DeriveInput) { visit_derive_input_mut(self, i) }
 
 fn visit_expr_mut(&mut self, i: &mut Expr) { visit_expr_mut(self, i) }
@@ -161,6 +163,12 @@
 fn visit_field_pat_mut(&mut self, i: &mut FieldPat) { visit_field_pat_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_field_value_mut(&mut self, i: &mut FieldValue) { visit_field_value_mut(self, i) }
+
+fn visit_fields_mut(&mut self, i: &mut Fields) { visit_fields_mut(self, i) }
+
+fn visit_fields_named_mut(&mut self, i: &mut FieldsNamed) { visit_fields_named_mut(self, i) }
+
+fn visit_fields_unnamed_mut(&mut self, i: &mut FieldsUnnamed) { visit_fields_unnamed_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_file_mut(&mut self, i: &mut File) { visit_file_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
@@ -374,8 +382,6 @@
 
 fn visit_variant_mut(&mut self, i: &mut Variant) { visit_variant_mut(self, i) }
 
-fn visit_variant_data_mut(&mut self, i: &mut VariantData) { visit_variant_data_mut(self, i) }
-
 fn visit_vis_crate_mut(&mut self, i: &mut VisCrate) { visit_vis_crate_mut(self, i) }
 
 fn visit_vis_public_mut(&mut self, i: &mut VisPublic) { visit_vis_public_mut(self, i) }
@@ -576,29 +582,6 @@
     for it in & mut _i . stmts { _visitor.visit_stmt_mut(it) };
 }
 
-pub fn visit_body_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Body) {
-    match *_i {
-        Body::Enum(ref mut _binding_0, ) => {
-            _visitor.visit_body_enum_mut(_binding_0);
-        }
-        Body::Struct(ref mut _binding_0, ) => {
-            _visitor.visit_body_struct_mut(_binding_0);
-        }
-    }
-}
-
-pub fn visit_body_enum_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut BodyEnum) {
-    tokens_helper(_visitor, &mut (& mut _i . enum_token).0);
-    tokens_helper(_visitor, &mut (& mut _i . brace_token).0);
-    for mut el in & mut _i . variants { let it = el.item_mut(); _visitor.visit_variant_mut(it) };
-}
-
-pub fn visit_body_struct_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut BodyStruct) {
-    _visitor.visit_variant_data_mut(& mut _i . data);
-    tokens_helper(_visitor, &mut (& mut _i . struct_token).0);
-    if let Some(ref mut it) = _i . semi_token { tokens_helper(_visitor, &mut (it).0) };
-}
-
 pub fn visit_bound_lifetimes_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut BoundLifetimes) {
     tokens_helper(_visitor, &mut (& mut _i . for_token).0);
     tokens_helper(_visitor, &mut (& mut _i . lt_token).0);
@@ -616,12 +599,43 @@
     if let Some(ref mut it) = _i . default { _visitor.visit_expr_mut(it) };
 }
 
+pub fn visit_data_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Data) {
+    match *_i {
+        Data::Struct(ref mut _binding_0, ) => {
+            _visitor.visit_data_struct_mut(_binding_0);
+        }
+        Data::Enum(ref mut _binding_0, ) => {
+            _visitor.visit_data_enum_mut(_binding_0);
+        }
+        Data::Union(ref mut _binding_0, ) => {
+            _visitor.visit_data_union_mut(_binding_0);
+        }
+    }
+}
+
+pub fn visit_data_enum_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut DataEnum) {
+    tokens_helper(_visitor, &mut (& mut _i . enum_token).0);
+    tokens_helper(_visitor, &mut (& mut _i . brace_token).0);
+    for mut el in & mut _i . variants { let it = el.item_mut(); _visitor.visit_variant_mut(it) };
+}
+
+pub fn visit_data_struct_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut DataStruct) {
+    tokens_helper(_visitor, &mut (& mut _i . struct_token).0);
+    _visitor.visit_fields_mut(& mut _i . fields);
+    if let Some(ref mut it) = _i . semi_token { tokens_helper(_visitor, &mut (it).0) };
+}
+
+pub fn visit_data_union_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut DataUnion) {
+    tokens_helper(_visitor, &mut (& mut _i . union_token).0);
+    _visitor.visit_fields_named_mut(& mut _i . fields);
+}
+
 pub fn visit_derive_input_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut DeriveInput) {
     for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     _visitor.visit_visibility_mut(& mut _i . vis);
     _visitor.visit_ident_mut(& mut _i . ident);
     _visitor.visit_generics_mut(& mut _i . generics);
-    _visitor.visit_body_mut(& mut _i . body);
+    _visitor.visit_data_mut(& mut _i . data);
 }
 
 pub fn visit_expr_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Expr) {
@@ -1058,6 +1072,28 @@
     if let Some(ref mut it) = _i . colon_token { tokens_helper(_visitor, &mut (it).0) };
     _visitor.visit_expr_mut(& mut _i . expr);
 }
+
+pub fn visit_fields_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Fields) {
+    match *_i {
+        Fields::Named(ref mut _binding_0, ) => {
+            _visitor.visit_fields_named_mut(_binding_0);
+        }
+        Fields::Unnamed(ref mut _binding_0, ) => {
+            _visitor.visit_fields_unnamed_mut(_binding_0);
+        }
+        Fields::Unit => { }
+    }
+}
+
+pub fn visit_fields_named_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut FieldsNamed) {
+    tokens_helper(_visitor, &mut (& mut _i . brace_token).0);
+    for mut el in & mut _i . fields { let it = el.item_mut(); _visitor.visit_field_mut(it) };
+}
+
+pub fn visit_fields_unnamed_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut FieldsUnnamed) {
+    tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
+    for mut el in & mut _i . fields { let it = el.item_mut(); _visitor.visit_field_mut(it) };
+}
 # [ cfg ( feature = "full" ) ]
 pub fn visit_file_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut File) {
     // Skipped field _i . shebang;
@@ -1290,12 +1326,12 @@
         Item::Type(ref mut _binding_0, ) => {
             _visitor.visit_item_type_mut(_binding_0);
         }
-        Item::Enum(ref mut _binding_0, ) => {
-            _visitor.visit_item_enum_mut(_binding_0);
-        }
         Item::Struct(ref mut _binding_0, ) => {
             _visitor.visit_item_struct_mut(_binding_0);
         }
+        Item::Enum(ref mut _binding_0, ) => {
+            _visitor.visit_item_enum_mut(_binding_0);
+        }
         Item::Union(ref mut _binding_0, ) => {
             _visitor.visit_item_union_mut(_binding_0);
         }
@@ -1435,7 +1471,7 @@
     tokens_helper(_visitor, &mut (& mut _i . struct_token).0);
     _visitor.visit_ident_mut(& mut _i . ident);
     _visitor.visit_generics_mut(& mut _i . generics);
-    _visitor.visit_variant_data_mut(& mut _i . data);
+    _visitor.visit_fields_mut(& mut _i . fields);
     if let Some(ref mut it) = _i . semi_token { tokens_helper(_visitor, &mut (it).0) };
 }
 # [ cfg ( feature = "full" ) ]
@@ -1470,7 +1506,7 @@
     tokens_helper(_visitor, &mut (& mut _i . union_token).0);
     _visitor.visit_ident_mut(& mut _i . ident);
     _visitor.visit_generics_mut(& mut _i . generics);
-    _visitor.visit_variant_data_mut(& mut _i . data);
+    _visitor.visit_fields_named_mut(& mut _i . fields);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_item_use_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ItemUse) {
@@ -2087,27 +2123,13 @@
 pub fn visit_variant_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Variant) {
     for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     _visitor.visit_ident_mut(& mut _i . ident);
-    _visitor.visit_variant_data_mut(& mut _i . data);
+    _visitor.visit_fields_mut(& mut _i . fields);
     if let Some(ref mut it) = _i . discriminant { 
             tokens_helper(_visitor, &mut (& mut ( it ) . 0).0);
             _visitor.visit_expr_mut(& mut ( it ) . 1);
          };
 }
 
-pub fn visit_variant_data_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut VariantData) {
-    match *_i {
-        VariantData::Struct(ref mut _binding_0, ref mut _binding_1, ) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
-            for mut el in _binding_1 { let it = el.item_mut(); _visitor.visit_field_mut(it) };
-        }
-        VariantData::Tuple(ref mut _binding_0, ref mut _binding_1, ) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
-            for mut el in _binding_1 { let it = el.item_mut(); _visitor.visit_field_mut(it) };
-        }
-        VariantData::Unit => { }
-    }
-}
-
 pub fn visit_vis_crate_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut VisCrate) {
     tokens_helper(_visitor, &mut (& mut _i . pub_token).0);
     tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
diff --git a/src/item.rs b/src/item.rs
index 3305678..0fa91ea 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -110,6 +110,18 @@
             pub ty: Box<Type>,
             pub semi_token: Token![;],
         }),
+        /// A struct definition (`struct` or `pub struct`).
+        ///
+        /// E.g. `struct Foo<A> { x: A }`
+        pub Struct(ItemStruct {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub struct_token: Token![struct],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub fields: Fields,
+            pub semi_token: Option<Token![;]>,
+        }),
         /// An enum definition (`enum` or `pub enum`).
         ///
         /// E.g. `enum Foo<A, B> { C<A>, D<B> }`
@@ -122,18 +134,6 @@
             pub brace_token: token::Brace,
             pub variants: Delimited<Variant, Token![,]>,
         }),
-        /// A struct definition (`struct` or `pub struct`).
-        ///
-        /// E.g. `struct Foo<A> { x: A }`
-        pub Struct(ItemStruct {
-            pub attrs: Vec<Attribute>,
-            pub vis: Visibility,
-            pub struct_token: Token![struct],
-            pub ident: Ident,
-            pub generics: Generics,
-            pub data: VariantData,
-            pub semi_token: Option<Token![;]>,
-        }),
         /// A union definition (`union` or `pub union`).
         ///
         /// E.g. `union Foo<A, B> { x: A, y: B }`
@@ -143,7 +143,7 @@
             pub union_token: Token![union],
             pub ident: Ident,
             pub generics: Generics,
-            pub data: VariantData,
+            pub fields: FieldsNamed,
         }),
         /// A Trait declaration (`trait` or `pub trait`).
         ///
@@ -256,8 +256,17 @@
 
 impl From<DeriveInput> for Item {
     fn from(input: DeriveInput) -> Item {
-        match input.body {
-            Body::Enum(data) => Item::Enum(ItemEnum {
+        match input.data {
+            Data::Struct(data) => Item::Struct(ItemStruct {
+                attrs: input.attrs,
+                vis: input.vis,
+                struct_token: data.struct_token,
+                ident: input.ident,
+                generics: input.generics,
+                fields: data.fields,
+                semi_token: data.semi_token,
+            }),
+            Data::Enum(data) => Item::Enum(ItemEnum {
                 attrs: input.attrs,
                 vis: input.vis,
                 enum_token: data.enum_token,
@@ -266,14 +275,13 @@
                 brace_token: data.brace_token,
                 variants: data.variants,
             }),
-            Body::Struct(data) => Item::Struct(ItemStruct {
+            Data::Union(data) => Item::Union(ItemUnion {
                 attrs: input.attrs,
                 vis: input.vis,
-                struct_token: data.struct_token,
+                union_token: data.union_token,
                 ident: input.ident,
                 generics: input.generics,
-                data: data.data,
-                semi_token: data.semi_token,
+                fields: data.fields,
             }),
         }
     }
@@ -1026,8 +1034,7 @@
         ident: syn!(Ident) >>
         generics: syn!(Generics) >>
         where_clause: option!(syn!(WhereClause)) >>
-        fields: braces!(call!(Delimited::parse_terminated_with,
-                              Field::parse_struct)) >>
+        fields: syn!(FieldsNamed) >>
         (ItemUnion {
             attrs: attrs,
             vis: vis,
@@ -1037,7 +1044,7 @@
                 where_clause: where_clause,
                 .. generics
             },
-            data: VariantData::Struct(fields.0, fields.1),
+            fields: fields,
         })
     ));
 
@@ -1379,7 +1386,6 @@
 mod printing {
     use super::*;
     use attr::FilterAttrs;
-    use data::VariantData;
     use quote::{ToTokens, Tokens};
 
     impl ToTokens for ItemExternCrate {
@@ -1515,17 +1521,17 @@
             self.struct_token.to_tokens(tokens);
             self.ident.to_tokens(tokens);
             self.generics.to_tokens(tokens);
-            match self.data {
-                VariantData::Struct(..) => {
+            match self.fields {
+                Fields::Named(ref fields) => {
                     self.generics.where_clause.to_tokens(tokens);
-                    self.data.to_tokens(tokens);
+                    fields.to_tokens(tokens);
                 }
-                VariantData::Tuple(..) => {
-                    self.data.to_tokens(tokens);
+                Fields::Unnamed(ref fields) => {
+                    fields.to_tokens(tokens);
                     self.generics.where_clause.to_tokens(tokens);
                     TokensOrDefault(&self.semi_token).to_tokens(tokens);
                 }
-                VariantData::Unit => {
+                Fields::Unit => {
                     self.generics.where_clause.to_tokens(tokens);
                     TokensOrDefault(&self.semi_token).to_tokens(tokens);
                 }
@@ -1541,9 +1547,7 @@
             self.ident.to_tokens(tokens);
             self.generics.to_tokens(tokens);
             self.generics.where_clause.to_tokens(tokens);
-            // XXX: Should we handle / complain when using a
-            // non-VariantData::Struct Variant in Union?
-            self.data.to_tokens(tokens);
+            self.fields.to_tokens(tokens);
         }
     }
 
diff --git a/src/lib.rs b/src/lib.rs
index 56c3be0..992d547 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,7 +25,7 @@
 pub use attr::{AttrStyle, Attribute, MetaItem, MetaItemList, MetaNameValue, NestedMetaItem};
 
 mod data;
-pub use data::{Field, Variant, VariantData, VisCrate, VisPublic, VisRestricted, Visibility};
+pub use data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted, Visibility};
 
 mod expr;
 pub use expr::{Expr, ExprAddrOf, ExprArray, ExprAssign, ExprAssignOp, ExprBinary, ExprBlock,
@@ -76,7 +76,7 @@
 pub use mac::{Macro, MacroDelimiter};
 
 mod derive;
-pub use derive::{Body, BodyEnum, BodyStruct, DeriveInput};
+pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
 
 mod op;
 pub use op::{BinOp, UnOp};
diff --git a/src/parsers.rs b/src/parsers.rs
index 41b36b0..6b2aea1 100644
--- a/src/parsers.rs
+++ b/src/parsers.rs
@@ -356,7 +356,7 @@
 ///             (types, variadic)
 ///         )) >>
 ///         ({
-///             let ((types, variadic), paren_token) = params;
+///             let (paren_token, (types, variadic)) = params;
 ///             VariadicFn {
 ///                 fn_token,
 ///                 paren_token,
@@ -879,8 +879,8 @@
 ///         (Macro {
 ///             name: name,
 ///             bang_token: bang,
-///             paren_token: body.1,
-///             tts: body.0,
+///             paren_token: body.0,
+///             tts: body.1,
 ///         })
 ///     ));
 /// }