Combine Expr and ExprKind
diff --git a/src/expr.rs b/src/expr.rs
index 8682f6a..780d090 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -5,36 +5,19 @@
 #[cfg(feature = "full")]
 use std::hash::{Hash, Hasher};
 
-ast_struct! {
-    /// An expression.
-    pub struct Expr {
-        /// Attributes tagged on the expression.
-        pub attrs: Vec<Attribute>,
-
-        /// Type of the expression.
-        pub node: ExprKind,
-    }
-}
-
-impl From<ExprKind> for Expr {
-    fn from(node: ExprKind) -> Expr {
-        Expr {
-            node: node,
-            attrs: Vec::new(),
-        }
-    }
-}
-
 ast_enum_of_structs! {
-    pub enum ExprKind {
+    /// An expression.
+    pub enum Expr {
         /// A `box x` expression.
         pub Box(ExprBox #full {
+            pub attrs: Vec<Attribute>,
             pub box_token: Token![box],
             pub expr: Box<Expr>,
         }),
 
         /// E.g. 'place <- val' or `in place { val }`.
         pub InPlace(ExprInPlace #full {
+            pub attrs: Vec<Attribute>,
             pub place: Box<Expr>,
             pub kind: InPlaceKind,
             pub value: Box<Expr>,
@@ -42,12 +25,14 @@
 
         /// An array, e.g. `[a, b, c, d]`.
         pub Array(ExprArray #full {
+            pub attrs: Vec<Attribute>,
             pub bracket_token: token::Bracket,
             pub exprs: Delimited<Expr, Token![,]>,
         }),
 
         /// A function call.
         pub Call(ExprCall {
+            pub attrs: Vec<Attribute>,
             pub func: Box<Expr>,
             pub paren_token: token::Paren,
             pub args: Delimited<Expr, Token![,]>,
@@ -58,10 +43,8 @@
         /// The `Ident` is the identifier for the method name.
         /// The vector of `Type`s are the ascripted type parameters for the method
         /// (within the angle brackets).
-        ///
-        /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
-        /// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
         pub MethodCall(ExprMethodCall #full {
+            pub attrs: Vec<Attribute>,
             pub expr: Box<Expr>,
             pub dot_token: Token![.],
             pub method: Ident,
@@ -75,12 +58,14 @@
 
         /// A tuple, e.g. `(a, b, c, d)`.
         pub Tuple(ExprTuple #full {
+            pub attrs: Vec<Attribute>,
             pub paren_token: token::Paren,
             pub args: Delimited<Expr, Token![,]>,
         }),
 
         /// A binary operation, e.g. `a + b`, `a * b`.
         pub Binary(ExprBinary {
+            pub attrs: Vec<Attribute>,
             pub left: Box<Expr>,
             pub op: BinOp,
             pub right: Box<Expr>,
@@ -88,15 +73,20 @@
 
         /// A unary operation, e.g. `!x`, `*x`.
         pub Unary(ExprUnary {
+            pub attrs: Vec<Attribute>,
             pub op: UnOp,
             pub expr: Box<Expr>,
         }),
 
         /// A literal, e.g. `1`, `"foo"`.
-        pub Lit(Lit),
+        pub Lit(ExprLit {
+            pub attrs: Vec<Attribute>,
+            pub lit: Lit,
+        }),
 
         /// A cast, e.g. `foo as f64`.
         pub Cast(ExprCast {
+            pub attrs: Vec<Attribute>,
             pub expr: Box<Expr>,
             pub as_token: Token![as],
             pub ty: Box<Type>,
@@ -104,6 +94,7 @@
 
         /// A type ascription, e.g. `foo: f64`.
         pub Type(ExprType {
+            pub attrs: Vec<Attribute>,
             pub expr: Box<Expr>,
             pub colon_token: Token![:],
             pub ty: Box<Type>,
@@ -113,6 +104,7 @@
         ///
         /// E.g., `if expr { block } else { expr }`
         pub If(ExprIf #full {
+            pub attrs: Vec<Attribute>,
             pub if_token: Token![if],
             pub cond: Box<Expr>,
             pub if_true: Block,
@@ -126,6 +118,7 @@
         ///
         /// This is desugared to a `match` expression.
         pub IfLet(ExprIfLet #full {
+            pub attrs: Vec<Attribute>,
             pub if_token: Token![if],
             pub let_token: Token![let],
             pub pat: Box<Pat>,
@@ -140,6 +133,7 @@
         ///
         /// E.g., `'label: while expr { block }`
         pub While(ExprWhile #full {
+            pub attrs: Vec<Attribute>,
             pub label: Option<Lifetime>,
             pub colon_token: Option<Token![:]>,
             pub while_token: Token![while],
@@ -153,6 +147,7 @@
         ///
         /// This is desugared to a combination of `loop` and `match` expressions.
         pub WhileLet(ExprWhileLet #full {
+            pub attrs: Vec<Attribute>,
             pub label: Option<Lifetime>,
             pub colon_token: Option<Token![:]>,
             pub while_token: Token![while],
@@ -169,6 +164,7 @@
         ///
         /// This is desugared to a combination of `loop` and `match` expressions.
         pub ForLoop(ExprForLoop #full {
+            pub attrs: Vec<Attribute>,
             pub label: Option<Lifetime>,
             pub colon_token: Option<Token![:]>,
             pub for_token: Token![for],
@@ -182,6 +178,7 @@
         ///
         /// E.g. `'label: loop { block }`
         pub Loop(ExprLoop #full {
+            pub attrs: Vec<Attribute>,
             pub label: Option<Lifetime>,
             pub colon_token: Option<Token![:]>,
             pub loop_token: Token![loop],
@@ -190,6 +187,7 @@
 
         /// A `match` block.
         pub Match(ExprMatch #full {
+            pub attrs: Vec<Attribute>,
             pub match_token: Token![match],
             pub expr: Box<Expr>,
             pub brace_token: token::Brace,
@@ -198,6 +196,7 @@
 
         /// A closure (for example, `move |a, b, c| a + b + c`)
         pub Closure(ExprClosure #full {
+            pub attrs: Vec<Attribute>,
             pub capture: CaptureBy,
             pub or1_token: Token![|],
             pub inputs: Delimited<FnArg, Token![,]>,
@@ -208,17 +207,20 @@
 
         /// An unsafe block (`unsafe { ... }`)
         pub Unsafe(ExprUnsafe #full {
+            pub attrs: Vec<Attribute>,
             pub unsafe_token: Token![unsafe],
             pub block: Block,
         }),
 
         /// A block (`{ ... }`)
         pub Block(ExprBlock #full {
+            pub attrs: Vec<Attribute>,
             pub block: Block,
         }),
 
         /// An assignment (`a = foo()`)
         pub Assign(ExprAssign #full {
+            pub attrs: Vec<Attribute>,
             pub left: Box<Expr>,
             pub eq_token: Token![=],
             pub right: Box<Expr>,
@@ -228,6 +230,7 @@
         ///
         /// For example, `a += 1`.
         pub AssignOp(ExprAssignOp #full {
+            pub attrs: Vec<Attribute>,
             pub left: Box<Expr>,
             pub op: BinOp,
             pub right: Box<Expr>,
@@ -236,6 +239,7 @@
         /// Access of a named struct field (`obj.foo`) or unnamed tuple struct
         /// field (`obj.0`).
         pub Field(ExprField #full {
+            pub attrs: Vec<Attribute>,
             pub base: Box<Expr>,
             pub dot_token: Token![.],
             pub member: Member,
@@ -243,6 +247,7 @@
 
         /// An indexing operation (`foo[2]`)
         pub Index(ExprIndex {
+            pub attrs: Vec<Attribute>,
             pub expr: Box<Expr>,
             pub bracket_token: token::Bracket,
             pub index: Box<Expr>,
@@ -250,6 +255,7 @@
 
         /// A range (`1..2`, `1..`, `..2`, `1..=2`, `..=2`)
         pub Range(ExprRange #full {
+            pub attrs: Vec<Attribute>,
             pub from: Option<Box<Expr>>,
             pub limits: RangeLimits,
             pub to: Option<Box<Expr>>,
@@ -261,12 +267,14 @@
         /// Optionally "qualified",
         /// E.g. `<Vec<T> as SomeTrait>::SomeType`.
         pub Path(ExprPath {
+            pub attrs: Vec<Attribute>,
             pub qself: Option<QSelf>,
             pub path: Path,
         }),
 
         /// A referencing operation (`&a` or `&mut a`)
         pub AddrOf(ExprAddrOf #full {
+            pub attrs: Vec<Attribute>,
             pub and_token: Token![&],
             pub mutbl: Mutability,
             pub expr: Box<Expr>,
@@ -274,6 +282,7 @@
 
         /// A `break`, with an optional label to break, and an optional expression
         pub Break(ExprBreak #full {
+            pub attrs: Vec<Attribute>,
             pub break_token: Token![break],
             pub label: Option<Lifetime>,
             pub expr: Option<Box<Expr>>,
@@ -281,24 +290,30 @@
 
         /// A `continue`, with an optional label
         pub Continue(ExprContinue #full {
+            pub attrs: Vec<Attribute>,
             pub continue_token: Token![continue],
             pub label: Option<Lifetime>,
         }),
 
         /// A `return`, with an optional value to be returned
         pub Ret(ExprRet #full {
+            pub attrs: Vec<Attribute>,
             pub return_token: Token![return],
             pub expr: Option<Box<Expr>>,
         }),
 
         /// A macro invocation; pre-expansion
-        pub Macro(Macro),
+        pub Macro(ExprMacro #full {
+            pub attrs: Vec<Attribute>,
+            pub mac: Macro,
+        }),
 
         /// A struct literal expression.
         ///
         /// For example, `Foo {x: 1, y: 2}`, or
         /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
         pub Struct(ExprStruct #full {
+            pub attrs: Vec<Attribute>,
             pub path: Path,
             pub brace_token: token::Brace,
             pub fields: Delimited<FieldValue, Token![,]>,
@@ -311,6 +326,7 @@
         /// For example, `[1; 5]`. The first expression is the element
         /// to be repeated; the second is the number of times to repeat it.
         pub Repeat(ExprRepeat #full {
+            pub attrs: Vec<Attribute>,
             pub bracket_token: token::Bracket,
             pub expr: Box<Expr>,
             pub semi_token: Token![;],
@@ -319,6 +335,7 @@
 
         /// No-op: used solely so we can pretty-print faithfully
         pub Paren(ExprParen {
+            pub attrs: Vec<Attribute>,
             pub paren_token: token::Paren,
             pub expr: Box<Expr>,
         }),
@@ -329,12 +346,14 @@
         /// `TokenStream` which affects the precidence of the resulting
         /// expression. They are used for macro hygiene.
         pub Group(ExprGroup {
+            pub attrs: Vec<Attribute>,
             pub group_token: token::Group,
             pub expr: Box<Expr>,
         }),
 
         /// `expr?`
         pub Try(ExprTry #full {
+            pub attrs: Vec<Attribute>,
             pub expr: Box<Expr>,
             pub question_token: Token![?],
         }),
@@ -343,6 +362,7 @@
         ///
         /// E.g. `do catch { block }`
         pub Catch(ExprCatch #full {
+            pub attrs: Vec<Attribute>,
             pub do_token: Token![do],
             pub catch_token: Token![catch],
             pub block: Block,
@@ -352,12 +372,61 @@
         ///
         /// E.g. `yield expr`
         pub Yield(ExprYield #full {
+            pub attrs: Vec<Attribute>,
             pub yield_token: Token![yield],
             pub expr: Option<Box<Expr>>,
         }),
     }
 }
 
+impl Expr {
+    // Not public API.
+    #[doc(hidden)]
+    pub fn attrs_mut(&mut self) -> &mut Vec<Attribute> {
+        match *self {
+            Expr::Box(ExprBox { ref mut attrs, .. }) |
+            Expr::InPlace(ExprInPlace { ref mut attrs, .. }) |
+            Expr::Array(ExprArray { ref mut attrs, .. }) |
+            Expr::Call(ExprCall { ref mut attrs, .. }) |
+            Expr::MethodCall(ExprMethodCall { ref mut attrs, .. }) |
+            Expr::Tuple(ExprTuple { ref mut attrs, .. }) |
+            Expr::Binary(ExprBinary { ref mut attrs, .. }) |
+            Expr::Unary(ExprUnary { ref mut attrs, .. }) |
+            Expr::Lit(ExprLit { ref mut attrs, .. }) |
+            Expr::Cast(ExprCast { ref mut attrs, .. }) |
+            Expr::Type(ExprType { ref mut attrs, .. }) |
+            Expr::If(ExprIf { ref mut attrs, .. }) |
+            Expr::IfLet(ExprIfLet { ref mut attrs, .. }) |
+            Expr::While(ExprWhile { ref mut attrs, .. }) |
+            Expr::WhileLet(ExprWhileLet { ref mut attrs, .. }) |
+            Expr::ForLoop(ExprForLoop { ref mut attrs, .. }) |
+            Expr::Loop(ExprLoop { ref mut attrs, .. }) |
+            Expr::Match(ExprMatch { ref mut attrs, .. }) |
+            Expr::Closure(ExprClosure { ref mut attrs, .. }) |
+            Expr::Unsafe(ExprUnsafe { ref mut attrs, .. }) |
+            Expr::Block(ExprBlock { ref mut attrs, .. }) |
+            Expr::Assign(ExprAssign { ref mut attrs, .. }) |
+            Expr::AssignOp(ExprAssignOp { ref mut attrs, .. }) |
+            Expr::Field(ExprField { ref mut attrs, .. }) |
+            Expr::Index(ExprIndex { ref mut attrs, .. }) |
+            Expr::Range(ExprRange { ref mut attrs, .. }) |
+            Expr::Path(ExprPath { ref mut attrs, .. }) |
+            Expr::AddrOf(ExprAddrOf { ref mut attrs, .. }) |
+            Expr::Break(ExprBreak { ref mut attrs, .. }) |
+            Expr::Continue(ExprContinue { ref mut attrs, .. }) |
+            Expr::Ret(ExprRet { ref mut attrs, .. }) |
+            Expr::Macro(ExprMacro { ref mut attrs, .. }) |
+            Expr::Struct(ExprStruct { ref mut attrs, .. }) |
+            Expr::Repeat(ExprRepeat { ref mut attrs, .. }) |
+            Expr::Paren(ExprParen { ref mut attrs, .. }) |
+            Expr::Group(ExprGroup { ref mut attrs, .. }) |
+            Expr::Try(ExprTry { ref mut attrs, .. }) |
+            Expr::Catch(ExprCatch { ref mut attrs, .. }) |
+            Expr::Yield(ExprYield { ref mut attrs, .. }) => attrs,
+        }
+    }
+}
+
 #[cfg(feature = "full")]
 ast_enum! {
     /// A struct or tuple struct field accessed in a struct literal or field
@@ -648,17 +717,17 @@
 fn arm_expr_requires_comma(expr: &Expr) -> bool {
     // see https://github.com/rust-lang/rust/blob/eb8f2586e
     //                       /src/libsyntax/parse/classify.rs#L17-L37
-    match expr.node {
-        ExprKind::Unsafe(..)
-        | ExprKind::Block(..)
-        | ExprKind::If(..)
-        | ExprKind::IfLet(..)
-        | ExprKind::Match(..)
-        | ExprKind::While(..)
-        | ExprKind::WhileLet(..)
-        | ExprKind::Loop(..)
-        | ExprKind::ForLoop(..)
-        | ExprKind::Catch(..) => false,
+    match *expr {
+        Expr::Unsafe(..)
+        | Expr::Block(..)
+        | Expr::If(..)
+        | Expr::IfLet(..)
+        | Expr::Match(..)
+        | Expr::While(..)
+        | Expr::WhileLet(..)
+        | Expr::Loop(..)
+        | Expr::ForLoop(..)
+        | Expr::Catch(..) => false,
         _ => true,
     }
 }
@@ -719,22 +788,14 @@
     // Parse an arbitrary expression.
     #[cfg(feature = "full")]
     fn ambiguous_expr(i: Cursor, allow_struct: bool, allow_block: bool) -> PResult<Expr> {
-        map!(
-            i,
-            call!(assign_expr, allow_struct, allow_block),
-            ExprKind::into
-        )
+        call!(i, assign_expr, allow_struct, allow_block)
     }
 
     #[cfg(not(feature = "full"))]
     fn ambiguous_expr(i: Cursor, allow_struct: bool, allow_block: bool) -> PResult<Expr> {
-        map!(
-            i,
-            // NOTE: We intentionally skip assign_expr, placement_expr, and
-            // range_expr, as they are not parsed in non-full mode.
-            call!(or_expr, allow_struct, allow_block),
-            ExprKind::into
-        )
+        // NOTE: We intentionally skip assign_expr, placement_expr, and
+        // range_expr, as they are not parsed in non-full mode.
+        call!(i, or_expr, allow_struct, allow_block)
     }
 
     // Parse a left-associative binary operator.
@@ -744,13 +805,14 @@
             $next: ident,
             $submac: ident!( $($args:tt)* )
         ) => {
-            named!($name(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
+            named!($name(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
                 mut e: call!($next, allow_struct, allow_block) >>
                 many0!(do_parse!(
                     op: $submac!($($args)*) >>
                     rhs: call!($next, allow_struct, true) >>
                     ({
                         e = ExprBinary {
+                            attrs: Vec::new(),
                             left: Box::new(e.into()),
                             op: op,
                             right: Box::new(rhs.into()),
@@ -776,7 +838,7 @@
     //
     // NOTE: This operator is right-associative.
     #[cfg(feature = "full")]
-    named!(assign_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
+    named!(assign_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
         mut e: call!(placement_expr, allow_struct, allow_block) >>
         alt!(
             do_parse!(
@@ -785,6 +847,7 @@
                 rhs: call!(assign_expr, allow_struct, true) >>
                 ({
                     e = ExprAssign {
+                        attrs: Vec::new(),
                         left: Box::new(e.into()),
                         eq_token: eq,
                         right: Box::new(rhs.into()),
@@ -798,6 +861,7 @@
                 rhs: call!(assign_expr, allow_struct, true) >>
                 ({
                     e = ExprAssignOp {
+                        attrs: Vec::new(),
                         left: Box::new(e.into()),
                         op: op,
                         right: Box::new(rhs.into()),
@@ -817,7 +881,7 @@
     //
     // NOTE: This operator is right-associative.
     #[cfg(feature = "full")]
-    named!(placement_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
+    named!(placement_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
         mut e: call!(range_expr, allow_struct, allow_block) >>
         alt!(
             do_parse!(
@@ -826,6 +890,7 @@
                 rhs: call!(placement_expr, allow_struct, true) >>
                 ({
                     e = ExprInPlace {
+                        attrs: Vec::new(),
                         // op: BinOp::Place(larrow),
                         place: Box::new(e.into()),
                         kind: InPlaceKind::Arrow(arrow),
@@ -851,7 +916,7 @@
     // NOTE: The form of ranges which don't include a preceding expression are
     // parsed by `atom_expr`, rather than by this function.
     #[cfg(feature = "full")]
-    named!(range_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
+    named!(range_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
         mut e: call!(or_expr, allow_struct, allow_block) >>
         many0!(do_parse!(
             limits: syn!(RangeLimits) >>
@@ -860,6 +925,7 @@
             hi: option!(call!(or_expr, allow_struct, allow_struct)) >>
             ({
                 e = ExprRange {
+                    attrs: Vec::new(),
                     from: Some(Box::new(e.into())),
                     limits: limits,
                     to: hi.map(|e| Box::new(e.into())),
@@ -977,7 +1043,7 @@
 
     // <unary> as <ty>
     // <unary> : <ty>
-    named!(cast_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
+    named!(cast_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
         mut e: call!(unary_expr, allow_struct, allow_block) >>
         many0!(alt!(
             do_parse!(
@@ -987,6 +1053,7 @@
                 ty: call!(Type::without_plus) >>
                 ({
                     e = ExprCast {
+                        attrs: Vec::new(),
                         expr: Box::new(e.into()),
                         as_token: as_,
                         ty: Box::new(ty),
@@ -1001,6 +1068,7 @@
                 ty: call!(Type::without_plus) >>
                 ({
                     e = ExprType {
+                        attrs: Vec::new(),
                         expr: Box::new(e.into()),
                         colon_token: colon,
                         ty: Box::new(ty),
@@ -1016,11 +1084,12 @@
     // &mut <trailer>
     // box <trailer>
     #[cfg(feature = "full")]
-    named!(unary_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
+    named!(unary_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
         do_parse!(
             op: syn!(UnOp) >>
             expr: call!(unary_expr, allow_struct, true) >>
             (ExprUnary {
+                attrs: Vec::new(),
                 op: op,
                 expr: Box::new(expr.into()),
             }.into())
@@ -1031,6 +1100,7 @@
             mutability: syn!(Mutability) >>
             expr: call!(unary_expr, allow_struct, true) >>
             (ExprAddrOf {
+                attrs: Vec::new(),
                 and_token: and,
                 mutbl: mutability,
                 expr: Box::new(expr.into()),
@@ -1041,6 +1111,7 @@
             box_: keyword!(box) >>
             expr: call!(unary_expr, allow_struct, true) >>
             (ExprBox {
+                attrs: Vec::new(),
                 box_token: box_,
                 expr: Box::new(expr.into()),
             }.into())
@@ -1051,11 +1122,12 @@
 
     // XXX: This duplication is ugly
     #[cfg(not(feature = "full"))]
-    named!(unary_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
+    named!(unary_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
         do_parse!(
             op: syn!(UnOp) >>
             expr: call!(unary_expr, allow_struct, true) >>
             (ExprUnary {
+                attrs: Vec::new(),
                 op: op,
                 expr: Box::new(expr.into()),
             }.into())
@@ -1071,12 +1143,13 @@
     // <atom> [ <expr> ] ...
     // <atom> ? ...
     #[cfg(feature = "full")]
-    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
+    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
         mut e: call!(atom_expr, allow_struct, allow_block) >>
         many0!(alt!(
             tap!(args: and_call => {
                 let (args, paren) = args;
                 e = ExprCall {
+                    attrs: Vec::new(),
                     func: Box::new(e.into()),
                     args: args,
                     paren_token: paren,
@@ -1092,6 +1165,7 @@
             tap!(field: and_field => {
                 let (token, member) = field;
                 e = ExprField {
+                    attrs: Vec::new(),
                     base: Box::new(e.into()),
                     dot_token: token,
                     member: member,
@@ -1101,6 +1175,7 @@
             tap!(i: and_index => {
                 let (i, token) = i;
                 e = ExprIndex {
+                    attrs: Vec::new(),
                     expr: Box::new(e.into()),
                     bracket_token: token,
                     index: Box::new(i),
@@ -1109,6 +1184,7 @@
             |
             tap!(question: punct!(?) => {
                 e = ExprTry {
+                    attrs: Vec::new(),
                     expr: Box::new(e.into()),
                     question_token: question,
                 }.into();
@@ -1119,12 +1195,13 @@
 
     // XXX: Duplication == ugly
     #[cfg(not(feature = "full"))]
-    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> ExprKind, do_parse!(
+    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
         mut e: call!(atom_expr, allow_struct, allow_block) >>
         many0!(alt!(
             tap!(args: and_call => {
                 let (args, paren) = args;
                 e = ExprCall {
+                    attrs: Vec::new(),
                     func: Box::new(e.into()),
                     args: args,
                     paren_token: paren,
@@ -1134,6 +1211,7 @@
             tap!(i: and_index => {
                 let (i, token) = i;
                 e = ExprIndex {
+                    attrs: Vec::new(),
                     expr: Box::new(e.into()),
                     bracket_token: token,
                     index: Box::new(i),
@@ -1146,105 +1224,125 @@
     // Parse all atomic expressions which don't have to worry about precidence
     // interactions, as they are fully contained.
     #[cfg(feature = "full")]
-    named!(atom_expr(allow_struct: bool, allow_block: bool) -> ExprKind, alt!(
-        syn!(ExprGroup) => { ExprKind::Group } // must be placed first
+    named!(atom_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
+        syn!(ExprGroup) => { Expr::Group } // must be placed first
         |
-        syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
+        syn!(ExprLit) => { Expr::Lit } // must be before expr_struct
         |
         // must be before expr_path
-        cond_reduce!(allow_struct, map!(syn!(ExprStruct), ExprKind::Struct))
+        cond_reduce!(allow_struct, map!(syn!(ExprStruct), Expr::Struct))
         |
-        syn!(ExprParen) => { ExprKind::Paren } // must be before expr_tup
+        syn!(ExprParen) => { Expr::Paren } // must be before expr_tup
         |
-        syn!(Macro) => { ExprKind::Macro } // must be before expr_path
+        syn!(ExprMacro) => { Expr::Macro } // must be before expr_path
         |
         call!(expr_break, allow_struct) // must be before expr_path
         |
-        syn!(ExprContinue) => { ExprKind::Continue } // must be before expr_path
+        syn!(ExprContinue) => { Expr::Continue } // must be before expr_path
         |
         call!(expr_ret, allow_struct) // must be before expr_path
         |
         // NOTE: The `in place { expr }` form. `place <- expr` is parsed above.
-        syn!(ExprInPlace) => { ExprKind::InPlace }
+        syn!(ExprInPlace) => { Expr::InPlace }
         |
-        syn!(ExprArray) => { ExprKind::Array }
+        syn!(ExprArray) => { Expr::Array }
         |
-        syn!(ExprTuple) => { ExprKind::Tuple }
+        syn!(ExprTuple) => { Expr::Tuple }
         |
-        syn!(ExprIf) => { ExprKind::If }
+        syn!(ExprIf) => { Expr::If }
         |
-        syn!(ExprIfLet) => { ExprKind::IfLet }
+        syn!(ExprIfLet) => { Expr::IfLet }
         |
-        syn!(ExprWhile) => { ExprKind::While }
+        syn!(ExprWhile) => { Expr::While }
         |
-        syn!(ExprWhileLet) => { ExprKind::WhileLet }
+        syn!(ExprWhileLet) => { Expr::WhileLet }
         |
-        syn!(ExprForLoop) => { ExprKind::ForLoop }
+        syn!(ExprForLoop) => { Expr::ForLoop }
         |
-        syn!(ExprLoop) => { ExprKind::Loop }
+        syn!(ExprLoop) => { Expr::Loop }
         |
-        syn!(ExprMatch) => { ExprKind::Match }
+        syn!(ExprMatch) => { Expr::Match }
         |
-        syn!(ExprCatch) => { ExprKind::Catch }
+        syn!(ExprCatch) => { Expr::Catch }
         |
-        syn!(ExprYield) => { ExprKind::Yield }
+        syn!(ExprYield) => { Expr::Yield }
         |
-        syn!(ExprUnsafe) => { ExprKind::Unsafe }
+        syn!(ExprUnsafe) => { Expr::Unsafe }
         |
         call!(expr_closure, allow_struct)
         |
-        cond_reduce!(allow_block, map!(syn!(ExprBlock), ExprKind::Block))
+        cond_reduce!(allow_block, map!(syn!(ExprBlock), Expr::Block))
         |
         // NOTE: This is the prefix-form of range
         call!(expr_range, allow_struct)
         |
-        syn!(ExprPath) => { ExprKind::Path }
+        syn!(ExprPath) => { Expr::Path }
         |
-        syn!(ExprRepeat) => { ExprKind::Repeat }
+        syn!(ExprRepeat) => { Expr::Repeat }
     ));
 
     #[cfg(not(feature = "full"))]
-    named!(atom_expr(_allow_struct: bool, _allow_block: bool) -> ExprKind, alt!(
-        syn!(ExprGroup) => { ExprKind::Group } // must be placed first
+    named!(atom_expr(_allow_struct: bool, _allow_block: bool) -> Expr, alt!(
+        syn!(ExprGroup) => { Expr::Group } // must be placed first
         |
-        syn!(Lit) => { ExprKind::Lit } // must be before expr_struct
+        syn!(ExprLit) => { Expr::Lit } // must be before expr_struct
         |
-        syn!(ExprParen) => { ExprKind::Paren } // must be before expr_tup
+        syn!(ExprParen) => { Expr::Paren } // must be before expr_tup
         |
-        syn!(Macro) => { ExprKind::Macro } // must be before expr_path
-        |
-        syn!(ExprPath) => { ExprKind::Path }
+        syn!(ExprPath) => { Expr::Path }
     ));
 
     #[cfg(feature = "full")]
     named!(expr_nosemi -> Expr, map!(alt!(
-        syn!(ExprIf) => { ExprKind::If }
+        syn!(ExprIf) => { Expr::If }
         |
-        syn!(ExprIfLet) => { ExprKind::IfLet }
+        syn!(ExprIfLet) => { Expr::IfLet }
         |
-        syn!(ExprWhile) => { ExprKind::While }
+        syn!(ExprWhile) => { Expr::While }
         |
-        syn!(ExprWhileLet) => { ExprKind::WhileLet }
+        syn!(ExprWhileLet) => { Expr::WhileLet }
         |
-        syn!(ExprForLoop) => { ExprKind::ForLoop }
+        syn!(ExprForLoop) => { Expr::ForLoop }
         |
-        syn!(ExprLoop) => { ExprKind::Loop }
+        syn!(ExprLoop) => { Expr::Loop }
         |
-        syn!(ExprMatch) => { ExprKind::Match }
+        syn!(ExprMatch) => { Expr::Match }
         |
-        syn!(ExprCatch) => { ExprKind::Catch }
+        syn!(ExprCatch) => { Expr::Catch }
         |
-        syn!(ExprYield) => { ExprKind::Yield }
+        syn!(ExprYield) => { Expr::Yield }
         |
-        syn!(ExprUnsafe) => { ExprKind::Unsafe }
+        syn!(ExprUnsafe) => { Expr::Unsafe }
         |
-        syn!(ExprBlock) => { ExprKind::Block }
+        syn!(ExprBlock) => { Expr::Block }
     ), Expr::from));
 
+    impl Synom for ExprLit {
+        named!(parse -> Self, do_parse!(
+            lit: syn!(Lit) >>
+            (ExprLit {
+                attrs: Vec::new(),
+                lit: lit,
+            })
+        ));
+    }
+
+    #[cfg(feature = "full")]
+    impl Synom for ExprMacro {
+        named!(parse -> Self, do_parse!(
+            mac: syn!(Macro) >>
+            (ExprMacro {
+                attrs: Vec::new(),
+                mac: mac,
+            })
+        ));
+    }
+
     impl Synom for ExprGroup {
         named!(parse -> Self, do_parse!(
             e: grouped!(syn!(Expr)) >>
             (ExprGroup {
+                attrs: Vec::new(),
                 expr: Box::new(e.0),
                 group_token: e.1,
             })
@@ -1255,6 +1353,7 @@
         named!(parse -> Self, do_parse!(
             e: parens!(syn!(Expr)) >>
             (ExprParen {
+                attrs: Vec::new(),
                 expr: Box::new(e.0),
                 paren_token: e.1,
             })
@@ -1268,17 +1367,16 @@
             place: expr_no_struct >>
             value: braces!(call!(Block::parse_within)) >>
             (ExprInPlace {
+                attrs: Vec::new(),
                 place: Box::new(place),
                 kind: InPlaceKind::In(in_),
-                value: Box::new(Expr {
-                    node: ExprBlock {
-                        block: Block {
-                            stmts: value.0,
-                            brace_token: value.1,
-                        },
-                    }.into(),
+                value: Box::new(ExprBlock {
                     attrs: Vec::new(),
-                }),
+                    block: Block {
+                        stmts: value.0,
+                        brace_token: value.1,
+                    },
+                }.into()),
             })
         ));
     }
@@ -1288,6 +1386,7 @@
         named!(parse -> Self, do_parse!(
             elems: brackets!(call!(Delimited::parse_terminated)) >>
             (ExprArray {
+                attrs: Vec::new(),
                 exprs: elems.0,
                 bracket_token: elems.1,
             })
@@ -1315,10 +1414,14 @@
                 None => (None, None, None, None),
             };
             ExprMethodCall {
+                attrs: Vec::new(),
                 // this expr will get overwritten after being returned
-                expr: Box::new(ExprKind::Lit(Lit {
-                    span: Span::default(),
-                    value: LitKind::Bool(false),
+                expr: Box::new(Expr::Lit(ExprLit {
+                    attrs: Vec::new(),
+                    lit: Lit {
+                        span: Span::default(),
+                        value: LitKind::Bool(false),
+                    },
                 }).into()),
 
                 method: method,
@@ -1338,6 +1441,7 @@
         named!(parse -> Self, do_parse!(
             elems: parens!(call!(Delimited::parse_terminated)) >>
             (ExprTuple {
+                attrs: Vec::new(),
                 args: elems.0,
                 paren_token: elems.1,
             })
@@ -1355,6 +1459,7 @@
             then_block: braces!(call!(Block::parse_within)) >>
             else_block: option!(else_block) >>
             (ExprIfLet {
+                attrs: Vec::new(),
                 pat: Box::new(pat),
                 let_token: let_,
                 eq_token: eq,
@@ -1378,6 +1483,7 @@
             then_block: braces!(call!(Block::parse_within)) >>
             else_block: option!(else_block) >>
             (ExprIf {
+                attrs: Vec::new(),
                 cond: Box::new(cond),
                 if_true: Block {
                     stmts: then_block.0,
@@ -1391,16 +1497,17 @@
     }
 
     #[cfg(feature = "full")]
-    named!(else_block -> (Token![else], ExprKind), do_parse!(
+    named!(else_block -> (Token![else], Expr), do_parse!(
         else_: keyword!(else) >>
         expr: alt!(
-            syn!(ExprIf) => { ExprKind::If }
+            syn!(ExprIf) => { Expr::If }
             |
-            syn!(ExprIfLet) => { ExprKind::IfLet }
+            syn!(ExprIfLet) => { Expr::IfLet }
             |
             do_parse!(
                 else_block: braces!(call!(Block::parse_within)) >>
-                (ExprKind::Block(ExprBlock {
+                (Expr::Block(ExprBlock {
+                    attrs: Vec::new(),
                     block: Block {
                         stmts: else_block.0,
                         brace_token: else_block.1,
@@ -1421,6 +1528,7 @@
             expr: expr_no_struct >>
             loop_block: syn!(Block) >>
             (ExprForLoop {
+                attrs: Vec::new(),
                 for_token: for_,
                 in_token: in_,
                 pat: Box::new(pat),
@@ -1439,6 +1547,7 @@
             loop_: keyword!(loop) >>
             loop_block: syn!(Block) >>
             (ExprLoop {
+                attrs: Vec::new(),
                 loop_token: loop_,
                 body: loop_block,
                 colon_token: lbl.as_ref().map(|p| Token![:]((p.1).0)),
@@ -1456,6 +1565,7 @@
             ({
                 let (arms, brace) = res;
                 ExprMatch {
+                    attrs: Vec::new(),
                     expr: Box::new(obj),
                     match_token: match_,
                     brace_token: brace,
@@ -1472,6 +1582,7 @@
             catch_: keyword!(catch) >>
             catch_block: syn!(Block) >>
             (ExprCatch {
+                attrs: Vec::new(),
                 block: catch_block,
                 do_token: do_,
                 catch_token: catch_,
@@ -1485,6 +1596,7 @@
             yield_: keyword!(yield) >>
             expr: option!(syn!(Expr)) >>
             (ExprYield {
+                attrs: Vec::new(),
                 yield_token: yield_,
                 expr: expr.map(Box::new),
             })
@@ -1521,7 +1633,7 @@
     }
 
     #[cfg(feature = "full")]
-    named!(expr_closure(allow_struct: bool) -> ExprKind, do_parse!(
+    named!(expr_closure(allow_struct: bool) -> Expr, do_parse!(
         capture: syn!(CaptureBy) >>
         or1: punct!(|) >>
         inputs: call!(Delimited::parse_terminated_with, fn_arg) >>
@@ -1532,7 +1644,8 @@
                 ty: syn!(Type) >>
                 body: syn!(Block) >>
                 (ReturnType::Type(arrow, Box::new(ty)),
-                 ExprKind::Block(ExprBlock {
+                 Expr::Block(ExprBlock {
+                     attrs: Vec::new(),
                     block: body,
                 }).into())
             )
@@ -1540,6 +1653,7 @@
             map!(ambiguous_expr!(allow_struct), |e| (ReturnType::Default, e))
         ) >>
         (ExprClosure {
+            attrs: Vec::new(),
             capture: capture,
             or1_token: or1,
             inputs: inputs,
@@ -1574,6 +1688,7 @@
             cond: expr_no_struct >>
             while_block: syn!(Block) >>
             (ExprWhile {
+                attrs: Vec::new(),
                 while_token: while_,
                 colon_token: lbl.as_ref().map(|p| Token![:]((p.1).0)),
                 cond: Box::new(cond),
@@ -1594,6 +1709,7 @@
             value: expr_no_struct >>
             while_block: syn!(Block) >>
             (ExprWhileLet {
+                attrs: Vec::new(),
                 eq_token: eq,
                 let_token: let_,
                 while_token: while_,
@@ -1612,6 +1728,7 @@
             cont: keyword!(continue) >>
             lbl: option!(syn!(Lifetime)) >>
             (ExprContinue {
+                attrs: Vec::new(),
                 continue_token: cont,
                 label: lbl,
             })
@@ -1619,13 +1736,14 @@
     }
 
     #[cfg(feature = "full")]
-    named!(expr_break(allow_struct: bool) -> ExprKind, do_parse!(
+    named!(expr_break(allow_struct: bool) -> Expr, do_parse!(
         break_: keyword!(break) >>
         lbl: option!(syn!(Lifetime)) >>
         // We can't allow blocks after a `break` expression when we wouldn't
         // allow structs, as this expression is ambiguous.
         val: opt_ambiguous_expr!(allow_struct) >>
         (ExprBreak {
+            attrs: Vec::new(),
             label: lbl,
             expr: val.map(Box::new),
             break_token: break_,
@@ -1633,7 +1751,7 @@
     ));
 
     #[cfg(feature = "full")]
-    named!(expr_ret(allow_struct: bool) -> ExprKind, do_parse!(
+    named!(expr_ret(allow_struct: bool) -> Expr, do_parse!(
         return_: keyword!(return) >>
         // NOTE: return is greedy and eats blocks after it even when in a
         // position where structs are not allowed, such as in if statement
@@ -1642,6 +1760,7 @@
         // if return { println!("A") } {} // Prints "A"
         ret_value: option!(ambiguous_expr!(allow_struct)) >>
         (ExprRet {
+            attrs: Vec::new(),
             expr: ret_value.map(Box::new),
             return_token: return_,
         }.into())
@@ -1671,6 +1790,7 @@
                     None => (None, None),
                 };
                 ExprStruct {
+                    attrs: Vec::new(),
                     brace_token: brace,
                     path: path,
                     fields: fields,
@@ -1699,7 +1819,11 @@
             |
             map!(syn!(Ident), |name| FieldValue {
                 member: Member::Named(name),
-                expr: ExprKind::Path(ExprPath { qself: None, path: name.into() }).into(),
+                expr: Expr::Path(ExprPath {
+                    attrs: Vec::new(),
+                    qself: None,
+                    path: name.into(),
+                }).into(),
                 is_shorthand: true,
                 attrs: Vec::new(),
                 colon_token: None,
@@ -1717,6 +1841,7 @@
                 (value, semi, times)
             )) >>
             (ExprRepeat {
+                attrs: Vec::new(),
                 expr: Box::new((data.0).0),
                 amt: Box::new((data.0).2),
                 bracket_token: data.1,
@@ -1731,6 +1856,7 @@
             unsafe_: keyword!(unsafe) >>
             b: syn!(Block) >>
             (ExprUnsafe {
+                attrs: Vec::new(),
                 unsafe_token: unsafe_,
                 block: b,
             })
@@ -1742,16 +1868,22 @@
         named!(parse -> Self, do_parse!(
             b: syn!(Block) >>
             (ExprBlock {
+                attrs: Vec::new(),
                 block: b,
             })
         ));
     }
 
     #[cfg(feature = "full")]
-    named!(expr_range(allow_struct: bool) -> ExprKind, do_parse!(
+    named!(expr_range(allow_struct: bool) -> Expr, do_parse!(
         limits: syn!(RangeLimits) >>
         hi: opt_ambiguous_expr!(allow_struct) >>
-        (ExprRange { from: None, to: hi.map(Box::new), limits: limits }.into())
+        (ExprRange {
+            attrs: Vec::new(),
+            from: None,
+            to: hi.map(Box::new),
+            limits: limits,
+        }.into())
     ));
 
     #[cfg(feature = "full")]
@@ -1771,6 +1903,7 @@
         named!(parse -> Self, do_parse!(
             pair: qpath >>
             (ExprPath {
+                attrs: Vec::new(),
                 qself: pair.0,
                 path: pair.1,
             })
@@ -1802,7 +1935,7 @@
                 attrs: many0!(Attribute::parse_outer) >>
                 mut e: syn!(Expr) >>
                 ({
-                    e.attrs = attrs;
+                    *e.attrs_mut() = attrs;
                     Stmt::Expr(Box::new(e))
                 })
             )) >>
@@ -1888,7 +2021,7 @@
         not!(punct!(?)) >>
         semi: option!(punct!(;)) >>
         ({
-            e.attrs = attrs;
+            *e.attrs_mut() = attrs;
             if let Some(semi) = semi {
                 Stmt::Semi(Box::new(e), semi)
             } else {
@@ -1903,7 +2036,7 @@
         mut e: syn!(Expr) >>
         semi: punct!(;) >>
         ({
-            e.attrs = attrs;
+            *e.attrs_mut() = attrs;
             Stmt::Semi(Box::new(e), semi)
         })
     ));
@@ -2158,7 +2291,7 @@
     impl Synom for PatLit {
         named!(parse -> Self, do_parse!(
             lit: pat_lit_expr >>
-            (if let ExprKind::Path(_) = lit.node {
+            (if let Expr::Path(_) = lit {
                 return parse_error(); // these need to be parsed by pat_path
             } else {
                 PatLit {
@@ -2186,12 +2319,13 @@
     named!(pat_lit_expr -> Expr, do_parse!(
         neg: option!(punct!(-)) >>
         v: alt!(
-            syn!(Lit) => { ExprKind::Lit }
+            syn!(ExprLit) => { Expr::Lit }
             |
-            syn!(ExprPath) => { ExprKind::Path }
+            syn!(ExprPath) => { Expr::Path }
         ) >>
         (if let Some(neg) = neg {
-            ExprKind::Unary(ExprUnary {
+            Expr::Unary(ExprUnary {
+                attrs: Vec::new(),
                 op: UnOp::Neg(neg),
                 expr: Box::new(v.into())
             }).into()
@@ -2266,7 +2400,7 @@
     // before appending it to `Tokens`.
     #[cfg(feature = "full")]
     fn wrap_bare_struct(tokens: &mut Tokens, e: &Expr) {
-        if let ExprKind::Struct(_) = e.node {
+        if let Expr::Struct(_) = *e {
             token::Paren::default().surround(tokens, |tokens| {
                 e.to_tokens(tokens);
             });
@@ -2275,22 +2409,19 @@
         }
     }
 
-    impl ToTokens for Expr {
-        #[cfg(feature = "full")]
-        fn to_tokens(&self, tokens: &mut Tokens) {
-            tokens.append_all(self.attrs.outer());
-            self.node.to_tokens(tokens)
-        }
+    #[cfg(feature = "full")]
+    fn attrs_to_tokens(attrs: &[Attribute], tokens: &mut Tokens) {
+        tokens.append_all(attrs.outer());
+    }
 
-        #[cfg(not(feature = "full"))]
-        fn to_tokens(&self, tokens: &mut Tokens) {
-            self.node.to_tokens(tokens)
-        }
+    #[cfg(not(feature = "full"))]
+    fn attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut Tokens) {
     }
 
     #[cfg(feature = "full")]
     impl ToTokens for ExprBox {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.box_token.to_tokens(tokens);
             self.expr.to_tokens(tokens);
         }
@@ -2299,6 +2430,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprInPlace {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             match self.kind {
                 InPlaceKind::Arrow(ref arrow) => {
                     self.place.to_tokens(tokens);
@@ -2310,7 +2442,7 @@
                     self.place.to_tokens(tokens);
                     // NOTE: The second operand must be in a block, add one if
                     // it is not present.
-                    if let ExprKind::Block(_) = self.value.node {
+                    if let Expr::Block(_) = *self.value {
                         self.value.to_tokens(tokens);
                     } else {
                         token::Brace::default().surround(tokens, |tokens| {
@@ -2325,6 +2457,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprArray {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.bracket_token.surround(tokens, |tokens| {
                 self.exprs.to_tokens(tokens);
             })
@@ -2333,6 +2466,7 @@
 
     impl ToTokens for ExprCall {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.func.to_tokens(tokens);
             self.paren_token.surround(tokens, |tokens| {
                 self.args.to_tokens(tokens);
@@ -2343,6 +2477,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprMethodCall {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.expr.to_tokens(tokens);
             self.dot_token.to_tokens(tokens);
             self.method.to_tokens(tokens);
@@ -2361,6 +2496,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprTuple {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.paren_token.surround(tokens, |tokens| {
                 self.args.to_tokens(tokens);
                 // If we only have one argument, we need a trailing comma to
@@ -2374,6 +2510,7 @@
 
     impl ToTokens for ExprBinary {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.left.to_tokens(tokens);
             self.op.to_tokens(tokens);
             self.right.to_tokens(tokens);
@@ -2382,13 +2519,22 @@
 
     impl ToTokens for ExprUnary {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.op.to_tokens(tokens);
             self.expr.to_tokens(tokens);
         }
     }
 
+    impl ToTokens for ExprLit {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
+            self.lit.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for ExprCast {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.expr.to_tokens(tokens);
             self.as_token.to_tokens(tokens);
             self.ty.to_tokens(tokens);
@@ -2397,6 +2543,7 @@
 
     impl ToTokens for ExprType {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.expr.to_tokens(tokens);
             self.colon_token.to_tokens(tokens);
             self.ty.to_tokens(tokens);
@@ -2414,8 +2561,8 @@
 
             // If we are not one of the valid expressions to exist in an else
             // clause, wrap ourselves in a block.
-            match if_false.node {
-                ExprKind::If(_) | ExprKind::IfLet(_) | ExprKind::Block(_) => {
+            match **if_false {
+                Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
                     if_false.to_tokens(tokens);
                 }
                 _ => {
@@ -2430,6 +2577,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprIf {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.if_token.to_tokens(tokens);
             wrap_bare_struct(tokens, &self.cond);
             self.if_true.to_tokens(tokens);
@@ -2440,6 +2588,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprIfLet {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.if_token.to_tokens(tokens);
             self.let_token.to_tokens(tokens);
             self.pat.to_tokens(tokens);
@@ -2453,6 +2602,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprWhile {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             if self.label.is_some() {
                 self.label.to_tokens(tokens);
                 TokensOrDefault(&self.colon_token).to_tokens(tokens);
@@ -2466,6 +2616,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprWhileLet {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             if self.label.is_some() {
                 self.label.to_tokens(tokens);
                 TokensOrDefault(&self.colon_token).to_tokens(tokens);
@@ -2482,6 +2633,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprForLoop {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             if self.label.is_some() {
                 self.label.to_tokens(tokens);
                 TokensOrDefault(&self.colon_token).to_tokens(tokens);
@@ -2497,6 +2649,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprLoop {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             if self.label.is_some() {
                 self.label.to_tokens(tokens);
                 TokensOrDefault(&self.colon_token).to_tokens(tokens);
@@ -2509,6 +2662,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprMatch {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.match_token.to_tokens(tokens);
             wrap_bare_struct(tokens, &self.expr);
             self.brace_token.surround(tokens, |tokens| {
@@ -2528,6 +2682,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprCatch {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.do_token.to_tokens(tokens);
             self.catch_token.to_tokens(tokens);
             self.block.to_tokens(tokens);
@@ -2537,6 +2692,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprYield {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.yield_token.to_tokens(tokens);
             self.expr.to_tokens(tokens);
         }
@@ -2545,6 +2701,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprClosure {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.capture.to_tokens(tokens);
             self.or1_token.to_tokens(tokens);
             for item in self.inputs.iter() {
@@ -2569,6 +2726,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprUnsafe {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.unsafe_token.to_tokens(tokens);
             self.block.to_tokens(tokens);
         }
@@ -2577,6 +2735,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprBlock {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.block.to_tokens(tokens);
         }
     }
@@ -2584,6 +2743,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprAssign {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.left.to_tokens(tokens);
             self.eq_token.to_tokens(tokens);
             self.right.to_tokens(tokens);
@@ -2593,6 +2753,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprAssignOp {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.left.to_tokens(tokens);
             self.op.to_tokens(tokens);
             self.right.to_tokens(tokens);
@@ -2602,6 +2763,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprField {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.base.to_tokens(tokens);
             self.dot_token.to_tokens(tokens);
             self.member.to_tokens(tokens);
@@ -2630,6 +2792,7 @@
 
     impl ToTokens for ExprIndex {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.expr.to_tokens(tokens);
             self.bracket_token.surround(tokens, |tokens| {
                 self.index.to_tokens(tokens);
@@ -2640,6 +2803,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprRange {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.from.to_tokens(tokens);
             match self.limits {
                 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
@@ -2651,6 +2815,7 @@
 
     impl ToTokens for ExprPath {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
         }
     }
@@ -2658,6 +2823,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprAddrOf {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.and_token.to_tokens(tokens);
             self.mutbl.to_tokens(tokens);
             self.expr.to_tokens(tokens);
@@ -2667,6 +2833,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprBreak {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.break_token.to_tokens(tokens);
             self.label.to_tokens(tokens);
             self.expr.to_tokens(tokens);
@@ -2676,6 +2843,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprContinue {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.continue_token.to_tokens(tokens);
             self.label.to_tokens(tokens);
         }
@@ -2684,14 +2852,24 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprRet {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.return_token.to_tokens(tokens);
             self.expr.to_tokens(tokens);
         }
     }
 
     #[cfg(feature = "full")]
+    impl ToTokens for ExprMacro {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
+            self.mac.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
     impl ToTokens for ExprStruct {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.path.to_tokens(tokens);
             self.brace_token.surround(tokens, |tokens| {
                 self.fields.to_tokens(tokens);
@@ -2706,6 +2884,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprRepeat {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.bracket_token.surround(tokens, |tokens| {
                 self.expr.to_tokens(tokens);
                 self.semi_token.to_tokens(tokens);
@@ -2716,6 +2895,7 @@
 
     impl ToTokens for ExprGroup {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.group_token.surround(tokens, |tokens| {
                 self.expr.to_tokens(tokens);
             });
@@ -2724,6 +2904,7 @@
 
     impl ToTokens for ExprParen {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            attrs_to_tokens(&self.attrs, tokens);
             self.paren_token.surround(tokens, |tokens| {
                 self.expr.to_tokens(tokens);
             });
@@ -2733,6 +2914,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprTry {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.expr.to_tokens(tokens);
             self.question_token.to_tokens(tokens);
         }
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index 3c7cefc..cdc1a47 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -130,10 +130,12 @@
 
 fn fold_expr_index(&mut self, i: ExprIndex) -> ExprIndex { fold_expr_index(self, i) }
 
-fn fold_expr_kind(&mut self, i: ExprKind) -> ExprKind { fold_expr_kind(self, i) }
+fn fold_expr_lit(&mut self, i: ExprLit) -> ExprLit { fold_expr_lit(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn fold_expr_loop(&mut self, i: ExprLoop) -> ExprLoop { fold_expr_loop(self, i) }
 # [ cfg ( feature = "full" ) ]
+fn fold_expr_macro(&mut self, i: ExprMacro) -> ExprMacro { fold_expr_macro(self, i) }
+# [ cfg ( feature = "full" ) ]
 fn fold_expr_match(&mut self, i: ExprMatch) -> ExprMatch { fold_expr_match(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn fold_expr_method_call(&mut self, i: ExprMethodCall) -> ExprMethodCall { fold_expr_method_call(self, i) }
@@ -793,182 +795,7 @@
 }
 
 pub fn fold_expr<V: Folder + ?Sized>(_visitor: &mut V, _i: Expr) -> Expr {
-    Expr {
-        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
-        node: _visitor.fold_expr_kind(_i . node),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_addr_of<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprAddrOf) -> ExprAddrOf {
-    ExprAddrOf {
-        and_token: Token ! [ & ](tokens_helper(_visitor, &(_i . and_token).0)),
-        mutbl: _visitor.fold_mutability(_i . mutbl),
-        expr: Box::new(_visitor.fold_expr(* _i . expr)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_array<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprArray) -> ExprArray {
-    ExprArray {
-        bracket_token: Bracket(tokens_helper(_visitor, &(_i . bracket_token).0)),
-        exprs: FoldHelper::lift(_i . exprs, |it| { _visitor.fold_expr(it) }),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_assign<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprAssign) -> ExprAssign {
-    ExprAssign {
-        left: Box::new(_visitor.fold_expr(* _i . left)),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i . eq_token).0)),
-        right: Box::new(_visitor.fold_expr(* _i . right)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_assign_op<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprAssignOp) -> ExprAssignOp {
-    ExprAssignOp {
-        left: Box::new(_visitor.fold_expr(* _i . left)),
-        op: _visitor.fold_bin_op(_i . op),
-        right: Box::new(_visitor.fold_expr(* _i . right)),
-    }
-}
-
-pub fn fold_expr_binary<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBinary) -> ExprBinary {
-    ExprBinary {
-        left: Box::new(_visitor.fold_expr(* _i . left)),
-        op: _visitor.fold_bin_op(_i . op),
-        right: Box::new(_visitor.fold_expr(* _i . right)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_block<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBlock) -> ExprBlock {
-    ExprBlock {
-        block: _visitor.fold_block(_i . block),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_box<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBox) -> ExprBox {
-    ExprBox {
-        box_token: Token ! [ box ](tokens_helper(_visitor, &(_i . box_token).0)),
-        expr: Box::new(_visitor.fold_expr(* _i . expr)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_break<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBreak) -> ExprBreak {
-    ExprBreak {
-        break_token: Token ! [ break ](tokens_helper(_visitor, &(_i . break_token).0)),
-        label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
-        expr: (_i . expr).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
-    }
-}
-
-pub fn fold_expr_call<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprCall) -> ExprCall {
-    ExprCall {
-        func: Box::new(_visitor.fold_expr(* _i . func)),
-        paren_token: Paren(tokens_helper(_visitor, &(_i . paren_token).0)),
-        args: FoldHelper::lift(_i . args, |it| { _visitor.fold_expr(it) }),
-    }
-}
-
-pub fn fold_expr_cast<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprCast) -> ExprCast {
-    ExprCast {
-        expr: Box::new(_visitor.fold_expr(* _i . expr)),
-        as_token: Token ! [ as ](tokens_helper(_visitor, &(_i . as_token).0)),
-        ty: Box::new(_visitor.fold_type(* _i . ty)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_catch<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprCatch) -> ExprCatch {
-    ExprCatch {
-        do_token: Token ! [ do ](tokens_helper(_visitor, &(_i . do_token).0)),
-        catch_token: Token ! [ catch ](tokens_helper(_visitor, &(_i . catch_token).0)),
-        block: _visitor.fold_block(_i . block),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_closure<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprClosure) -> ExprClosure {
-    ExprClosure {
-        capture: _visitor.fold_capture_by(_i . capture),
-        or1_token: Token ! [ | ](tokens_helper(_visitor, &(_i . or1_token).0)),
-        inputs: FoldHelper::lift(_i . inputs, |it| { _visitor.fold_fn_arg(it) }),
-        or2_token: Token ! [ | ](tokens_helper(_visitor, &(_i . or2_token).0)),
-        output: _visitor.fold_return_type(_i . output),
-        body: Box::new(_visitor.fold_expr(* _i . body)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_continue<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprContinue) -> ExprContinue {
-    ExprContinue {
-        continue_token: Token ! [ continue ](tokens_helper(_visitor, &(_i . continue_token).0)),
-        label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_field<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprField) -> ExprField {
-    ExprField {
-        base: Box::new(_visitor.fold_expr(* _i . base)),
-        dot_token: Token ! [ . ](tokens_helper(_visitor, &(_i . dot_token).0)),
-        member: _visitor.fold_member(_i . member),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_for_loop<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprForLoop) -> ExprForLoop {
-    ExprForLoop {
-        label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
-        colon_token: (_i . colon_token).map(|it| { Token ! [ : ](tokens_helper(_visitor, &(it).0)) }),
-        for_token: Token ! [ for ](tokens_helper(_visitor, &(_i . for_token).0)),
-        pat: Box::new(_visitor.fold_pat(* _i . pat)),
-        in_token: Token ! [ in ](tokens_helper(_visitor, &(_i . in_token).0)),
-        expr: Box::new(_visitor.fold_expr(* _i . expr)),
-        body: _visitor.fold_block(_i . body),
-    }
-}
-
-pub fn fold_expr_group<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprGroup) -> ExprGroup {
-    ExprGroup {
-        group_token: Group(tokens_helper(_visitor, &(_i . group_token).0)),
-        expr: Box::new(_visitor.fold_expr(* _i . expr)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_if<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprIf) -> ExprIf {
-    ExprIf {
-        if_token: Token ! [ if ](tokens_helper(_visitor, &(_i . if_token).0)),
-        cond: Box::new(_visitor.fold_expr(* _i . cond)),
-        if_true: _visitor.fold_block(_i . if_true),
-        else_token: (_i . else_token).map(|it| { Token ! [ else ](tokens_helper(_visitor, &(it).0)) }),
-        if_false: (_i . if_false).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_if_let<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprIfLet) -> ExprIfLet {
-    ExprIfLet {
-        if_token: Token ! [ if ](tokens_helper(_visitor, &(_i . if_token).0)),
-        let_token: Token ! [ let ](tokens_helper(_visitor, &(_i . let_token).0)),
-        pat: Box::new(_visitor.fold_pat(* _i . pat)),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i . eq_token).0)),
-        expr: Box::new(_visitor.fold_expr(* _i . expr)),
-        if_true: _visitor.fold_block(_i . if_true),
-        else_token: (_i . else_token).map(|it| { Token ! [ else ](tokens_helper(_visitor, &(it).0)) }),
-        if_false: (_i . if_false).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_expr_in_place<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprInPlace) -> ExprInPlace {
-    ExprInPlace {
-        place: Box::new(_visitor.fold_expr(* _i . place)),
-        kind: _visitor.fold_in_place_kind(_i . kind),
-        value: Box::new(_visitor.fold_expr(* _i . value)),
-    }
-}
-
-pub fn fold_expr_index<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprIndex) -> ExprIndex {
-    ExprIndex {
-        expr: Box::new(_visitor.fold_expr(* _i . expr)),
-        bracket_token: Bracket(tokens_helper(_visitor, &(_i . bracket_token).0)),
-        index: Box::new(_visitor.fold_expr(* _i . index)),
-    }
-}
-
-pub fn fold_expr_kind<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprKind) -> ExprKind {
-    use ::ExprKind::*;
+    use ::Expr::*;
     match _i {
         Box(_binding_0, ) => {
             Box (
@@ -1012,7 +839,7 @@
         }
         Lit(_binding_0, ) => {
             Lit (
-                _visitor.fold_lit(_binding_0),
+                _visitor.fold_expr_lit(_binding_0),
             )
         }
         Cast(_binding_0, ) => {
@@ -1127,7 +954,7 @@
         }
         Macro(_binding_0, ) => {
             Macro (
-                _visitor.fold_macro(_binding_0),
+                full!(_visitor.fold_expr_macro(_binding_0)),
             )
         }
         Struct(_binding_0, ) => {
@@ -1168,8 +995,204 @@
     }
 }
 # [ cfg ( feature = "full" ) ]
+pub fn fold_expr_addr_of<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprAddrOf) -> ExprAddrOf {
+    ExprAddrOf {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        and_token: Token ! [ & ](tokens_helper(_visitor, &(_i . and_token).0)),
+        mutbl: _visitor.fold_mutability(_i . mutbl),
+        expr: Box::new(_visitor.fold_expr(* _i . expr)),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_array<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprArray) -> ExprArray {
+    ExprArray {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        bracket_token: Bracket(tokens_helper(_visitor, &(_i . bracket_token).0)),
+        exprs: FoldHelper::lift(_i . exprs, |it| { _visitor.fold_expr(it) }),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_assign<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprAssign) -> ExprAssign {
+    ExprAssign {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        left: Box::new(_visitor.fold_expr(* _i . left)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i . eq_token).0)),
+        right: Box::new(_visitor.fold_expr(* _i . right)),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_assign_op<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprAssignOp) -> ExprAssignOp {
+    ExprAssignOp {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        left: Box::new(_visitor.fold_expr(* _i . left)),
+        op: _visitor.fold_bin_op(_i . op),
+        right: Box::new(_visitor.fold_expr(* _i . right)),
+    }
+}
+
+pub fn fold_expr_binary<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBinary) -> ExprBinary {
+    ExprBinary {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        left: Box::new(_visitor.fold_expr(* _i . left)),
+        op: _visitor.fold_bin_op(_i . op),
+        right: Box::new(_visitor.fold_expr(* _i . right)),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_block<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBlock) -> ExprBlock {
+    ExprBlock {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        block: _visitor.fold_block(_i . block),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_box<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBox) -> ExprBox {
+    ExprBox {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        box_token: Token ! [ box ](tokens_helper(_visitor, &(_i . box_token).0)),
+        expr: Box::new(_visitor.fold_expr(* _i . expr)),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_break<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBreak) -> ExprBreak {
+    ExprBreak {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        break_token: Token ! [ break ](tokens_helper(_visitor, &(_i . break_token).0)),
+        label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
+        expr: (_i . expr).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
+    }
+}
+
+pub fn fold_expr_call<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprCall) -> ExprCall {
+    ExprCall {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        func: Box::new(_visitor.fold_expr(* _i . func)),
+        paren_token: Paren(tokens_helper(_visitor, &(_i . paren_token).0)),
+        args: FoldHelper::lift(_i . args, |it| { _visitor.fold_expr(it) }),
+    }
+}
+
+pub fn fold_expr_cast<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprCast) -> ExprCast {
+    ExprCast {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        expr: Box::new(_visitor.fold_expr(* _i . expr)),
+        as_token: Token ! [ as ](tokens_helper(_visitor, &(_i . as_token).0)),
+        ty: Box::new(_visitor.fold_type(* _i . ty)),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_catch<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprCatch) -> ExprCatch {
+    ExprCatch {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        do_token: Token ! [ do ](tokens_helper(_visitor, &(_i . do_token).0)),
+        catch_token: Token ! [ catch ](tokens_helper(_visitor, &(_i . catch_token).0)),
+        block: _visitor.fold_block(_i . block),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_closure<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprClosure) -> ExprClosure {
+    ExprClosure {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        capture: _visitor.fold_capture_by(_i . capture),
+        or1_token: Token ! [ | ](tokens_helper(_visitor, &(_i . or1_token).0)),
+        inputs: FoldHelper::lift(_i . inputs, |it| { _visitor.fold_fn_arg(it) }),
+        or2_token: Token ! [ | ](tokens_helper(_visitor, &(_i . or2_token).0)),
+        output: _visitor.fold_return_type(_i . output),
+        body: Box::new(_visitor.fold_expr(* _i . body)),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_continue<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprContinue) -> ExprContinue {
+    ExprContinue {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        continue_token: Token ! [ continue ](tokens_helper(_visitor, &(_i . continue_token).0)),
+        label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_field<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprField) -> ExprField {
+    ExprField {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        base: Box::new(_visitor.fold_expr(* _i . base)),
+        dot_token: Token ! [ . ](tokens_helper(_visitor, &(_i . dot_token).0)),
+        member: _visitor.fold_member(_i . member),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_for_loop<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprForLoop) -> ExprForLoop {
+    ExprForLoop {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
+        colon_token: (_i . colon_token).map(|it| { Token ! [ : ](tokens_helper(_visitor, &(it).0)) }),
+        for_token: Token ! [ for ](tokens_helper(_visitor, &(_i . for_token).0)),
+        pat: Box::new(_visitor.fold_pat(* _i . pat)),
+        in_token: Token ! [ in ](tokens_helper(_visitor, &(_i . in_token).0)),
+        expr: Box::new(_visitor.fold_expr(* _i . expr)),
+        body: _visitor.fold_block(_i . body),
+    }
+}
+
+pub fn fold_expr_group<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprGroup) -> ExprGroup {
+    ExprGroup {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        group_token: Group(tokens_helper(_visitor, &(_i . group_token).0)),
+        expr: Box::new(_visitor.fold_expr(* _i . expr)),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_if<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprIf) -> ExprIf {
+    ExprIf {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        if_token: Token ! [ if ](tokens_helper(_visitor, &(_i . if_token).0)),
+        cond: Box::new(_visitor.fold_expr(* _i . cond)),
+        if_true: _visitor.fold_block(_i . if_true),
+        else_token: (_i . else_token).map(|it| { Token ! [ else ](tokens_helper(_visitor, &(it).0)) }),
+        if_false: (_i . if_false).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_if_let<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprIfLet) -> ExprIfLet {
+    ExprIfLet {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        if_token: Token ! [ if ](tokens_helper(_visitor, &(_i . if_token).0)),
+        let_token: Token ! [ let ](tokens_helper(_visitor, &(_i . let_token).0)),
+        pat: Box::new(_visitor.fold_pat(* _i . pat)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i . eq_token).0)),
+        expr: Box::new(_visitor.fold_expr(* _i . expr)),
+        if_true: _visitor.fold_block(_i . if_true),
+        else_token: (_i . else_token).map(|it| { Token ! [ else ](tokens_helper(_visitor, &(it).0)) }),
+        if_false: (_i . if_false).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
+    }
+}
+# [ cfg ( feature = "full" ) ]
+pub fn fold_expr_in_place<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprInPlace) -> ExprInPlace {
+    ExprInPlace {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        place: Box::new(_visitor.fold_expr(* _i . place)),
+        kind: _visitor.fold_in_place_kind(_i . kind),
+        value: Box::new(_visitor.fold_expr(* _i . value)),
+    }
+}
+
+pub fn fold_expr_index<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprIndex) -> ExprIndex {
+    ExprIndex {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        expr: Box::new(_visitor.fold_expr(* _i . expr)),
+        bracket_token: Bracket(tokens_helper(_visitor, &(_i . bracket_token).0)),
+        index: Box::new(_visitor.fold_expr(* _i . index)),
+    }
+}
+
+pub fn fold_expr_lit<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprLit) -> ExprLit {
+    ExprLit {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        lit: _visitor.fold_lit(_i . lit),
+    }
+}
+# [ cfg ( feature = "full" ) ]
 pub fn fold_expr_loop<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprLoop) -> ExprLoop {
     ExprLoop {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
         colon_token: (_i . colon_token).map(|it| { Token ! [ : ](tokens_helper(_visitor, &(it).0)) }),
         loop_token: Token ! [ loop ](tokens_helper(_visitor, &(_i . loop_token).0)),
@@ -1177,8 +1200,16 @@
     }
 }
 # [ cfg ( feature = "full" ) ]
+pub fn fold_expr_macro<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprMacro) -> ExprMacro {
+    ExprMacro {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        mac: _visitor.fold_macro(_i . mac),
+    }
+}
+# [ cfg ( feature = "full" ) ]
 pub fn fold_expr_match<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprMatch) -> ExprMatch {
     ExprMatch {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         match_token: Token ! [ match ](tokens_helper(_visitor, &(_i . match_token).0)),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
         brace_token: Brace(tokens_helper(_visitor, &(_i . brace_token).0)),
@@ -1188,6 +1219,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_method_call<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprMethodCall) -> ExprMethodCall {
     ExprMethodCall {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
         dot_token: Token ! [ . ](tokens_helper(_visitor, &(_i . dot_token).0)),
         method: _visitor.fold_ident(_i . method),
@@ -1202,6 +1234,7 @@
 
 pub fn fold_expr_paren<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprParen) -> ExprParen {
     ExprParen {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         paren_token: Paren(tokens_helper(_visitor, &(_i . paren_token).0)),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
     }
@@ -1209,6 +1242,7 @@
 
 pub fn fold_expr_path<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprPath) -> ExprPath {
     ExprPath {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         qself: (_i . qself).map(|it| { _visitor.fold_qself(it) }),
         path: _visitor.fold_path(_i . path),
     }
@@ -1216,6 +1250,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_range<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprRange) -> ExprRange {
     ExprRange {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         from: (_i . from).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         limits: _visitor.fold_range_limits(_i . limits),
         to: (_i . to).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
@@ -1224,6 +1259,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_repeat<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprRepeat) -> ExprRepeat {
     ExprRepeat {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         bracket_token: Bracket(tokens_helper(_visitor, &(_i . bracket_token).0)),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
         semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i . semi_token).0)),
@@ -1233,6 +1269,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_ret<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprRet) -> ExprRet {
     ExprRet {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         return_token: Token ! [ return ](tokens_helper(_visitor, &(_i . return_token).0)),
         expr: (_i . expr).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
     }
@@ -1240,6 +1277,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_struct<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprStruct) -> ExprStruct {
     ExprStruct {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         path: _visitor.fold_path(_i . path),
         brace_token: Brace(tokens_helper(_visitor, &(_i . brace_token).0)),
         fields: FoldHelper::lift(_i . fields, |it| { _visitor.fold_field_value(it) }),
@@ -1250,6 +1288,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_try<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprTry) -> ExprTry {
     ExprTry {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
         question_token: Token ! [ ? ](tokens_helper(_visitor, &(_i . question_token).0)),
     }
@@ -1257,6 +1296,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_tuple<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprTuple) -> ExprTuple {
     ExprTuple {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         paren_token: Paren(tokens_helper(_visitor, &(_i . paren_token).0)),
         args: FoldHelper::lift(_i . args, |it| { _visitor.fold_expr(it) }),
     }
@@ -1264,6 +1304,7 @@
 
 pub fn fold_expr_type<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprType) -> ExprType {
     ExprType {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
         colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i . colon_token).0)),
         ty: Box::new(_visitor.fold_type(* _i . ty)),
@@ -1272,6 +1313,7 @@
 
 pub fn fold_expr_unary<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprUnary) -> ExprUnary {
     ExprUnary {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         op: _visitor.fold_un_op(_i . op),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
     }
@@ -1279,6 +1321,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_unsafe<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprUnsafe) -> ExprUnsafe {
     ExprUnsafe {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         unsafe_token: Token ! [ unsafe ](tokens_helper(_visitor, &(_i . unsafe_token).0)),
         block: _visitor.fold_block(_i . block),
     }
@@ -1286,6 +1329,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_while<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprWhile) -> ExprWhile {
     ExprWhile {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
         colon_token: (_i . colon_token).map(|it| { Token ! [ : ](tokens_helper(_visitor, &(it).0)) }),
         while_token: Token ! [ while ](tokens_helper(_visitor, &(_i . while_token).0)),
@@ -1296,6 +1340,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_while_let<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprWhileLet) -> ExprWhileLet {
     ExprWhileLet {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         label: (_i . label).map(|it| { _visitor.fold_lifetime(it) }),
         colon_token: (_i . colon_token).map(|it| { Token ! [ : ](tokens_helper(_visitor, &(it).0)) }),
         while_token: Token ! [ while ](tokens_helper(_visitor, &(_i . while_token).0)),
@@ -1309,6 +1354,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn fold_expr_yield<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprYield) -> ExprYield {
     ExprYield {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         yield_token: Token ! [ yield ](tokens_helper(_visitor, &(_i . yield_token).0)),
         expr: (_i . expr).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
     }
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index 63f6ae9..c9d7649 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -126,10 +126,12 @@
 
 fn visit_expr_index(&mut self, i: &'ast ExprIndex) { visit_expr_index(self, i) }
 
-fn visit_expr_kind(&mut self, i: &'ast ExprKind) { visit_expr_kind(self, i) }
+fn visit_expr_lit(&mut self, i: &'ast ExprLit) { visit_expr_lit(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_expr_loop(&mut self, i: &'ast ExprLoop) { visit_expr_loop(self, i) }
 # [ cfg ( feature = "full" ) ]
+fn visit_expr_macro(&mut self, i: &'ast ExprMacro) { visit_expr_macro(self, i) }
+# [ cfg ( feature = "full" ) ]
 fn visit_expr_match(&mut self, i: &'ast ExprMatch) { visit_expr_match(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_expr_method_call(&mut self, i: &'ast ExprMethodCall) { visit_expr_method_call(self, i) }
@@ -681,140 +683,7 @@
 }
 
 pub fn visit_expr<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Expr) {
-    for it in & _i . attrs { _visitor.visit_attribute(it) };
-    _visitor.visit_expr_kind(& _i . node);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_addr_of<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAddrOf) {
-    tokens_helper(_visitor, &(& _i . and_token).0);
-    _visitor.visit_mutability(& _i . mutbl);
-    _visitor.visit_expr(& * _i . expr);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_array<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprArray) {
-    tokens_helper(_visitor, &(& _i . bracket_token).0);
-    for el in & _i . exprs { let it = el.item(); _visitor.visit_expr(it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_assign<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAssign) {
-    _visitor.visit_expr(& * _i . left);
-    tokens_helper(_visitor, &(& _i . eq_token).0);
-    _visitor.visit_expr(& * _i . right);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_assign_op<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAssignOp) {
-    _visitor.visit_expr(& * _i . left);
-    _visitor.visit_bin_op(& _i . op);
-    _visitor.visit_expr(& * _i . right);
-}
-
-pub fn visit_expr_binary<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBinary) {
-    _visitor.visit_expr(& * _i . left);
-    _visitor.visit_bin_op(& _i . op);
-    _visitor.visit_expr(& * _i . right);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_block<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBlock) {
-    _visitor.visit_block(& _i . block);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_box<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBox) {
-    tokens_helper(_visitor, &(& _i . box_token).0);
-    _visitor.visit_expr(& * _i . expr);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_break<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBreak) {
-    tokens_helper(_visitor, &(& _i . break_token).0);
-    if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
-    if let Some(ref it) = _i . expr { _visitor.visit_expr(& * * it) };
-}
-
-pub fn visit_expr_call<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCall) {
-    _visitor.visit_expr(& * _i . func);
-    tokens_helper(_visitor, &(& _i . paren_token).0);
-    for el in & _i . args { let it = el.item(); _visitor.visit_expr(it) };
-}
-
-pub fn visit_expr_cast<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCast) {
-    _visitor.visit_expr(& * _i . expr);
-    tokens_helper(_visitor, &(& _i . as_token).0);
-    _visitor.visit_type(& * _i . ty);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_catch<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCatch) {
-    tokens_helper(_visitor, &(& _i . do_token).0);
-    tokens_helper(_visitor, &(& _i . catch_token).0);
-    _visitor.visit_block(& _i . block);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_closure<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprClosure) {
-    _visitor.visit_capture_by(& _i . capture);
-    tokens_helper(_visitor, &(& _i . or1_token).0);
-    for el in & _i . inputs { let it = el.item(); _visitor.visit_fn_arg(it) };
-    tokens_helper(_visitor, &(& _i . or2_token).0);
-    _visitor.visit_return_type(& _i . output);
-    _visitor.visit_expr(& * _i . body);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_continue<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprContinue) {
-    tokens_helper(_visitor, &(& _i . continue_token).0);
-    if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_field<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprField) {
-    _visitor.visit_expr(& * _i . base);
-    tokens_helper(_visitor, &(& _i . dot_token).0);
-    _visitor.visit_member(& _i . member);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_for_loop<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprForLoop) {
-    if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
-    if let Some(ref it) = _i . colon_token { tokens_helper(_visitor, &(it).0) };
-    tokens_helper(_visitor, &(& _i . for_token).0);
-    _visitor.visit_pat(& * _i . pat);
-    tokens_helper(_visitor, &(& _i . in_token).0);
-    _visitor.visit_expr(& * _i . expr);
-    _visitor.visit_block(& _i . body);
-}
-
-pub fn visit_expr_group<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprGroup) {
-    tokens_helper(_visitor, &(& _i . group_token).0);
-    _visitor.visit_expr(& * _i . expr);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_if<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIf) {
-    tokens_helper(_visitor, &(& _i . if_token).0);
-    _visitor.visit_expr(& * _i . cond);
-    _visitor.visit_block(& _i . if_true);
-    if let Some(ref it) = _i . else_token { tokens_helper(_visitor, &(it).0) };
-    if let Some(ref it) = _i . if_false { _visitor.visit_expr(& * * it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_if_let<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIfLet) {
-    tokens_helper(_visitor, &(& _i . if_token).0);
-    tokens_helper(_visitor, &(& _i . let_token).0);
-    _visitor.visit_pat(& * _i . pat);
-    tokens_helper(_visitor, &(& _i . eq_token).0);
-    _visitor.visit_expr(& * _i . expr);
-    _visitor.visit_block(& _i . if_true);
-    if let Some(ref it) = _i . else_token { tokens_helper(_visitor, &(it).0) };
-    if let Some(ref it) = _i . if_false { _visitor.visit_expr(& * * it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_in_place<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprInPlace) {
-    _visitor.visit_expr(& * _i . place);
-    _visitor.visit_in_place_kind(& _i . kind);
-    _visitor.visit_expr(& * _i . value);
-}
-
-pub fn visit_expr_index<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIndex) {
-    _visitor.visit_expr(& * _i . expr);
-    tokens_helper(_visitor, &(& _i . bracket_token).0);
-    _visitor.visit_expr(& * _i . index);
-}
-
-pub fn visit_expr_kind<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprKind) {
-    use ::ExprKind::*;
+    use ::Expr::*;
     match *_i {
         Box(ref _binding_0, ) => {
             full!(_visitor.visit_expr_box(_binding_0));
@@ -841,7 +710,7 @@
             _visitor.visit_expr_unary(_binding_0);
         }
         Lit(ref _binding_0, ) => {
-            _visitor.visit_lit(_binding_0);
+            _visitor.visit_expr_lit(_binding_0);
         }
         Cast(ref _binding_0, ) => {
             _visitor.visit_expr_cast(_binding_0);
@@ -910,7 +779,7 @@
             full!(_visitor.visit_expr_ret(_binding_0));
         }
         Macro(ref _binding_0, ) => {
-            _visitor.visit_macro(_binding_0);
+            full!(_visitor.visit_expr_macro(_binding_0));
         }
         Struct(ref _binding_0, ) => {
             full!(_visitor.visit_expr_struct(_binding_0));
@@ -936,14 +805,174 @@
     }
 }
 # [ cfg ( feature = "full" ) ]
+pub fn visit_expr_addr_of<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAddrOf) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . and_token).0);
+    _visitor.visit_mutability(& _i . mutbl);
+    _visitor.visit_expr(& * _i . expr);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_array<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprArray) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . bracket_token).0);
+    for el in & _i . exprs { let it = el.item(); _visitor.visit_expr(it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_assign<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAssign) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . left);
+    tokens_helper(_visitor, &(& _i . eq_token).0);
+    _visitor.visit_expr(& * _i . right);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_assign_op<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAssignOp) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . left);
+    _visitor.visit_bin_op(& _i . op);
+    _visitor.visit_expr(& * _i . right);
+}
+
+pub fn visit_expr_binary<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBinary) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . left);
+    _visitor.visit_bin_op(& _i . op);
+    _visitor.visit_expr(& * _i . right);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_block<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBlock) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_block(& _i . block);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_box<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBox) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . box_token).0);
+    _visitor.visit_expr(& * _i . expr);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_break<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBreak) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . break_token).0);
+    if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
+    if let Some(ref it) = _i . expr { _visitor.visit_expr(& * * it) };
+}
+
+pub fn visit_expr_call<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCall) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . func);
+    tokens_helper(_visitor, &(& _i . paren_token).0);
+    for el in & _i . args { let it = el.item(); _visitor.visit_expr(it) };
+}
+
+pub fn visit_expr_cast<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCast) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . expr);
+    tokens_helper(_visitor, &(& _i . as_token).0);
+    _visitor.visit_type(& * _i . ty);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_catch<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCatch) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . do_token).0);
+    tokens_helper(_visitor, &(& _i . catch_token).0);
+    _visitor.visit_block(& _i . block);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_closure<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprClosure) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_capture_by(& _i . capture);
+    tokens_helper(_visitor, &(& _i . or1_token).0);
+    for el in & _i . inputs { let it = el.item(); _visitor.visit_fn_arg(it) };
+    tokens_helper(_visitor, &(& _i . or2_token).0);
+    _visitor.visit_return_type(& _i . output);
+    _visitor.visit_expr(& * _i . body);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_continue<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprContinue) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . continue_token).0);
+    if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_field<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprField) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . base);
+    tokens_helper(_visitor, &(& _i . dot_token).0);
+    _visitor.visit_member(& _i . member);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_for_loop<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprForLoop) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
+    if let Some(ref it) = _i . colon_token { tokens_helper(_visitor, &(it).0) };
+    tokens_helper(_visitor, &(& _i . for_token).0);
+    _visitor.visit_pat(& * _i . pat);
+    tokens_helper(_visitor, &(& _i . in_token).0);
+    _visitor.visit_expr(& * _i . expr);
+    _visitor.visit_block(& _i . body);
+}
+
+pub fn visit_expr_group<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprGroup) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . group_token).0);
+    _visitor.visit_expr(& * _i . expr);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_if<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIf) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . if_token).0);
+    _visitor.visit_expr(& * _i . cond);
+    _visitor.visit_block(& _i . if_true);
+    if let Some(ref it) = _i . else_token { tokens_helper(_visitor, &(it).0) };
+    if let Some(ref it) = _i . if_false { _visitor.visit_expr(& * * it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_if_let<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIfLet) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    tokens_helper(_visitor, &(& _i . if_token).0);
+    tokens_helper(_visitor, &(& _i . let_token).0);
+    _visitor.visit_pat(& * _i . pat);
+    tokens_helper(_visitor, &(& _i . eq_token).0);
+    _visitor.visit_expr(& * _i . expr);
+    _visitor.visit_block(& _i . if_true);
+    if let Some(ref it) = _i . else_token { tokens_helper(_visitor, &(it).0) };
+    if let Some(ref it) = _i . if_false { _visitor.visit_expr(& * * it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_in_place<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprInPlace) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . place);
+    _visitor.visit_in_place_kind(& _i . kind);
+    _visitor.visit_expr(& * _i . value);
+}
+
+pub fn visit_expr_index<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIndex) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_expr(& * _i . expr);
+    tokens_helper(_visitor, &(& _i . bracket_token).0);
+    _visitor.visit_expr(& * _i . index);
+}
+
+pub fn visit_expr_lit<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprLit) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_lit(& _i . lit);
+}
+# [ cfg ( feature = "full" ) ]
 pub fn visit_expr_loop<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprLoop) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
     if let Some(ref it) = _i . colon_token { tokens_helper(_visitor, &(it).0) };
     tokens_helper(_visitor, &(& _i . loop_token).0);
     _visitor.visit_block(& _i . body);
 }
 # [ cfg ( feature = "full" ) ]
+pub fn visit_expr_macro<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprMacro) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
+    _visitor.visit_macro(& _i . mac);
+}
+# [ cfg ( feature = "full" ) ]
 pub fn visit_expr_match<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprMatch) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     tokens_helper(_visitor, &(& _i . match_token).0);
     _visitor.visit_expr(& * _i . expr);
     tokens_helper(_visitor, &(& _i . brace_token).0);
@@ -951,6 +980,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_method_call<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprMethodCall) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     _visitor.visit_expr(& * _i . expr);
     tokens_helper(_visitor, &(& _i . dot_token).0);
     _visitor.visit_ident(& _i . method);
@@ -963,22 +993,26 @@
 }
 
 pub fn visit_expr_paren<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprParen) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     tokens_helper(_visitor, &(& _i . paren_token).0);
     _visitor.visit_expr(& * _i . expr);
 }
 
 pub fn visit_expr_path<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprPath) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     if let Some(ref it) = _i . qself { _visitor.visit_qself(it) };
     _visitor.visit_path(& _i . path);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_range<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprRange) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     if let Some(ref it) = _i . from { _visitor.visit_expr(& * * it) };
     _visitor.visit_range_limits(& _i . limits);
     if let Some(ref it) = _i . to { _visitor.visit_expr(& * * it) };
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_repeat<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprRepeat) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     tokens_helper(_visitor, &(& _i . bracket_token).0);
     _visitor.visit_expr(& * _i . expr);
     tokens_helper(_visitor, &(& _i . semi_token).0);
@@ -986,11 +1020,13 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_ret<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprRet) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     tokens_helper(_visitor, &(& _i . return_token).0);
     if let Some(ref it) = _i . expr { _visitor.visit_expr(& * * it) };
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_struct<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprStruct) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     _visitor.visit_path(& _i . path);
     tokens_helper(_visitor, &(& _i . brace_token).0);
     for el in & _i . fields { let it = el.item(); _visitor.visit_field_value(it) };
@@ -999,32 +1035,38 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_try<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprTry) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     _visitor.visit_expr(& * _i . expr);
     tokens_helper(_visitor, &(& _i . question_token).0);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_tuple<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprTuple) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     tokens_helper(_visitor, &(& _i . paren_token).0);
     for el in & _i . args { let it = el.item(); _visitor.visit_expr(it) };
 }
 
 pub fn visit_expr_type<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprType) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     _visitor.visit_expr(& * _i . expr);
     tokens_helper(_visitor, &(& _i . colon_token).0);
     _visitor.visit_type(& * _i . ty);
 }
 
 pub fn visit_expr_unary<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprUnary) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     _visitor.visit_un_op(& _i . op);
     _visitor.visit_expr(& * _i . expr);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_unsafe<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprUnsafe) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     tokens_helper(_visitor, &(& _i . unsafe_token).0);
     _visitor.visit_block(& _i . block);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_while<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprWhile) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
     if let Some(ref it) = _i . colon_token { tokens_helper(_visitor, &(it).0) };
     tokens_helper(_visitor, &(& _i . while_token).0);
@@ -1033,6 +1075,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_while_let<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprWhileLet) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     if let Some(ref it) = _i . label { _visitor.visit_lifetime(it) };
     if let Some(ref it) = _i . colon_token { tokens_helper(_visitor, &(it).0) };
     tokens_helper(_visitor, &(& _i . while_token).0);
@@ -1044,6 +1087,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_yield<'ast, V: Visitor<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprYield) {
+    for it in & _i . attrs { _visitor.visit_attribute(it) };
     tokens_helper(_visitor, &(& _i . yield_token).0);
     if let Some(ref it) = _i . expr { _visitor.visit_expr(& * * it) };
 }
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index f9117f2..c732b4c 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -126,10 +126,12 @@
 
 fn visit_expr_index_mut(&mut self, i: &mut ExprIndex) { visit_expr_index_mut(self, i) }
 
-fn visit_expr_kind_mut(&mut self, i: &mut ExprKind) { visit_expr_kind_mut(self, i) }
+fn visit_expr_lit_mut(&mut self, i: &mut ExprLit) { visit_expr_lit_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_expr_loop_mut(&mut self, i: &mut ExprLoop) { visit_expr_loop_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
+fn visit_expr_macro_mut(&mut self, i: &mut ExprMacro) { visit_expr_macro_mut(self, i) }
+# [ cfg ( feature = "full" ) ]
 fn visit_expr_match_mut(&mut self, i: &mut ExprMatch) { visit_expr_match_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
 fn visit_expr_method_call_mut(&mut self, i: &mut ExprMethodCall) { visit_expr_method_call_mut(self, i) }
@@ -681,140 +683,7 @@
 }
 
 pub fn visit_expr_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Expr) {
-    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
-    _visitor.visit_expr_kind_mut(& mut _i . node);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_addr_of_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAddrOf) {
-    tokens_helper(_visitor, &mut (& mut _i . and_token).0);
-    _visitor.visit_mutability_mut(& mut _i . mutbl);
-    _visitor.visit_expr_mut(& mut * _i . expr);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_array_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprArray) {
-    tokens_helper(_visitor, &mut (& mut _i . bracket_token).0);
-    for mut el in & mut _i . exprs { let it = el.item_mut(); _visitor.visit_expr_mut(it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_assign_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAssign) {
-    _visitor.visit_expr_mut(& mut * _i . left);
-    tokens_helper(_visitor, &mut (& mut _i . eq_token).0);
-    _visitor.visit_expr_mut(& mut * _i . right);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_assign_op_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAssignOp) {
-    _visitor.visit_expr_mut(& mut * _i . left);
-    _visitor.visit_bin_op_mut(& mut _i . op);
-    _visitor.visit_expr_mut(& mut * _i . right);
-}
-
-pub fn visit_expr_binary_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBinary) {
-    _visitor.visit_expr_mut(& mut * _i . left);
-    _visitor.visit_bin_op_mut(& mut _i . op);
-    _visitor.visit_expr_mut(& mut * _i . right);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_block_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBlock) {
-    _visitor.visit_block_mut(& mut _i . block);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_box_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBox) {
-    tokens_helper(_visitor, &mut (& mut _i . box_token).0);
-    _visitor.visit_expr_mut(& mut * _i . expr);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_break_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBreak) {
-    tokens_helper(_visitor, &mut (& mut _i . break_token).0);
-    if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
-    if let Some(ref mut it) = _i . expr { _visitor.visit_expr_mut(& mut * * it) };
-}
-
-pub fn visit_expr_call_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCall) {
-    _visitor.visit_expr_mut(& mut * _i . func);
-    tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
-    for mut el in & mut _i . args { let it = el.item_mut(); _visitor.visit_expr_mut(it) };
-}
-
-pub fn visit_expr_cast_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCast) {
-    _visitor.visit_expr_mut(& mut * _i . expr);
-    tokens_helper(_visitor, &mut (& mut _i . as_token).0);
-    _visitor.visit_type_mut(& mut * _i . ty);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_catch_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCatch) {
-    tokens_helper(_visitor, &mut (& mut _i . do_token).0);
-    tokens_helper(_visitor, &mut (& mut _i . catch_token).0);
-    _visitor.visit_block_mut(& mut _i . block);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_closure_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprClosure) {
-    _visitor.visit_capture_by_mut(& mut _i . capture);
-    tokens_helper(_visitor, &mut (& mut _i . or1_token).0);
-    for mut el in & mut _i . inputs { let it = el.item_mut(); _visitor.visit_fn_arg_mut(it) };
-    tokens_helper(_visitor, &mut (& mut _i . or2_token).0);
-    _visitor.visit_return_type_mut(& mut _i . output);
-    _visitor.visit_expr_mut(& mut * _i . body);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_continue_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprContinue) {
-    tokens_helper(_visitor, &mut (& mut _i . continue_token).0);
-    if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_field_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprField) {
-    _visitor.visit_expr_mut(& mut * _i . base);
-    tokens_helper(_visitor, &mut (& mut _i . dot_token).0);
-    _visitor.visit_member_mut(& mut _i . member);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_for_loop_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprForLoop) {
-    if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
-    if let Some(ref mut it) = _i . colon_token { tokens_helper(_visitor, &mut (it).0) };
-    tokens_helper(_visitor, &mut (& mut _i . for_token).0);
-    _visitor.visit_pat_mut(& mut * _i . pat);
-    tokens_helper(_visitor, &mut (& mut _i . in_token).0);
-    _visitor.visit_expr_mut(& mut * _i . expr);
-    _visitor.visit_block_mut(& mut _i . body);
-}
-
-pub fn visit_expr_group_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprGroup) {
-    tokens_helper(_visitor, &mut (& mut _i . group_token).0);
-    _visitor.visit_expr_mut(& mut * _i . expr);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_if_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIf) {
-    tokens_helper(_visitor, &mut (& mut _i . if_token).0);
-    _visitor.visit_expr_mut(& mut * _i . cond);
-    _visitor.visit_block_mut(& mut _i . if_true);
-    if let Some(ref mut it) = _i . else_token { tokens_helper(_visitor, &mut (it).0) };
-    if let Some(ref mut it) = _i . if_false { _visitor.visit_expr_mut(& mut * * it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_if_let_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIfLet) {
-    tokens_helper(_visitor, &mut (& mut _i . if_token).0);
-    tokens_helper(_visitor, &mut (& mut _i . let_token).0);
-    _visitor.visit_pat_mut(& mut * _i . pat);
-    tokens_helper(_visitor, &mut (& mut _i . eq_token).0);
-    _visitor.visit_expr_mut(& mut * _i . expr);
-    _visitor.visit_block_mut(& mut _i . if_true);
-    if let Some(ref mut it) = _i . else_token { tokens_helper(_visitor, &mut (it).0) };
-    if let Some(ref mut it) = _i . if_false { _visitor.visit_expr_mut(& mut * * it) };
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_expr_in_place_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprInPlace) {
-    _visitor.visit_expr_mut(& mut * _i . place);
-    _visitor.visit_in_place_kind_mut(& mut _i . kind);
-    _visitor.visit_expr_mut(& mut * _i . value);
-}
-
-pub fn visit_expr_index_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIndex) {
-    _visitor.visit_expr_mut(& mut * _i . expr);
-    tokens_helper(_visitor, &mut (& mut _i . bracket_token).0);
-    _visitor.visit_expr_mut(& mut * _i . index);
-}
-
-pub fn visit_expr_kind_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprKind) {
-    use ::ExprKind::*;
+    use ::Expr::*;
     match *_i {
         Box(ref mut _binding_0, ) => {
             full!(_visitor.visit_expr_box_mut(_binding_0));
@@ -841,7 +710,7 @@
             _visitor.visit_expr_unary_mut(_binding_0);
         }
         Lit(ref mut _binding_0, ) => {
-            _visitor.visit_lit_mut(_binding_0);
+            _visitor.visit_expr_lit_mut(_binding_0);
         }
         Cast(ref mut _binding_0, ) => {
             _visitor.visit_expr_cast_mut(_binding_0);
@@ -910,7 +779,7 @@
             full!(_visitor.visit_expr_ret_mut(_binding_0));
         }
         Macro(ref mut _binding_0, ) => {
-            _visitor.visit_macro_mut(_binding_0);
+            full!(_visitor.visit_expr_macro_mut(_binding_0));
         }
         Struct(ref mut _binding_0, ) => {
             full!(_visitor.visit_expr_struct_mut(_binding_0));
@@ -936,14 +805,174 @@
     }
 }
 # [ cfg ( feature = "full" ) ]
+pub fn visit_expr_addr_of_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAddrOf) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . and_token).0);
+    _visitor.visit_mutability_mut(& mut _i . mutbl);
+    _visitor.visit_expr_mut(& mut * _i . expr);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_array_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprArray) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . bracket_token).0);
+    for mut el in & mut _i . exprs { let it = el.item_mut(); _visitor.visit_expr_mut(it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_assign_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAssign) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . left);
+    tokens_helper(_visitor, &mut (& mut _i . eq_token).0);
+    _visitor.visit_expr_mut(& mut * _i . right);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_assign_op_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAssignOp) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . left);
+    _visitor.visit_bin_op_mut(& mut _i . op);
+    _visitor.visit_expr_mut(& mut * _i . right);
+}
+
+pub fn visit_expr_binary_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBinary) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . left);
+    _visitor.visit_bin_op_mut(& mut _i . op);
+    _visitor.visit_expr_mut(& mut * _i . right);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_block_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBlock) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_block_mut(& mut _i . block);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_box_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBox) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . box_token).0);
+    _visitor.visit_expr_mut(& mut * _i . expr);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_break_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBreak) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . break_token).0);
+    if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
+    if let Some(ref mut it) = _i . expr { _visitor.visit_expr_mut(& mut * * it) };
+}
+
+pub fn visit_expr_call_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCall) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . func);
+    tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
+    for mut el in & mut _i . args { let it = el.item_mut(); _visitor.visit_expr_mut(it) };
+}
+
+pub fn visit_expr_cast_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCast) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . expr);
+    tokens_helper(_visitor, &mut (& mut _i . as_token).0);
+    _visitor.visit_type_mut(& mut * _i . ty);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_catch_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCatch) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . do_token).0);
+    tokens_helper(_visitor, &mut (& mut _i . catch_token).0);
+    _visitor.visit_block_mut(& mut _i . block);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_closure_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprClosure) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_capture_by_mut(& mut _i . capture);
+    tokens_helper(_visitor, &mut (& mut _i . or1_token).0);
+    for mut el in & mut _i . inputs { let it = el.item_mut(); _visitor.visit_fn_arg_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . or2_token).0);
+    _visitor.visit_return_type_mut(& mut _i . output);
+    _visitor.visit_expr_mut(& mut * _i . body);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_continue_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprContinue) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . continue_token).0);
+    if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_field_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprField) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . base);
+    tokens_helper(_visitor, &mut (& mut _i . dot_token).0);
+    _visitor.visit_member_mut(& mut _i . member);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_for_loop_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprForLoop) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
+    if let Some(ref mut it) = _i . colon_token { tokens_helper(_visitor, &mut (it).0) };
+    tokens_helper(_visitor, &mut (& mut _i . for_token).0);
+    _visitor.visit_pat_mut(& mut * _i . pat);
+    tokens_helper(_visitor, &mut (& mut _i . in_token).0);
+    _visitor.visit_expr_mut(& mut * _i . expr);
+    _visitor.visit_block_mut(& mut _i . body);
+}
+
+pub fn visit_expr_group_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprGroup) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . group_token).0);
+    _visitor.visit_expr_mut(& mut * _i . expr);
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_if_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIf) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . if_token).0);
+    _visitor.visit_expr_mut(& mut * _i . cond);
+    _visitor.visit_block_mut(& mut _i . if_true);
+    if let Some(ref mut it) = _i . else_token { tokens_helper(_visitor, &mut (it).0) };
+    if let Some(ref mut it) = _i . if_false { _visitor.visit_expr_mut(& mut * * it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_if_let_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIfLet) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    tokens_helper(_visitor, &mut (& mut _i . if_token).0);
+    tokens_helper(_visitor, &mut (& mut _i . let_token).0);
+    _visitor.visit_pat_mut(& mut * _i . pat);
+    tokens_helper(_visitor, &mut (& mut _i . eq_token).0);
+    _visitor.visit_expr_mut(& mut * _i . expr);
+    _visitor.visit_block_mut(& mut _i . if_true);
+    if let Some(ref mut it) = _i . else_token { tokens_helper(_visitor, &mut (it).0) };
+    if let Some(ref mut it) = _i . if_false { _visitor.visit_expr_mut(& mut * * it) };
+}
+# [ cfg ( feature = "full" ) ]
+pub fn visit_expr_in_place_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprInPlace) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . place);
+    _visitor.visit_in_place_kind_mut(& mut _i . kind);
+    _visitor.visit_expr_mut(& mut * _i . value);
+}
+
+pub fn visit_expr_index_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIndex) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_expr_mut(& mut * _i . expr);
+    tokens_helper(_visitor, &mut (& mut _i . bracket_token).0);
+    _visitor.visit_expr_mut(& mut * _i . index);
+}
+
+pub fn visit_expr_lit_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprLit) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_lit_mut(& mut _i . lit);
+}
+# [ cfg ( feature = "full" ) ]
 pub fn visit_expr_loop_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprLoop) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
     if let Some(ref mut it) = _i . colon_token { tokens_helper(_visitor, &mut (it).0) };
     tokens_helper(_visitor, &mut (& mut _i . loop_token).0);
     _visitor.visit_block_mut(& mut _i . body);
 }
 # [ cfg ( feature = "full" ) ]
+pub fn visit_expr_macro_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprMacro) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
+    _visitor.visit_macro_mut(& mut _i . mac);
+}
+# [ cfg ( feature = "full" ) ]
 pub fn visit_expr_match_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprMatch) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . match_token).0);
     _visitor.visit_expr_mut(& mut * _i . expr);
     tokens_helper(_visitor, &mut (& mut _i . brace_token).0);
@@ -951,6 +980,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_method_call_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprMethodCall) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     _visitor.visit_expr_mut(& mut * _i . expr);
     tokens_helper(_visitor, &mut (& mut _i . dot_token).0);
     _visitor.visit_ident_mut(& mut _i . method);
@@ -963,22 +993,26 @@
 }
 
 pub fn visit_expr_paren_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprParen) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
     _visitor.visit_expr_mut(& mut * _i . expr);
 }
 
 pub fn visit_expr_path_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprPath) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     if let Some(ref mut it) = _i . qself { _visitor.visit_qself_mut(it) };
     _visitor.visit_path_mut(& mut _i . path);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_range_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprRange) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     if let Some(ref mut it) = _i . from { _visitor.visit_expr_mut(& mut * * it) };
     _visitor.visit_range_limits_mut(& mut _i . limits);
     if let Some(ref mut it) = _i . to { _visitor.visit_expr_mut(& mut * * it) };
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_repeat_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprRepeat) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . bracket_token).0);
     _visitor.visit_expr_mut(& mut * _i . expr);
     tokens_helper(_visitor, &mut (& mut _i . semi_token).0);
@@ -986,11 +1020,13 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_ret_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprRet) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . return_token).0);
     if let Some(ref mut it) = _i . expr { _visitor.visit_expr_mut(& mut * * it) };
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_struct_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprStruct) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     _visitor.visit_path_mut(& mut _i . path);
     tokens_helper(_visitor, &mut (& mut _i . brace_token).0);
     for mut el in & mut _i . fields { let it = el.item_mut(); _visitor.visit_field_value_mut(it) };
@@ -999,32 +1035,38 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_try_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprTry) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     _visitor.visit_expr_mut(& mut * _i . expr);
     tokens_helper(_visitor, &mut (& mut _i . question_token).0);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_tuple_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprTuple) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . paren_token).0);
     for mut el in & mut _i . args { let it = el.item_mut(); _visitor.visit_expr_mut(it) };
 }
 
 pub fn visit_expr_type_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprType) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     _visitor.visit_expr_mut(& mut * _i . expr);
     tokens_helper(_visitor, &mut (& mut _i . colon_token).0);
     _visitor.visit_type_mut(& mut * _i . ty);
 }
 
 pub fn visit_expr_unary_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprUnary) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     _visitor.visit_un_op_mut(& mut _i . op);
     _visitor.visit_expr_mut(& mut * _i . expr);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_unsafe_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprUnsafe) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . unsafe_token).0);
     _visitor.visit_block_mut(& mut _i . block);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_while_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprWhile) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
     if let Some(ref mut it) = _i . colon_token { tokens_helper(_visitor, &mut (it).0) };
     tokens_helper(_visitor, &mut (& mut _i . while_token).0);
@@ -1033,6 +1075,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_while_let_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprWhileLet) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     if let Some(ref mut it) = _i . label { _visitor.visit_lifetime_mut(it) };
     if let Some(ref mut it) = _i . colon_token { tokens_helper(_visitor, &mut (it).0) };
     tokens_helper(_visitor, &mut (& mut _i . while_token).0);
@@ -1044,6 +1087,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_expr_yield_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprYield) {
+    for it in & mut _i . attrs { _visitor.visit_attribute_mut(it) };
     tokens_helper(_visitor, &mut (& mut _i . yield_token).0);
     if let Some(ref mut it) = _i . expr { _visitor.visit_expr_mut(& mut * * it) };
 }
diff --git a/src/helper.rs b/src/helper.rs
index 93df003..d15332e 100644
--- a/src/helper.rs
+++ b/src/helper.rs
@@ -116,14 +116,12 @@
 /// named!(expr_with_arrow_call -> Expr, do_parse!(
 ///     mut e: syn!(Expr) >>
 ///     many0!(tap!(arg: tuple!(punct!(->), syn!(Expr)) => {
-///         e = Expr {
-///             node: ExprCall {
-///                 func: Box::new(e),
-///                 args: vec![arg.1].into(),
-///                 paren_token: Default::default(),
-///             }.into(),
+///         e = Expr::Call(ExprCall {
 ///             attrs: Vec::new(),
-///         };
+///             func: Box::new(e),
+///             args: vec![arg.1].into(),
+///             paren_token: Default::default(),
+///         });
 ///     })) >>
 ///     (e)
 /// ));
diff --git a/src/lib.rs b/src/lib.rs
index 8fd6e0a..ef57cf5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -36,7 +36,7 @@
 pub use expr::{Expr, ExprAddrOf, ExprArray, ExprAssign, ExprAssignOp, ExprBinary, ExprBlock,
                ExprBox, ExprBreak, ExprCall, ExprCast, ExprCatch, ExprClosure, ExprContinue,
                ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIfLet, ExprInPlace, ExprIndex,
-               ExprKind, ExprLoop, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRange,
+               ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRange,
                ExprRepeat, ExprRet, ExprStruct, ExprTry, ExprTuple, ExprType,
                ExprUnary, ExprUnsafe, ExprWhile, ExprWhileLet, ExprYield};
 
diff --git a/src/ty.rs b/src/ty.rs
index 8176e76..c95bc86 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -695,9 +695,9 @@
             |
             syn!(TypeBinding) => { GenericArgument::TypeBinding }
             |
-            syn!(Lit) => { |l| GenericArgument::Const(ExprKind::Lit(l).into()) }
+            syn!(ExprLit) => { |l| GenericArgument::Const(Expr::Lit(l).into()) }
             |
-            syn!(ExprBlock) => { |b| GenericArgument::Const(ExprKind::Block(b).into()) }
+            syn!(ExprBlock) => { |b| GenericArgument::Const(Expr::Block(b).into()) }
         ));
     }
 
@@ -1029,14 +1029,14 @@
                 GenericArgument::Lifetime(ref lt) => lt.to_tokens(tokens),
                 GenericArgument::Type(ref ty) => ty.to_tokens(tokens),
                 GenericArgument::TypeBinding(ref tb) => tb.to_tokens(tokens),
-                GenericArgument::Const(ref e) => match e.node {
-                    ExprKind::Lit(_) => e.to_tokens(tokens),
+                GenericArgument::Const(ref e) => match *e {
+                    Expr::Lit(_) => e.to_tokens(tokens),
 
                     // NOTE: We should probably support parsing blocks with only
                     // expressions in them without the full feature for const
                     // generics.
                     #[cfg(feature = "full")]
-                    ExprKind::Block(_) => e.to_tokens(tokens),
+                    Expr::Block(_) => e.to_tokens(tokens),
 
                     // ERROR CORRECTION: Add braces to make sure that the
                     // generated code is valid.
diff --git a/tests/test_derive_input.rs b/tests/test_derive_input.rs
index 34c88bb..e0318ff 100644
--- a/tests/test_derive_input.rs
+++ b/tests/test_derive_input.rs
@@ -271,13 +271,13 @@
                     data: VariantData::Unit,
                     discriminant: Some((
                         Default::default(),
-                        Expr {
-                            node: Lit {
+                        Expr::Lit(ExprLit {
+                            attrs: Vec::new(),
+                            lit: Lit {
                                 value: LitKind::Other(Literal::isize(0)),
                                 span: Default::default(),
-                            }.into(),
-                            attrs: Vec::new(),
-                        },
+                            },
+                        }),
                     )),
                 },
                 Variant {
@@ -286,38 +286,34 @@
                     data: VariantData::Unit,
                     discriminant: Some((
                         Default::default(),
-                        Expr {
-                            node: ExprField {
-                                base: Box::new(Expr {
-                                    node: ExprTuple {
-                                        paren_token: Default::default(),
-                                        args: vec![
-                                            Expr {
-                                                node: ExprKind::Lit(Lit {
-                                                    value: LitKind::Other(Literal::integer(0)),
-                                                    span: Default::default(),
-                                                }),
-                                                attrs: Vec::new(),
-                                            },
-                                            Expr {
-                                                node: ExprKind::Lit(Lit {
-                                                    value: LitKind::Other(Literal::string("data")),
-                                                    span: Default::default(),
-                                                }),
-                                                attrs: Vec::new(),
-                                            },
-                                        ].into(),
-                                    }.into(),
-                                    attrs: Vec::new(),
-                                }),
-                                dot_token: Default::default(),
-                                member: Member::Unnamed(Index {
-                                    index: 0,
-                                    span: Default::default(),
-                                }),
-                            }.into(),
+                        Expr::Field(ExprField {
                             attrs: Vec::new(),
-                        },
+                            base: Box::new(Expr::Tuple(ExprTuple {
+                                attrs: Vec::new(),
+                                paren_token: Default::default(),
+                                args: vec![
+                                    Expr::Lit(ExprLit {
+                                        attrs: Vec::new(),
+                                        lit: Lit {
+                                            value: LitKind::Other(Literal::integer(0)),
+                                            span: Default::default(),
+                                        },
+                                    }),
+                                    Expr::Lit(ExprLit {
+                                        attrs: Vec::new(),
+                                        lit: Lit {
+                                            value: LitKind::Other(Literal::string("data")),
+                                            span: Default::default(),
+                                        },
+                                    }),
+                                ].into(),
+                            })),
+                            dot_token: Default::default(),
+                            member: Member::Unnamed(Index {
+                                index: 0,
+                                span: Default::default(),
+                            }),
+                        }),
                     )),
                 },
             ].into(),
diff --git a/tests/test_expr.rs b/tests/test_expr.rs
index 5967aa6..4a76669 100644
--- a/tests/test_expr.rs
+++ b/tests/test_expr.rs
@@ -95,7 +95,7 @@
     assert_let!(Item::Fn(ItemFn { ref block, .. }) = actual.items[1]; {
         assert_let!(Stmt::Local(ref local) = block.stmts[0]; {
             assert_let!(Local { init: Some(ref init_expr), .. } = **local; {
-                assert_let!(Expr { node: ExprKind::Catch(..), .. } = **init_expr);
+                assert_let!(Expr::Catch(..) = **init_expr);
             });
         });
 
@@ -106,21 +106,21 @@
         });
 
         assert_let!(Stmt::Expr(ref expr) = block.stmts[3]; {
-            assert_let!(Expr { node: ExprKind::While(ExprWhile { ref cond, .. }), .. } = **expr; {
-                assert_let!(Expr { node: ExprKind::Path(ExprPath { qself: None, ref path }), .. } = **cond; {
+            assert_let!(Expr::While(ExprWhile { ref cond, .. }) = **expr; {
+                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
                     assert_eq!(*path, "catch".into());
                 });
             });
         });
 
         assert_let!(Stmt::Semi(ref expr, _) = block.stmts[5]; {
-            assert_let!(Expr { node: ExprKind::Assign(ExprAssign { ref left, ref right, .. }), .. } = **expr; {
-                assert_let!(Expr { node: ExprKind::Path(ExprPath { qself: None, ref path }), .. } = **left; {
+            assert_let!(Expr::Assign(ExprAssign { ref left, ref right, .. }) = **expr; {
+                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **left; {
                     assert_eq!(*path, "catch".into());
                 });
 
-                assert_let!(Expr { node: ExprKind::If(ExprIf { ref cond, .. }), .. } = **right; {
-                    assert_let!(Expr { node: ExprKind::Path(ExprPath { qself: None, ref path }), .. } = **cond; {
+                assert_let!(Expr::If(ExprIf { ref cond, .. }) = **right; {
+                    assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
                         assert_eq!(*path, "catch".into());
                     });
                 });
@@ -128,8 +128,8 @@
         });
 
         assert_let!(Stmt::Semi(ref expr, _) = block.stmts[7]; {
-            assert_let!(Expr { node: ExprKind::Match(ExprMatch { ref expr, .. }), .. } = **expr; {
-                assert_let!(Expr { node: ExprKind::Path(ExprPath { qself: None, ref path }), .. } = **expr; {
+            assert_let!(Expr::Match(ExprMatch { ref expr, .. }) = **expr; {
+                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **expr; {
                     assert_eq!(*path, "catch".into());
                 });
             });
diff --git a/tests/test_grouping.rs b/tests/test_grouping.rs
index f532639..b09225e 100644
--- a/tests/test_grouping.rs
+++ b/tests/test_grouping.rs
@@ -3,7 +3,7 @@
 
 #[macro_use]
 extern crate syn;
-use syn::{BinOp, Expr, ExprBinary, ExprGroup, ExprKind, Lit, LitKind};
+use syn::{BinOp, Expr, ExprBinary, ExprGroup, ExprLit, Lit, LitKind};
 use syn::token::Group;
 
 extern crate proc_macro2;
@@ -18,14 +18,17 @@
     }
 }
 
-fn expr<T: Into<ExprKind>>(t: T) -> Expr {
-    t.into().into()
+fn expr<T: Into<Expr>>(t: T) -> Expr {
+    t.into()
 }
 
 fn lit<T: Into<Literal>>(t: T) -> Expr {
-    expr(Lit {
-        value: LitKind::Other(t.into()),
-        span: Span::default(),
+    Expr::Lit(ExprLit {
+        attrs: Vec::new(),
+        lit: Lit {
+            value: LitKind::Other(t.into()),
+            span: Span::default(),
+        },
     })
 }
 
@@ -53,12 +56,16 @@
     assert_eq!(
         common::parse::syn::<Expr>(raw),
         expr(ExprBinary {
+            attrs: Vec::new(),
             left: Box::new(lit(Literal::i32(1))),
             op: BinOp::Add(<Token![+]>::default()),
             right: Box::new(expr(ExprBinary {
+                attrs: Vec::new(),
                 left: Box::new(expr(ExprGroup {
+                    attrs: Vec::new(),
                     group_token: Group::default(),
                     expr: Box::new(expr(ExprBinary {
+                        attrs: Vec::new(),
                         left: Box::new(lit(Literal::i32(2))),
                         op: BinOp::Add(<Token![+]>::default()),
                         right: Box::new(lit(Literal::i32(3))),
@@ -95,13 +102,16 @@
     assert_eq!(
         common::parse::syn::<Expr>(raw),
         expr(ExprBinary {
+            attrs: Vec::new(),
             left: Box::new(expr(ExprBinary {
+                attrs: Vec::new(),
                 left: Box::new(lit(Literal::i32(1))),
                 op: BinOp::Add(<Token![+]>::default()),
                 right: Box::new(lit(Literal::i32(2))),
             })),
             op: BinOp::Add(<Token![+]>::default()),
             right: Box::new(expr(ExprBinary {
+                attrs: Vec::new(),
                 left: Box::new(lit(Literal::i32(3))),
                 op: BinOp::Mul(<Token![*]>::default()),
                 right: Box::new(lit(Literal::i32(4))),
diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs
index d8dc4ed..9071b04 100644
--- a/tests/test_precedence.rs
+++ b/tests/test_precedence.rs
@@ -292,15 +292,15 @@
 fn syn_brackets(syn_expr: syn::Expr) -> syn::Expr {
     use syn::*;
     use syn::fold::*;
+    use std::mem;
 
-    fn paren(folder: &mut BracketsFolder, node: ExprKind) -> ExprKind {
-        ExprKind::Paren(ExprParen {
+    fn paren(folder: &mut BracketsFolder, mut node: Expr) -> Expr {
+        let attrs = mem::replace(node.attrs_mut(), Vec::new());
+        Expr::Paren(ExprParen {
+            attrs: attrs,
             expr: Box::new(fold_expr(
                 folder,
-                Expr {
-                    node: node,
-                    attrs: vec![],
-                },
+                node,
             )),
             paren_token: token::Paren::default(),
         })
@@ -309,19 +309,17 @@
     struct BracketsFolder;
     impl Folder for BracketsFolder {
         fn fold_expr(&mut self, expr: Expr) -> Expr {
-            let kind = match expr.node {
-                ExprKind::Group(_) => unreachable!(),
-                ExprKind::Paren(p) => paren(self, p.expr.node),
-                ExprKind::If(..)
-                | ExprKind::Unsafe(..)
-                | ExprKind::Block(..)
-                | ExprKind::IfLet(..) => {
+            match expr {
+                Expr::Group(_) => unreachable!(),
+                Expr::Paren(p) => paren(self, *p.expr),
+                Expr::If(..)
+                | Expr::Unsafe(..)
+                | Expr::Block(..)
+                | Expr::IfLet(..) => {
                     return fold_expr(self, expr);
                 }
                 node => paren(self, node),
-            };
-
-            Expr { node: kind, ..expr }
+            }
         }
 
         fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
@@ -360,13 +358,11 @@
         fn fold_expr(&mut self, expr: Expr) -> Expr {
             self.0.push(expr);
 
-            Expr {
-                node: ExprKind::Tuple(ExprTuple {
-                    args: Delimited::new(),
-                    paren_token: token::Paren::default(),
-                }),
+            Expr::Tuple(ExprTuple {
                 attrs: vec![],
-            }
+                args: Delimited::new(),
+                paren_token: token::Paren::default(),
+            })
         }
     }