Correctly handle Option<T> types in visitor codegen
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index 326bf4c..6f5e77f 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -32,6 +32,18 @@
     }
 }
 
+
+#[cfg(feature = "full")]
+macro_rules! full {
+    ($e:expr) => { $e }
+}
+
+#[cfg(not(feature = "full"))]
+macro_rules! full {
+    ($e:expr) => { unreachable!() }
+}
+
+
 /// AST->AST fold.
 ///
 /// Each method of the Folder trait is a hook to be potentially overridden. Each
@@ -448,7 +460,7 @@
         attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         pats: FoldHelper::lift(_i . pats, |it| { _visitor.fold_pat(it) }),
         if_token: _i . if_token,
-        guard: _i . guard,
+        guard: (_i . guard).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         rocket_token: _i . rocket_token,
         body: Box::new(_visitor.fold_expr(* _i . body)),
         comma: _i . comma,
@@ -503,9 +515,9 @@
 
 pub fn walk_bare_fn_ty<V: Folder + ?Sized>(_visitor: &mut V, _i: BareFnTy) -> BareFnTy {
     BareFnTy {
-        lifetimes: _i . lifetimes,
+        lifetimes: (_i . lifetimes).map(|it| { _visitor.fold_bound_lifetimes(it) }),
         unsafety: _visitor.fold_unsafety(_i . unsafety),
-        abi: _i . abi,
+        abi: (_i . abi).map(|it| { _visitor.fold_abi(it) }),
         fn_token: _i . fn_token,
         paren_token: _i . paren_token,
         inputs: FoldHelper::lift(_i . inputs, |it| { _visitor.fold_bare_fn_arg(it) }),
@@ -834,7 +846,7 @@
 pub fn walk_expr_break<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprBreak) -> ExprBreak {
     ExprBreak {
         label: _i . label,
-        expr: _i . expr,
+        expr: (_i . expr).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         break_token: _i . break_token,
     }
 }
@@ -911,7 +923,7 @@
     ExprIf {
         cond: Box::new(_visitor.fold_expr(* _i . cond)),
         if_true: _visitor.fold_block(_i . if_true),
-        if_false: _i . if_false,
+        if_false: (_i . if_false).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         if_token: _i . if_token,
         else_token: _i . else_token,
     }
@@ -922,7 +934,7 @@
         pat: Box::new(_visitor.fold_pat(* _i . pat)),
         expr: Box::new(_visitor.fold_expr(* _i . expr)),
         if_true: _visitor.fold_block(_i . if_true),
-        if_false: _i . if_false,
+        if_false: (_i . if_false).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         if_token: _i . if_token,
         let_token: _i . let_token,
         eq_token: _i . eq_token,
@@ -951,17 +963,17 @@
     match _i {
         Box(_binding_0, ) => {
             Box (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_box(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_box(_binding_0)),
             )
         }
         InPlace(_binding_0, ) => {
             InPlace (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_in_place(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_in_place(_binding_0)),
             )
         }
         Array(_binding_0, ) => {
             Array (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_array(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_array(_binding_0)),
             )
         }
         Call(_binding_0, ) => {
@@ -971,12 +983,12 @@
         }
         MethodCall(_binding_0, ) => {
             MethodCall (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_method_call(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_method_call(_binding_0)),
             )
         }
         Tup(_binding_0, ) => {
             Tup (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_tup(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_tup(_binding_0)),
             )
         }
         Binary(_binding_0, ) => {
@@ -1006,67 +1018,67 @@
         }
         If(_binding_0, ) => {
             If (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_if(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_if(_binding_0)),
             )
         }
         IfLet(_binding_0, ) => {
             IfLet (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_if_let(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_if_let(_binding_0)),
             )
         }
         While(_binding_0, ) => {
             While (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_while(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_while(_binding_0)),
             )
         }
         WhileLet(_binding_0, ) => {
             WhileLet (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_while_let(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_while_let(_binding_0)),
             )
         }
         ForLoop(_binding_0, ) => {
             ForLoop (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_for_loop(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_for_loop(_binding_0)),
             )
         }
         Loop(_binding_0, ) => {
             Loop (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_loop(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_loop(_binding_0)),
             )
         }
         Match(_binding_0, ) => {
             Match (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_match(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_match(_binding_0)),
             )
         }
         Closure(_binding_0, ) => {
             Closure (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_closure(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_closure(_binding_0)),
             )
         }
         Block(_binding_0, ) => {
             Block (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_block(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_block(_binding_0)),
             )
         }
         Assign(_binding_0, ) => {
             Assign (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_assign(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_assign(_binding_0)),
             )
         }
         AssignOp(_binding_0, ) => {
             AssignOp (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_assign_op(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_assign_op(_binding_0)),
             )
         }
         Field(_binding_0, ) => {
             Field (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_field(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_field(_binding_0)),
             )
         }
         TupField(_binding_0, ) => {
             TupField (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_tup_field(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_tup_field(_binding_0)),
             )
         }
         Index(_binding_0, ) => {
@@ -1076,7 +1088,7 @@
         }
         Range(_binding_0, ) => {
             Range (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_range(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_range(_binding_0)),
             )
         }
         Path(_binding_0, ) => {
@@ -1086,22 +1098,22 @@
         }
         AddrOf(_binding_0, ) => {
             AddrOf (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_addr_of(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_addr_of(_binding_0)),
             )
         }
         Break(_binding_0, ) => {
             Break (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_break(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_break(_binding_0)),
             )
         }
         Continue(_binding_0, ) => {
             Continue (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_continue(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_continue(_binding_0)),
             )
         }
         Ret(_binding_0, ) => {
             Ret (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_ret(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_ret(_binding_0)),
             )
         }
         Mac(_binding_0, ) => {
@@ -1111,12 +1123,12 @@
         }
         Struct(_binding_0, ) => {
             Struct (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_struct(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_struct(_binding_0)),
             )
         }
         Repeat(_binding_0, ) => {
             Repeat (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_repeat(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_repeat(_binding_0)),
             )
         }
         Paren(_binding_0, ) => {
@@ -1131,17 +1143,17 @@
         }
         Try(_binding_0, ) => {
             Try (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_try(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_try(_binding_0)),
             )
         }
         Catch(_binding_0, ) => {
             Catch (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_catch(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_catch(_binding_0)),
             )
         }
         Yield(_binding_0, ) => {
             Yield (
-                { #[cfg(feature = "full")] { _visitor.fold_expr_yield(_binding_0) } #[cfg(not(feature = "full"))] unreachable!() },
+                full!(_visitor.fold_expr_yield(_binding_0)),
             )
         }
     }
@@ -1188,15 +1200,15 @@
 
 pub fn walk_expr_path<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprPath) -> ExprPath {
     ExprPath {
-        qself: _i . qself,
+        qself: (_i . qself).map(|it| { _visitor.fold_qself(it) }),
         path: _visitor.fold_path(_i . path),
     }
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_range<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprRange) -> ExprRange {
     ExprRange {
-        from: _i . from,
-        to: _i . to,
+        from: (_i . from).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
+        to: (_i . to).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         limits: _visitor.fold_range_limits(_i . limits),
     }
 }
@@ -1212,7 +1224,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_ret<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprRet) -> ExprRet {
     ExprRet {
-        expr: _i . expr,
+        expr: (_i . expr).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         return_token: _i . return_token,
     }
 }
@@ -1221,7 +1233,7 @@
     ExprStruct {
         path: _visitor.fold_path(_i . path),
         fields: FoldHelper::lift(_i . fields, |it| { _visitor.fold_field_value(it) }),
-        rest: _i . rest,
+        rest: (_i . rest).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         dot2_token: _i . dot2_token,
         brace_token: _i . brace_token,
     }
@@ -1291,7 +1303,7 @@
 pub fn walk_expr_yield<V: Folder + ?Sized>(_visitor: &mut V, _i: ExprYield) -> ExprYield {
     ExprYield {
         yield_token: _i . yield_token,
-        expr: _i . expr,
+        expr: (_i . expr).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
     }
 }
 
@@ -1589,7 +1601,7 @@
         vis: _visitor.fold_visibility(_i . vis),
         constness: _visitor.fold_constness(_i . constness),
         unsafety: _visitor.fold_unsafety(_i . unsafety),
-        abi: _i . abi,
+        abi: (_i . abi).map(|it| { _visitor.fold_abi(it) }),
         decl: Box::new(_visitor.fold_fn_decl(* _i . decl)),
         ident: _i . ident,
         block: Box::new(_visitor.fold_block(* _i . block)),
@@ -1794,8 +1806,8 @@
         eq_token: _i . eq_token,
         semi_token: _i . semi_token,
         pat: Box::new(_visitor.fold_pat(* _i . pat)),
-        ty: _i . ty,
-        init: _i . init,
+        ty: (_i . ty).map(|it| { Box::new(_visitor.fold_ty(* it)) }),
+        init: (_i . init).map(|it| { Box::new(_visitor.fold_expr(* it)) }),
         attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
     }
 }
@@ -1863,7 +1875,7 @@
     MethodSig {
         constness: _visitor.fold_constness(_i . constness),
         unsafety: _visitor.fold_unsafety(_i . unsafety),
-        abi: _i . abi,
+        abi: (_i . abi).map(|it| { _visitor.fold_abi(it) }),
         ident: _i . ident,
         decl: _visitor.fold_fn_decl(_i . decl),
     }
@@ -1989,7 +2001,7 @@
     PatIdent {
         mode: _visitor.fold_binding_mode(_i . mode),
         ident: _i . ident,
-        subpat: _i . subpat,
+        subpat: (_i . subpat).map(|it| { Box::new(_visitor.fold_pat(* it)) }),
         at_token: _i . at_token,
     }
 }
@@ -2002,7 +2014,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_pat_path<V: Folder + ?Sized>(_visitor: &mut V, _i: PatPath) -> PatPath {
     PatPath {
-        qself: _i . qself,
+        qself: (_i . qself).map(|it| { _visitor.fold_qself(it) }),
         path: _visitor.fold_path(_i . path),
     }
 }
@@ -2026,7 +2038,7 @@
 pub fn walk_pat_slice<V: Folder + ?Sized>(_visitor: &mut V, _i: PatSlice) -> PatSlice {
     PatSlice {
         front: FoldHelper::lift(_i . front, |it| { _visitor.fold_pat(it) }),
-        middle: _i . middle,
+        middle: (_i . middle).map(|it| { Box::new(_visitor.fold_pat(* it)) }),
         back: FoldHelper::lift(_i . back, |it| { _visitor.fold_pat(it) }),
         dot2_token: _i . dot2_token,
         comma_token: _i . comma_token,
@@ -2132,7 +2144,7 @@
 
 pub fn walk_poly_trait_ref<V: Folder + ?Sized>(_visitor: &mut V, _i: PolyTraitRef) -> PolyTraitRef {
     PolyTraitRef {
-        bound_lifetimes: _i . bound_lifetimes,
+        bound_lifetimes: (_i . bound_lifetimes).map(|it| { _visitor.fold_bound_lifetimes(it) }),
         trait_ref: _visitor.fold_path(_i . trait_ref),
     }
 }
@@ -2254,7 +2266,7 @@
 pub fn walk_trait_item_method<V: Folder + ?Sized>(_visitor: &mut V, _i: TraitItemMethod) -> TraitItemMethod {
     TraitItemMethod {
         sig: _visitor.fold_method_sig(_i . sig),
-        default: _i . default,
+        default: (_i . default).map(|it| { _visitor.fold_block(it) }),
         semi_token: _i . semi_token,
     }
 }
@@ -2394,7 +2406,7 @@
         colon_token: _i . colon_token,
         bounds: FoldHelper::lift(_i . bounds, |it| { _visitor.fold_ty_param_bound(it) }),
         eq_token: _i . eq_token,
-        default: _i . default,
+        default: (_i . default).map(|it| { _visitor.fold_ty(it) }),
     }
 }
 
@@ -2424,7 +2436,7 @@
 
 pub fn walk_ty_path<V: Folder + ?Sized>(_visitor: &mut V, _i: TyPath) -> TyPath {
     TyPath {
-        qself: _i . qself,
+        qself: (_i . qself).map(|it| { _visitor.fold_qself(it) }),
         path: _visitor.fold_path(_i . path),
     }
 }
@@ -2512,7 +2524,7 @@
         ident: _i . ident,
         attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
         data: _visitor.fold_variant_data(_i . data),
-        discriminant: _i . discriminant,
+        discriminant: (_i . discriminant).map(|it| { _visitor.fold_expr(it) }),
         eq_token: _i . eq_token,
     }
 }
@@ -2613,7 +2625,7 @@
 
 pub fn walk_where_bound_predicate<V: Folder + ?Sized>(_visitor: &mut V, _i: WhereBoundPredicate) -> WhereBoundPredicate {
     WhereBoundPredicate {
-        bound_lifetimes: _i . bound_lifetimes,
+        bound_lifetimes: (_i . bound_lifetimes).map(|it| { _visitor.fold_bound_lifetimes(it) }),
         bounded_ty: _visitor.fold_ty(_i . bounded_ty),
         colon_token: _i . colon_token,
         bounds: FoldHelper::lift(_i . bounds, |it| { _visitor.fold_ty_param_bound(it) }),
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index f932995..d908aef 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -8,6 +8,18 @@
 
 use super::*;
 
+
+#[cfg(feature = "full")]
+macro_rules! full {
+    ($e:expr) => { $e }
+}
+
+#[cfg(not(feature = "full"))]
+macro_rules! full {
+    ($e:expr) => { unreachable!() }
+}
+
+
 /// Each method of the Visitor trait is a hook to be potentially
 /// overridden.  Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -408,7 +420,7 @@
     for it in (_i . attrs).iter() { _visitor.visit_attribute(&it) };
     for el in (_i . pats).iter() { let it = el.item(); _visitor.visit_pat(&it) };
     // Skipped field _i . if_token;
-    // Skipped field _i . guard;
+    if let Some(ref it) = _i . guard { _visitor.visit_expr(&* it) };
     // Skipped field _i . rocket_token;
     _visitor.visit_expr(&_i . body);
     // Skipped field _i . comma;
@@ -451,9 +463,9 @@
 }
 
 pub fn walk_bare_fn_ty<V: Visitor + ?Sized>(_visitor: &mut V, _i: &BareFnTy) {
-    // Skipped field _i . lifetimes;
+    if let Some(ref it) = _i . lifetimes { _visitor.visit_bound_lifetimes(&* it) };
     _visitor.visit_unsafety(&_i . unsafety);
-    // Skipped field _i . abi;
+    if let Some(ref it) = _i . abi { _visitor.visit_abi(&* it) };
     // Skipped field _i . fn_token;
     // Skipped field _i . paren_token;
     for el in (_i . inputs).iter() { let it = el.item(); _visitor.visit_bare_fn_arg(&it) };
@@ -684,7 +696,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_break<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ExprBreak) {
     // Skipped field _i . label;
-    // Skipped field _i . expr;
+    if let Some(ref it) = _i . expr { _visitor.visit_expr(&* it) };
     // Skipped field _i . break_token;
 }
 
@@ -743,7 +755,7 @@
 pub fn walk_expr_if<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ExprIf) {
     _visitor.visit_expr(&_i . cond);
     _visitor.visit_block(&_i . if_true);
-    // Skipped field _i . if_false;
+    if let Some(ref it) = _i . if_false { _visitor.visit_expr(&* it) };
     // Skipped field _i . if_token;
     // Skipped field _i . else_token;
 }
@@ -752,7 +764,7 @@
     _visitor.visit_pat(&_i . pat);
     _visitor.visit_expr(&_i . expr);
     _visitor.visit_block(&_i . if_true);
-    // Skipped field _i . if_false;
+    if let Some(ref it) = _i . if_false { _visitor.visit_expr(&* it) };
     // Skipped field _i . if_token;
     // Skipped field _i . let_token;
     // Skipped field _i . eq_token;
@@ -775,22 +787,22 @@
     use ::ExprKind::*;
     match *_i {
         Box(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_box(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_box(&* _binding_0));
         }
         InPlace(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_in_place(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_in_place(&* _binding_0));
         }
         Array(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_array(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_array(&* _binding_0));
         }
         Call(ref _binding_0, ) => {
             _visitor.visit_expr_call(&* _binding_0);
         }
         MethodCall(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_method_call(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_method_call(&* _binding_0));
         }
         Tup(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_tup(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_tup(&* _binding_0));
         }
         Binary(ref _binding_0, ) => {
             _visitor.visit_expr_binary(&* _binding_0);
@@ -808,73 +820,73 @@
             _visitor.visit_expr_type(&* _binding_0);
         }
         If(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_if(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_if(&* _binding_0));
         }
         IfLet(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_if_let(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_if_let(&* _binding_0));
         }
         While(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_while(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_while(&* _binding_0));
         }
         WhileLet(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_while_let(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_while_let(&* _binding_0));
         }
         ForLoop(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_for_loop(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_for_loop(&* _binding_0));
         }
         Loop(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_loop(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_loop(&* _binding_0));
         }
         Match(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_match(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_match(&* _binding_0));
         }
         Closure(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_closure(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_closure(&* _binding_0));
         }
         Block(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_block(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_block(&* _binding_0));
         }
         Assign(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_assign(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_assign(&* _binding_0));
         }
         AssignOp(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_assign_op(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_assign_op(&* _binding_0));
         }
         Field(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_field(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_field(&* _binding_0));
         }
         TupField(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_tup_field(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_tup_field(&* _binding_0));
         }
         Index(ref _binding_0, ) => {
             _visitor.visit_expr_index(&* _binding_0);
         }
         Range(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_range(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_range(&* _binding_0));
         }
         Path(ref _binding_0, ) => {
             _visitor.visit_expr_path(&* _binding_0);
         }
         AddrOf(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_addr_of(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_addr_of(&* _binding_0));
         }
         Break(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_break(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_break(&* _binding_0));
         }
         Continue(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_continue(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_continue(&* _binding_0));
         }
         Ret(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_ret(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_ret(&* _binding_0));
         }
         Mac(ref _binding_0, ) => {
             _visitor.visit_mac(&* _binding_0);
         }
         Struct(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_struct(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_struct(&* _binding_0));
         }
         Repeat(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_repeat(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_repeat(&* _binding_0));
         }
         Paren(ref _binding_0, ) => {
             _visitor.visit_expr_paren(&* _binding_0);
@@ -883,13 +895,13 @@
             _visitor.visit_expr_group(&* _binding_0);
         }
         Try(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_try(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_try(&* _binding_0));
         }
         Catch(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_catch(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_catch(&* _binding_0));
         }
         Yield(ref _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_yield(&* _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_yield(&* _binding_0));
         }
     }
 }
@@ -926,13 +938,13 @@
 }
 
 pub fn walk_expr_path<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ExprPath) {
-    // Skipped field _i . qself;
+    if let Some(ref it) = _i . qself { _visitor.visit_qself(&* it) };
     _visitor.visit_path(&_i . path);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_range<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ExprRange) {
-    // Skipped field _i . from;
-    // Skipped field _i . to;
+    if let Some(ref it) = _i . from { _visitor.visit_expr(&* it) };
+    if let Some(ref it) = _i . to { _visitor.visit_expr(&* it) };
     _visitor.visit_range_limits(&_i . limits);
 }
 # [ cfg ( feature = "full" ) ]
@@ -944,14 +956,14 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_ret<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ExprRet) {
-    // Skipped field _i . expr;
+    if let Some(ref it) = _i . expr { _visitor.visit_expr(&* it) };
     // Skipped field _i . return_token;
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_struct<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ExprStruct) {
     _visitor.visit_path(&_i . path);
     for el in (_i . fields).iter() { let it = el.item(); _visitor.visit_field_value(&it) };
-    // Skipped field _i . rest;
+    if let Some(ref it) = _i . rest { _visitor.visit_expr(&* it) };
     // Skipped field _i . dot2_token;
     // Skipped field _i . brace_token;
 }
@@ -1005,7 +1017,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_yield<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ExprYield) {
     // Skipped field _i . yield_token;
-    // Skipped field _i . expr;
+    if let Some(ref it) = _i . expr { _visitor.visit_expr(&* it) };
 }
 
 pub fn walk_field<V: Visitor + ?Sized>(_visitor: &mut V, _i: &Field) {
@@ -1237,7 +1249,7 @@
     _visitor.visit_visibility(&_i . vis);
     _visitor.visit_constness(&_i . constness);
     _visitor.visit_unsafety(&_i . unsafety);
-    // Skipped field _i . abi;
+    if let Some(ref it) = _i . abi { _visitor.visit_abi(&* it) };
     _visitor.visit_fn_decl(&_i . decl);
     // Skipped field _i . ident;
     _visitor.visit_block(&_i . block);
@@ -1390,8 +1402,8 @@
     // Skipped field _i . eq_token;
     // Skipped field _i . semi_token;
     _visitor.visit_pat(&_i . pat);
-    // Skipped field _i . ty;
-    // Skipped field _i . init;
+    if let Some(ref it) = _i . ty { _visitor.visit_ty(&* it) };
+    if let Some(ref it) = _i . init { _visitor.visit_expr(&* it) };
     for it in (_i . attrs).iter() { _visitor.visit_attribute(&it) };
 }
 
@@ -1443,7 +1455,7 @@
 pub fn walk_method_sig<V: Visitor + ?Sized>(_visitor: &mut V, _i: &MethodSig) {
     _visitor.visit_constness(&_i . constness);
     _visitor.visit_unsafety(&_i . unsafety);
-    // Skipped field _i . abi;
+    if let Some(ref it) = _i . abi { _visitor.visit_abi(&* it) };
     // Skipped field _i . ident;
     _visitor.visit_fn_decl(&_i . decl);
 }
@@ -1531,7 +1543,7 @@
 pub fn walk_pat_ident<V: Visitor + ?Sized>(_visitor: &mut V, _i: &PatIdent) {
     _visitor.visit_binding_mode(&_i . mode);
     // Skipped field _i . ident;
-    // Skipped field _i . subpat;
+    if let Some(ref it) = _i . subpat { _visitor.visit_pat(&* it) };
     // Skipped field _i . at_token;
 }
 # [ cfg ( feature = "full" ) ]
@@ -1540,7 +1552,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_pat_path<V: Visitor + ?Sized>(_visitor: &mut V, _i: &PatPath) {
-    // Skipped field _i . qself;
+    if let Some(ref it) = _i . qself { _visitor.visit_qself(&* it) };
     _visitor.visit_path(&_i . path);
 }
 # [ cfg ( feature = "full" ) ]
@@ -1558,7 +1570,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_pat_slice<V: Visitor + ?Sized>(_visitor: &mut V, _i: &PatSlice) {
     for el in (_i . front).iter() { let it = el.item(); _visitor.visit_pat(&it) };
-    // Skipped field _i . middle;
+    if let Some(ref it) = _i . middle { _visitor.visit_pat(&* it) };
     for el in (_i . back).iter() { let it = el.item(); _visitor.visit_pat(&it) };
     // Skipped field _i . dot2_token;
     // Skipped field _i . comma_token;
@@ -1638,7 +1650,7 @@
 }
 
 pub fn walk_poly_trait_ref<V: Visitor + ?Sized>(_visitor: &mut V, _i: &PolyTraitRef) {
-    // Skipped field _i . bound_lifetimes;
+    if let Some(ref it) = _i . bound_lifetimes { _visitor.visit_bound_lifetimes(&* it) };
     _visitor.visit_path(&_i . trait_ref);
 }
 
@@ -1728,7 +1740,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_trait_item_method<V: Visitor + ?Sized>(_visitor: &mut V, _i: &TraitItemMethod) {
     _visitor.visit_method_sig(&_i . sig);
-    // Skipped field _i . default;
+    if let Some(ref it) = _i . default { _visitor.visit_block(&* it) };
     // Skipped field _i . semi_token;
 }
 # [ cfg ( feature = "full" ) ]
@@ -1824,7 +1836,7 @@
     // Skipped field _i . colon_token;
     for el in (_i . bounds).iter() { let it = el.item(); _visitor.visit_ty_param_bound(&it) };
     // Skipped field _i . eq_token;
-    // Skipped field _i . default;
+    if let Some(ref it) = _i . default { _visitor.visit_ty(&* it) };
 }
 
 pub fn walk_ty_param_bound<V: Visitor + ?Sized>(_visitor: &mut V, _i: &TyParamBound) {
@@ -1846,7 +1858,7 @@
 }
 
 pub fn walk_ty_path<V: Visitor + ?Sized>(_visitor: &mut V, _i: &TyPath) {
-    // Skipped field _i . qself;
+    if let Some(ref it) = _i . qself { _visitor.visit_qself(&* it) };
     _visitor.visit_path(&_i . path);
 }
 
@@ -1912,7 +1924,7 @@
     // Skipped field _i . ident;
     for it in (_i . attrs).iter() { _visitor.visit_attribute(&it) };
     _visitor.visit_variant_data(&_i . data);
-    // Skipped field _i . discriminant;
+    if let Some(ref it) = _i . discriminant { _visitor.visit_expr(&* it) };
     // Skipped field _i . eq_token;
 }
 
@@ -1985,7 +1997,7 @@
 }
 
 pub fn walk_where_bound_predicate<V: Visitor + ?Sized>(_visitor: &mut V, _i: &WhereBoundPredicate) {
-    // Skipped field _i . bound_lifetimes;
+    if let Some(ref it) = _i . bound_lifetimes { _visitor.visit_bound_lifetimes(&* it) };
     _visitor.visit_ty(&_i . bounded_ty);
     // Skipped field _i . colon_token;
     for el in (_i . bounds).iter() { let it = el.item(); _visitor.visit_ty_param_bound(&it) };
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index aefb7cc..a0d7e73 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -8,6 +8,18 @@
 
 use super::*;
 
+
+#[cfg(feature = "full")]
+macro_rules! full {
+    ($e:expr) => { $e }
+}
+
+#[cfg(not(feature = "full"))]
+macro_rules! full {
+    ($e:expr) => { unreachable!() }
+}
+
+
 /// Each method of the VisitorMut trait is a hook to be potentially
 /// overridden.  Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -408,7 +420,7 @@
     for mut it in (_i . attrs).iter_mut() { _visitor.visit_attribute(&mut it) };
     for mut el in (_i . pats).iter_mut() { let mut it = el.item_mut(); _visitor.visit_pat(&mut it) };
     // Skipped field _i . if_token;
-    // Skipped field _i . guard;
+    if let Some(ref mut it) = _i . guard { _visitor.visit_expr(&mut * it) };
     // Skipped field _i . rocket_token;
     _visitor.visit_expr(&mut _i . body);
     // Skipped field _i . comma;
@@ -451,9 +463,9 @@
 }
 
 pub fn walk_bare_fn_ty<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut BareFnTy) {
-    // Skipped field _i . lifetimes;
+    if let Some(ref mut it) = _i . lifetimes { _visitor.visit_bound_lifetimes(&mut * it) };
     _visitor.visit_unsafety(&mut _i . unsafety);
-    // Skipped field _i . abi;
+    if let Some(ref mut it) = _i . abi { _visitor.visit_abi(&mut * it) };
     // Skipped field _i . fn_token;
     // Skipped field _i . paren_token;
     for mut el in (_i . inputs).iter_mut() { let mut it = el.item_mut(); _visitor.visit_bare_fn_arg(&mut it) };
@@ -684,7 +696,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_break<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBreak) {
     // Skipped field _i . label;
-    // Skipped field _i . expr;
+    if let Some(ref mut it) = _i . expr { _visitor.visit_expr(&mut * it) };
     // Skipped field _i . break_token;
 }
 
@@ -743,7 +755,7 @@
 pub fn walk_expr_if<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIf) {
     _visitor.visit_expr(&mut _i . cond);
     _visitor.visit_block(&mut _i . if_true);
-    // Skipped field _i . if_false;
+    if let Some(ref mut it) = _i . if_false { _visitor.visit_expr(&mut * it) };
     // Skipped field _i . if_token;
     // Skipped field _i . else_token;
 }
@@ -752,7 +764,7 @@
     _visitor.visit_pat(&mut _i . pat);
     _visitor.visit_expr(&mut _i . expr);
     _visitor.visit_block(&mut _i . if_true);
-    // Skipped field _i . if_false;
+    if let Some(ref mut it) = _i . if_false { _visitor.visit_expr(&mut * it) };
     // Skipped field _i . if_token;
     // Skipped field _i . let_token;
     // Skipped field _i . eq_token;
@@ -775,22 +787,22 @@
     use ::ExprKind::*;
     match *_i {
         Box(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_box(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_box(&mut * _binding_0));
         }
         InPlace(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_in_place(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_in_place(&mut * _binding_0));
         }
         Array(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_array(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_array(&mut * _binding_0));
         }
         Call(ref mut _binding_0, ) => {
             _visitor.visit_expr_call(&mut * _binding_0);
         }
         MethodCall(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_method_call(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_method_call(&mut * _binding_0));
         }
         Tup(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_tup(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_tup(&mut * _binding_0));
         }
         Binary(ref mut _binding_0, ) => {
             _visitor.visit_expr_binary(&mut * _binding_0);
@@ -808,73 +820,73 @@
             _visitor.visit_expr_type(&mut * _binding_0);
         }
         If(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_if(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_if(&mut * _binding_0));
         }
         IfLet(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_if_let(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_if_let(&mut * _binding_0));
         }
         While(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_while(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_while(&mut * _binding_0));
         }
         WhileLet(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_while_let(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_while_let(&mut * _binding_0));
         }
         ForLoop(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_for_loop(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_for_loop(&mut * _binding_0));
         }
         Loop(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_loop(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_loop(&mut * _binding_0));
         }
         Match(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_match(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_match(&mut * _binding_0));
         }
         Closure(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_closure(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_closure(&mut * _binding_0));
         }
         Block(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_block(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_block(&mut * _binding_0));
         }
         Assign(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_assign(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_assign(&mut * _binding_0));
         }
         AssignOp(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_assign_op(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_assign_op(&mut * _binding_0));
         }
         Field(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_field(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_field(&mut * _binding_0));
         }
         TupField(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_tup_field(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_tup_field(&mut * _binding_0));
         }
         Index(ref mut _binding_0, ) => {
             _visitor.visit_expr_index(&mut * _binding_0);
         }
         Range(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_range(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_range(&mut * _binding_0));
         }
         Path(ref mut _binding_0, ) => {
             _visitor.visit_expr_path(&mut * _binding_0);
         }
         AddrOf(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_addr_of(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_addr_of(&mut * _binding_0));
         }
         Break(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_break(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_break(&mut * _binding_0));
         }
         Continue(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_continue(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_continue(&mut * _binding_0));
         }
         Ret(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_ret(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_ret(&mut * _binding_0));
         }
         Mac(ref mut _binding_0, ) => {
             _visitor.visit_mac(&mut * _binding_0);
         }
         Struct(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_struct(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_struct(&mut * _binding_0));
         }
         Repeat(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_repeat(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_repeat(&mut * _binding_0));
         }
         Paren(ref mut _binding_0, ) => {
             _visitor.visit_expr_paren(&mut * _binding_0);
@@ -883,13 +895,13 @@
             _visitor.visit_expr_group(&mut * _binding_0);
         }
         Try(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_try(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_try(&mut * _binding_0));
         }
         Catch(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_catch(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_catch(&mut * _binding_0));
         }
         Yield(ref mut _binding_0, ) => {
-            { #[cfg(feature = "full")] { _visitor.visit_expr_yield(&mut * _binding_0) } #[cfg(not(feature = "full"))] unreachable!() };
+            full!(_visitor.visit_expr_yield(&mut * _binding_0));
         }
     }
 }
@@ -926,13 +938,13 @@
 }
 
 pub fn walk_expr_path<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprPath) {
-    // Skipped field _i . qself;
+    if let Some(ref mut it) = _i . qself { _visitor.visit_qself(&mut * it) };
     _visitor.visit_path(&mut _i . path);
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_range<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprRange) {
-    // Skipped field _i . from;
-    // Skipped field _i . to;
+    if let Some(ref mut it) = _i . from { _visitor.visit_expr(&mut * it) };
+    if let Some(ref mut it) = _i . to { _visitor.visit_expr(&mut * it) };
     _visitor.visit_range_limits(&mut _i . limits);
 }
 # [ cfg ( feature = "full" ) ]
@@ -944,14 +956,14 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_ret<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprRet) {
-    // Skipped field _i . expr;
+    if let Some(ref mut it) = _i . expr { _visitor.visit_expr(&mut * it) };
     // Skipped field _i . return_token;
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_struct<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprStruct) {
     _visitor.visit_path(&mut _i . path);
     for mut el in (_i . fields).iter_mut() { let mut it = el.item_mut(); _visitor.visit_field_value(&mut it) };
-    // Skipped field _i . rest;
+    if let Some(ref mut it) = _i . rest { _visitor.visit_expr(&mut * it) };
     // Skipped field _i . dot2_token;
     // Skipped field _i . brace_token;
 }
@@ -1005,7 +1017,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_expr_yield<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ExprYield) {
     // Skipped field _i . yield_token;
-    // Skipped field _i . expr;
+    if let Some(ref mut it) = _i . expr { _visitor.visit_expr(&mut * it) };
 }
 
 pub fn walk_field<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut Field) {
@@ -1237,7 +1249,7 @@
     _visitor.visit_visibility(&mut _i . vis);
     _visitor.visit_constness(&mut _i . constness);
     _visitor.visit_unsafety(&mut _i . unsafety);
-    // Skipped field _i . abi;
+    if let Some(ref mut it) = _i . abi { _visitor.visit_abi(&mut * it) };
     _visitor.visit_fn_decl(&mut _i . decl);
     // Skipped field _i . ident;
     _visitor.visit_block(&mut _i . block);
@@ -1390,8 +1402,8 @@
     // Skipped field _i . eq_token;
     // Skipped field _i . semi_token;
     _visitor.visit_pat(&mut _i . pat);
-    // Skipped field _i . ty;
-    // Skipped field _i . init;
+    if let Some(ref mut it) = _i . ty { _visitor.visit_ty(&mut * it) };
+    if let Some(ref mut it) = _i . init { _visitor.visit_expr(&mut * it) };
     for mut it in (_i . attrs).iter_mut() { _visitor.visit_attribute(&mut it) };
 }
 
@@ -1443,7 +1455,7 @@
 pub fn walk_method_sig<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut MethodSig) {
     _visitor.visit_constness(&mut _i . constness);
     _visitor.visit_unsafety(&mut _i . unsafety);
-    // Skipped field _i . abi;
+    if let Some(ref mut it) = _i . abi { _visitor.visit_abi(&mut * it) };
     // Skipped field _i . ident;
     _visitor.visit_fn_decl(&mut _i . decl);
 }
@@ -1531,7 +1543,7 @@
 pub fn walk_pat_ident<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut PatIdent) {
     _visitor.visit_binding_mode(&mut _i . mode);
     // Skipped field _i . ident;
-    // Skipped field _i . subpat;
+    if let Some(ref mut it) = _i . subpat { _visitor.visit_pat(&mut * it) };
     // Skipped field _i . at_token;
 }
 # [ cfg ( feature = "full" ) ]
@@ -1540,7 +1552,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn walk_pat_path<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut PatPath) {
-    // Skipped field _i . qself;
+    if let Some(ref mut it) = _i . qself { _visitor.visit_qself(&mut * it) };
     _visitor.visit_path(&mut _i . path);
 }
 # [ cfg ( feature = "full" ) ]
@@ -1558,7 +1570,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_pat_slice<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut PatSlice) {
     for mut el in (_i . front).iter_mut() { let mut it = el.item_mut(); _visitor.visit_pat(&mut it) };
-    // Skipped field _i . middle;
+    if let Some(ref mut it) = _i . middle { _visitor.visit_pat(&mut * it) };
     for mut el in (_i . back).iter_mut() { let mut it = el.item_mut(); _visitor.visit_pat(&mut it) };
     // Skipped field _i . dot2_token;
     // Skipped field _i . comma_token;
@@ -1638,7 +1650,7 @@
 }
 
 pub fn walk_poly_trait_ref<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut PolyTraitRef) {
-    // Skipped field _i . bound_lifetimes;
+    if let Some(ref mut it) = _i . bound_lifetimes { _visitor.visit_bound_lifetimes(&mut * it) };
     _visitor.visit_path(&mut _i . trait_ref);
 }
 
@@ -1728,7 +1740,7 @@
 # [ cfg ( feature = "full" ) ]
 pub fn walk_trait_item_method<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut TraitItemMethod) {
     _visitor.visit_method_sig(&mut _i . sig);
-    // Skipped field _i . default;
+    if let Some(ref mut it) = _i . default { _visitor.visit_block(&mut * it) };
     // Skipped field _i . semi_token;
 }
 # [ cfg ( feature = "full" ) ]
@@ -1824,7 +1836,7 @@
     // Skipped field _i . colon_token;
     for mut el in (_i . bounds).iter_mut() { let mut it = el.item_mut(); _visitor.visit_ty_param_bound(&mut it) };
     // Skipped field _i . eq_token;
-    // Skipped field _i . default;
+    if let Some(ref mut it) = _i . default { _visitor.visit_ty(&mut * it) };
 }
 
 pub fn walk_ty_param_bound<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut TyParamBound) {
@@ -1846,7 +1858,7 @@
 }
 
 pub fn walk_ty_path<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut TyPath) {
-    // Skipped field _i . qself;
+    if let Some(ref mut it) = _i . qself { _visitor.visit_qself(&mut * it) };
     _visitor.visit_path(&mut _i . path);
 }
 
@@ -1912,7 +1924,7 @@
     // Skipped field _i . ident;
     for mut it in (_i . attrs).iter_mut() { _visitor.visit_attribute(&mut it) };
     _visitor.visit_variant_data(&mut _i . data);
-    // Skipped field _i . discriminant;
+    if let Some(ref mut it) = _i . discriminant { _visitor.visit_expr(&mut * it) };
     // Skipped field _i . eq_token;
 }
 
@@ -1985,7 +1997,7 @@
 }
 
 pub fn walk_where_bound_predicate<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut WhereBoundPredicate) {
-    // Skipped field _i . bound_lifetimes;
+    if let Some(ref mut it) = _i . bound_lifetimes { _visitor.visit_bound_lifetimes(&mut * it) };
     _visitor.visit_ty(&mut _i . bounded_ty);
     // Skipped field _i . colon_token;
     for mut el in (_i . bounds).iter_mut() { let mut it = el.item_mut(); _visitor.visit_ty_param_bound(&mut it) };
diff --git a/syn_codegen/src/main.rs b/syn_codegen/src/main.rs
index 1ca357f..95fc2bc 100644
--- a/syn_codegen/src/main.rs
+++ b/syn_codegen/src/main.rs
@@ -451,18 +451,56 @@
         None
     }
 
+    fn option_visit(
+        seg: &PathSegment,
+        lookup: &Lookup,
+        kind: Kind,
+        name: &Tokens,
+        eos_full: &mut bool,
+    ) -> Option<String> {
+        if let Some(res) = vec_visit(seg, lookup, kind, name, eos_full) {
+            return Some(res);
+        }
+
+        if seg.ident == "Option" {
+            let ty = first_param(&seg.parameters);
+            if let Some(seg) = last_segment(ty) {
+                let it = match kind {
+                    Kind::Fold => quote!(it),
+                    _ => quote!(*it),
+                };
+                if let Some(val) = vec_visit(seg, lookup, kind, &it, eos_full) {
+                    return Some(match kind {
+                        Kind::Visit => format!(
+                            "if let Some(ref it) = {name} {{ {val} }}",
+                            name = name,
+                            val = val,
+                        ),
+                        Kind::VisitMut => format!(
+                            "if let Some(ref mut it) = {name} {{ {val} }}",
+                            name = name,
+                            val = val,
+                        ),
+                        Kind::Fold => format!(
+                            "({name}).map(|it| {{ {val} }})",
+                            name = name,
+                            val = val,
+                        ),
+                    });
+                }
+            }
+        }
+
+        None
+    }
+
     fn visit(ty: &Ty, lookup: &Lookup, kind: Kind, name: &Tokens) -> String {
         if let Some(seg) = last_segment(ty) {
             let mut eos_full = false;
-            if let Some(res) = vec_visit(seg, lookup, kind, name, &mut eos_full) {
+            if let Some(res) = option_visit(seg, lookup, kind, name, &mut eos_full) {
                 if eos_full {
                     return format!(
-                        "{{ \
-                         #[cfg(feature = \"full\")] \
-                         {{ {res} }} \
-                         #[cfg(not(feature = \"full\"))] \
-                         unreachable!() \
-                         }}",
+                        "full!({res})",
                         res = res);
                 }
                 return res;
@@ -687,6 +725,18 @@
         codegen::generate(&mut state, &lookup, s);
     }
 
+    let full_macro = "
+#[cfg(feature = \"full\")]
+macro_rules! full {
+    ($e:expr) => { $e }
+}
+
+#[cfg(not(feature = \"full\"))]
+macro_rules! full {
+    ($e:expr) => { unreachable!() }
+}
+";
+
     let mut fold_file = File::create(FOLD_SRC).unwrap();
     write!(fold_file, "
 // THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT
@@ -722,6 +772,8 @@
     }}
 }}
 
+{full_macro}
+
 /// AST->AST fold.
 ///
 /// Each method of the Folder trait is a hook to be potentially overridden. Each
@@ -740,8 +792,9 @@
 
 {fold_impl}
 ",
-            fold_trait = state.fold_trait,
-            fold_impl = state.fold_impl).unwrap();
+           full_macro = full_macro,
+           fold_trait = state.fold_trait,
+           fold_impl = state.fold_impl).unwrap();
 
     let mut visit_file = File::create(VISIT_SRC).unwrap();
     write!(visit_file, "
@@ -754,6 +807,8 @@
 
 use super::*;
 
+{full_macro}
+
 /// Each method of the Visitor trait is a hook to be potentially
 /// overridden.  Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -769,8 +824,9 @@
 
 {visit_impl}
 ",
-            visit_trait = state.visit_trait,
-            visit_impl = state.visit_impl).unwrap();
+           full_macro = full_macro,
+           visit_trait = state.visit_trait,
+           visit_impl = state.visit_impl).unwrap();
 
     let mut visit_mut_file = File::create(VISIT_MUT_SRC).unwrap();
     write!(visit_mut_file, "
@@ -783,6 +839,8 @@
 
 use super::*;
 
+{full_macro}
+
 /// Each method of the VisitorMut trait is a hook to be potentially
 /// overridden.  Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -798,6 +856,7 @@
 
 {visit_mut_impl}
 ",
-            visit_mut_trait = state.visit_mut_trait,
-            visit_mut_impl = state.visit_mut_impl).unwrap();
+           full_macro = full_macro,
+           visit_mut_trait = state.visit_mut_trait,
+           visit_mut_impl = state.visit_mut_impl).unwrap();
 }