Merge branch master into next
diff --git a/codegen/src/main.rs b/codegen/src/main.rs
index 4a7ec38..9f884b9 100644
--- a/codegen/src/main.rs
+++ b/codegen/src/main.rs
@@ -54,13 +54,9 @@
 const TERMINAL_TYPES: &[&str] = &["Span", "Ident"];
 
 fn path_eq(a: &syn::Path, b: &str) -> bool {
-    if a.global() {
-        return false;
-    }
-    if a.segments.len() != 1 {
-        return false;
-    }
-    a.segments[0].ident == b
+    a.leading_colon.is_none()
+        && a.segments.len() == 1
+        && a.segments[0].ident == b
 }
 
 fn get_features(attrs: &[Attribute], mut features: TokenStream) -> TokenStream {
@@ -149,15 +145,15 @@
                 // Try to parse the AstItem declaration out of the item.
                 let tts = &item.mac.tts;
                 let found = if path_eq(&item.mac.path, "ast_struct") {
-                    syn::parse_str::<parsing::AstStruct>(&quote!(#tts).to_string())
+                    syn::parse2::<parsing::AstStruct>(quote!(#tts))
                         .map_err(|_| err_msg("failed to parse ast_struct"))?
                         .0
                 } else if path_eq(&item.mac.path, "ast_enum") {
-                    syn::parse_str::<parsing::AstEnum>(&quote!(#tts).to_string())
+                    syn::parse2::<parsing::AstEnum>(quote!(#tts))
                         .map_err(|_| err_msg("failed to parse ast_enum"))?
                         .0
                 } else if path_eq(&item.mac.path, "ast_enum_of_structs") {
-                    syn::parse_str::<parsing::AstEnumOfStructs>(&quote!(#tts).to_string())
+                    syn::parse2::<parsing::AstEnumOfStructs>(quote!(#tts))
                         .map_err(|_| err_msg("failed to parse ast_enum_of_structs"))?
                         .0
                 } else {
@@ -204,85 +200,95 @@
 
     use proc_macro2::TokenStream;
     use syn;
-    use syn::synom::*;
+    use syn::parse::{Parse, ParseStream, Result};
     use syn::*;
 
+    fn peek_tag(input: ParseStream, tag: &str) -> bool {
+        let ahead = input.fork();
+        ahead.parse::<Token![#]>().is_ok() && ahead
+            .parse::<Ident>()
+            .map(|ident| ident == tag)
+            .unwrap_or(false)
+    }
+
     // Parses #full - returns #[cfg(feature = "full")] if it is present, and
     // nothing otherwise.
-    named!(full -> (TokenStream, bool), map!(option!(do_parse!(
-        punct!(#) >>
-        id: syn!(Ident) >>
-        cond_reduce!(id == "full") >>
-        ()
-    )), |s| if s.is_some() {
-        (quote!(#[cfg(feature = "full")]), true)
-    } else {
-        (quote!(), false)
-    }));
+    fn full(input: ParseStream) -> (TokenStream, bool) {
+        if peek_tag(input, "full") {
+            input.parse::<Token![#]>().unwrap();
+            input.parse::<Ident>().unwrap();
+            (quote!(#[cfg(feature = "full")]), true)
+        } else {
+            (quote!(), false)
+        }
+    }
 
-    named!(manual_extra_traits -> (), do_parse!(
-        punct!(#) >>
-        id: syn!(Ident) >>
-        cond_reduce!(id == "manual_extra_traits") >>
-        ()
-    ));
+    fn skip_manual_extra_traits(input: ParseStream) {
+        if peek_tag(input, "manual_extra_traits") {
+            input.parse::<Token![#]>().unwrap();
+            input.parse::<Ident>().unwrap();
+        }
+    }
 
     // Parses a simple AstStruct without the `pub struct` prefix.
-    named!(ast_struct_inner -> AstItem, do_parse!(
-        id: syn!(Ident) >>
-        features: full >>
-        option!(manual_extra_traits) >>
-        rest: syn!(TokenStream) >>
-        (AstItem {
-            ast: syn::parse_str(&quote! {
-                pub struct #id #rest
-            }.to_string())?,
-            features: features.0,
-            eos_full: features.1,
+    fn ast_struct_inner(input: ParseStream) -> Result<AstItem> {
+        let ident: Ident = input.parse()?;
+        let (features, eos_full) = full(input);
+        skip_manual_extra_traits(input);
+        let rest: TokenStream = input.parse()?;
+        Ok(AstItem {
+            ast: syn::parse2(quote! {
+                pub struct #ident #rest
+            })?,
+            features: features,
+            eos_full: eos_full,
         })
-    ));
+    }
 
     // ast_struct! parsing
     pub struct AstStruct(pub Vec<AstItem>);
-    impl Synom for AstStruct {
-        named!(parse -> Self, do_parse!(
-            many0!(Attribute::parse_outer) >>
-            keyword!(pub) >>
-            keyword!(struct) >>
-            res: call!(ast_struct_inner) >>
-            (AstStruct(vec![res]))
-        ));
+    impl Parse for AstStruct {
+        fn parse(input: ParseStream) -> Result<Self> {
+            input.call(Attribute::parse_outer)?;
+            input.parse::<Token![pub]>()?;
+            input.parse::<Token![struct]>()?;
+            let res = input.call(ast_struct_inner)?;
+            Ok(AstStruct(vec![res]))
+        }
     }
 
-    named!(no_visit -> (), do_parse!(
-        punct!(#) >>
-        id: syn!(Ident) >>
-        cond_reduce!(id == "no_visit") >>
-        ()
-    ));
+    fn no_visit(input: ParseStream) -> bool {
+        if peek_tag(input, "no_visit") {
+            input.parse::<Token![#]>().unwrap();
+            input.parse::<Ident>().unwrap();
+            true
+        } else {
+            false
+        }
+    }
 
     // ast_enum! parsing
     pub struct AstEnum(pub Vec<AstItem>);
-    impl Synom for AstEnum {
-        named!(parse -> Self, do_parse!(
-            many0!(Attribute::parse_outer) >>
-            keyword!(pub) >>
-            keyword!(enum) >>
-            id: syn!(Ident) >>
-            no_visit: option!(no_visit) >>
-            rest: syn!(TokenStream) >>
-            (AstEnum(if no_visit.is_some() {
+    impl Parse for AstEnum {
+        fn parse(input: ParseStream) -> Result<Self> {
+            input.call(Attribute::parse_outer)?;
+            input.parse::<Token![pub]>()?;
+            input.parse::<Token![enum]>()?;
+            let ident: Ident = input.parse()?;
+            let no_visit = no_visit(input);
+            let rest: TokenStream = input.parse()?;
+            Ok(AstEnum(if no_visit {
                 vec![]
             } else {
                 vec![AstItem {
-                    ast: syn::parse_str(&quote! {
-                        pub enum #id #rest
-                    }.to_string())?,
+                    ast: syn::parse2(quote! {
+                        pub enum #ident #rest
+                    })?,
                     features: quote!(),
                     eos_full: false,
                 }]
             }))
-        ));
+        }
     }
 
     // A single variant of an ast_enum_of_structs!
@@ -291,57 +297,73 @@
         member: Option<Path>,
         inner: Option<AstItem>,
     }
-    named!(eos_variant -> EosVariant, do_parse!(
-        many0!(Attribute::parse_outer) >>
-        keyword!(pub) >>
-        variant: syn!(Ident) >>
-        member: option!(map!(parens!(alt!(
-            call!(ast_struct_inner) => { |x: AstItem| (Path::from(x.ast.ident.clone()), Some(x)) }
-            |
-            syn!(Path) => { |x| (x, None) }
-        )), |x| x.1)) >>
-        punct!(,) >>
-        (EosVariant {
+    fn eos_variant(input: ParseStream) -> Result<EosVariant> {
+        input.call(Attribute::parse_outer)?;
+        input.parse::<Token![pub]>()?;
+        let variant: Ident = input.parse()?;
+        let (member, inner) = if input.peek(token::Paren) {
+            let content;
+            parenthesized!(content in input);
+            if content.fork().call(ast_struct_inner).is_ok() {
+                let item = content.call(ast_struct_inner)?;
+                (Some(Path::from(item.ast.ident.clone())), Some(item))
+            } else {
+                let path: Path = content.parse()?;
+                (Some(path), None)
+            }
+        } else {
+            (None, None)
+        };
+        input.parse::<Token![,]>()?;
+        Ok(EosVariant {
             name: variant,
-            member: member.clone().map(|x| x.0),
-            inner: member.map(|x| x.1).unwrap_or_default(),
+            member: member,
+            inner: inner,
         })
-    ));
+    }
 
     // ast_enum_of_structs! parsing
     pub struct AstEnumOfStructs(pub Vec<AstItem>);
-    impl Synom for AstEnumOfStructs {
-        named!(parse -> Self, do_parse!(
-            many0!(Attribute::parse_outer) >>
-            keyword!(pub) >>
-            keyword!(enum) >>
-            id: syn!(Ident) >>
-            variants: braces!(many0!(eos_variant)) >>
-            option!(syn!(Ident)) >> // do_not_generate_to_tokens
-            ({
-                let enum_item = {
-                    let variants = variants.1.iter().map(|v| {
-                        let name = v.name.clone();
-                        match v.member {
-                            Some(ref member) => quote!(#name(#member)),
-                            None => quote!(#name),
-                        }
-                    });
-                    parse_quote! {
-                        pub enum #id {
-                            #(#variants),*
-                        }
+    impl Parse for AstEnumOfStructs {
+        fn parse(input: ParseStream) -> Result<Self> {
+            input.call(Attribute::parse_outer)?;
+            input.parse::<Token![pub]>()?;
+            input.parse::<Token![enum]>()?;
+            let ident: Ident = input.parse()?;
+
+            let content;
+            braced!(content in input);
+            let mut variants = Vec::new();
+            while !content.is_empty() {
+                variants.push(content.call(eos_variant)?);
+            }
+
+            if let Some(ident) = input.parse::<Option<Ident>>()? {
+                assert_eq!(ident, "do_not_generate_to_tokens");
+            }
+
+            let enum_item = {
+                let variants = variants.iter().map(|v| {
+                    let name = v.name.clone();
+                    match v.member {
+                        Some(ref member) => quote!(#name(#member)),
+                        None => quote!(#name),
                     }
-                };
-                let mut items = vec![AstItem {
-                    ast: enum_item,
-                    features: quote!(),
-                    eos_full:  false,
-                }];
-                items.extend(variants.1.into_iter().filter_map(|v| v.inner));
-                AstEnumOfStructs(items)
-            })
-        ));
+                });
+                parse_quote! {
+                    pub enum #ident {
+                        #(#variants),*
+                    }
+                }
+            };
+            let mut items = vec![AstItem {
+                ast: enum_item,
+                features: quote!(),
+                eos_full: false,
+            }];
+            items.extend(variants.into_iter().filter_map(|v| v.inner));
+            Ok(AstEnumOfStructs(items))
+        }
     }
 }
 
@@ -350,6 +372,8 @@
     use inflections::Inflect;
     use proc_macro2::{Span, TokenStream};
     use quote::{ToTokens, TokenStreamExt};
+    use syn::ext::IdentExt;
+    use syn::parse::Parser;
     use syn::punctuated::Punctuated;
     use syn::*;
 
@@ -374,7 +398,9 @@
         Option(&'a Type),
         Tuple(&'a Punctuated<Type, Token![,]>),
         Simple(&'a AstItem),
-        Token(TokenStream),
+        TokenPunct(TokenStream),
+        TokenKeyword(TokenStream),
+        TokenGroup(Ident),
         Pass,
     }
 
@@ -391,7 +417,7 @@
                     "Punctuated" => RelevantType::Punctuated(first_arg(&last.arguments)),
                     "Option" => RelevantType::Option(first_arg(&last.arguments)),
                     "Brace" | "Bracket" | "Paren" | "Group" => {
-                        RelevantType::Token(last.ident.clone().into_token_stream())
+                        RelevantType::TokenGroup(last.ident.clone())
                     }
                     _ => {
                         if let Some(item) = lookup.get(&last.ident) {
@@ -406,7 +432,13 @@
             Type::Macro(TypeMacro { ref mac })
                 if mac.path.segments.last().unwrap().into_value().ident == "Token" =>
             {
-                RelevantType::Token(mac.into_token_stream())
+                let is_ident = Ident::parse_any.parse2(mac.tts.clone()).is_ok();
+                let is_underscore = parse2::<Token![_]>(mac.tts.clone()).is_ok();
+                if is_ident && !is_underscore {
+                    RelevantType::TokenKeyword(mac.into_token_stream())
+                } else {
+                    RelevantType::TokenPunct(mac.into_token_stream())
+                }
             }
             _ => RelevantType::Pass,
         }
@@ -642,17 +674,47 @@
         })
     }
 
-    fn token_visit(ty: TokenStream, kind: Kind, name: &Operand) -> TokenStream {
+    fn token_punct_visit(ty: TokenStream, kind: Kind, name: &Operand) -> TokenStream {
         let name = name.tokens();
         match kind {
             Fold => quote! {
-                #ty(tokens_helper(_visitor, &(#name).0))
+                #ty(tokens_helper(_visitor, &#name.spans))
             },
             Visit => quote! {
-                tokens_helper(_visitor, &(#name).0)
+                tokens_helper(_visitor, &#name.spans)
             },
             VisitMut => quote! {
-                tokens_helper(_visitor, &mut (#name).0)
+                tokens_helper(_visitor, &mut #name.spans)
+            },
+        }
+    }
+
+    fn token_keyword_visit(ty: TokenStream, kind: Kind, name: &Operand) -> TokenStream {
+        let name = name.tokens();
+        match kind {
+            Fold => quote! {
+                #ty(tokens_helper(_visitor, &#name.span))
+            },
+            Visit => quote! {
+                tokens_helper(_visitor, &#name.span)
+            },
+            VisitMut => quote! {
+                tokens_helper(_visitor, &mut #name.span)
+            },
+        }
+    }
+
+    fn token_group_visit(ty: Ident, kind: Kind, name: &Operand) -> TokenStream {
+        let name = name.tokens();
+        match kind {
+            Fold => quote! {
+                #ty(tokens_helper(_visitor, &#name.span))
+            },
+            Visit => quote! {
+                tokens_helper(_visitor, &#name.span)
+            },
+            VisitMut => quote! {
+                tokens_helper(_visitor, &mut #name.span)
             },
         }
     }
@@ -686,7 +748,9 @@
                     res
                 })
             }
-            RelevantType::Token(ty) => Some(token_visit(ty, kind, name)),
+            RelevantType::TokenPunct(ty) => Some(token_punct_visit(ty, kind, name)),
+            RelevantType::TokenKeyword(ty) => Some(token_keyword_visit(ty, kind, name)),
+            RelevantType::TokenGroup(ty) => Some(token_group_visit(ty, kind, name)),
             RelevantType::Pass => None,
         }
     }
diff --git a/examples/heapsize/example/src/main.rs b/examples/heapsize/example/src/main.rs
index 9c9d88a..f29d237 100644
--- a/examples/heapsize/example/src/main.rs
+++ b/examples/heapsize/example/src/main.rs
@@ -21,10 +21,12 @@
     };
 
     // 10 + 0 + 0 + 6 = 16
-    println!("heap size = {} + {} + {} + {} = {}",
+    println!(
+        "heap size = {} + {} + {} + {} = {}",
         demo.a.heap_size_of_children(),
         demo.b.heap_size_of_children(),
         demo.c.heap_size_of_children(),
         demo.d.heap_size_of_children(),
-        demo.heap_size_of_children());
+        demo.heap_size_of_children()
+    );
 }
diff --git a/examples/heapsize/heapsize_derive/src/lib.rs b/examples/heapsize/heapsize_derive/src/lib.rs
index 68055e5..e4435b4 100644
--- a/examples/heapsize/heapsize_derive/src/lib.rs
+++ b/examples/heapsize/heapsize_derive/src/lib.rs
@@ -8,7 +8,7 @@
 extern crate quote;
 
 use proc_macro2::TokenStream;
-use syn::{DeriveInput, Data, Fields, Generics, GenericParam};
+use syn::{Data, DeriveInput, Fields, GenericParam, Generics};
 
 #[proc_macro_derive(HeapSize)]
 pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
diff --git a/examples/heapsize2/example/src/main.rs b/examples/heapsize2/example/src/main.rs
index 1c66692..e424c11 100644
--- a/examples/heapsize2/example/src/main.rs
+++ b/examples/heapsize2/example/src/main.rs
@@ -25,5 +25,8 @@
             e: "String".to_owned(),
         },
     };
-    println!("heap size = {}", heapsize::HeapSize::heap_size_of_children(&demo));
+    println!(
+        "heap size = {}",
+        heapsize::HeapSize::heap_size_of_children(&demo)
+    );
 }
diff --git a/examples/heapsize2/heapsize_derive/src/lib.rs b/examples/heapsize2/heapsize_derive/src/lib.rs
index 87bb60e..4b46c1f 100644
--- a/examples/heapsize2/heapsize_derive/src/lib.rs
+++ b/examples/heapsize2/heapsize_derive/src/lib.rs
@@ -8,8 +8,8 @@
 extern crate quote;
 
 use proc_macro2::{Span, TokenStream};
-use syn::{DeriveInput, Data, Fields, Generics, GenericParam, Index};
 use syn::spanned::Spanned;
+use syn::{Data, DeriveInput, Fields, GenericParam, Generics, Index};
 
 #[proc_macro_derive(HeapSize)]
 pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
@@ -84,7 +84,10 @@
                     //
                     //     0 + HeapSize::heap_size(&self.0) + HeapSize::heap_size(&self.1)
                     let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| {
-                        let index = Index { index: i as u32, span: call_site };
+                        let index = Index {
+                            index: i as u32,
+                            span: call_site,
+                        };
                         let access = quote_spanned!(call_site=> #var.#index);
                         quote_spanned! {f.span()=>
                             ::heapsize::HeapSize::heap_size_of_children(&#access)
diff --git a/examples/lazy-static/example/src/main.rs b/examples/lazy-static/example/src/main.rs
index 16cfb36..4c3a160 100644
--- a/examples/lazy-static/example/src/main.rs
+++ b/examples/lazy-static/example/src/main.rs
@@ -1,5 +1,3 @@
-#![feature(proc_macro)]
-
 extern crate lazy_static;
 extern crate regex;
 
diff --git a/examples/lazy-static/lazy-static/src/lib.rs b/examples/lazy-static/lazy-static/src/lib.rs
index 4d4131f..e324905 100644
--- a/examples/lazy-static/lazy-static/src/lib.rs
+++ b/examples/lazy-static/lazy-static/src/lib.rs
@@ -1,5 +1,5 @@
 #![recursion_limit = "128"]
-#![feature(proc_macro)]
+#![feature(proc_macro_diagnostic)]
 
 #[macro_use]
 extern crate syn;
@@ -7,10 +7,10 @@
 extern crate quote;
 extern crate proc_macro;
 
-use syn::{Visibility, Ident, Type, Expr};
-use syn::synom::Synom;
-use syn::spanned::Spanned;
 use proc_macro::TokenStream;
+use syn::parse::{Parse, ParseStream, Result};
+use syn::spanned::Spanned;
+use syn::{Expr, Ident, Type, Visibility};
 
 /// Parses the following syntax, which aligns with the input of the real
 /// `lazy_static` crate.
@@ -31,24 +31,34 @@
     init: Expr,
 }
 
-impl Synom for LazyStatic {
-    named!(parse -> Self, do_parse!(
-        visibility: syn!(Visibility) >>
-        keyword!(static) >>
-        keyword!(ref) >>
-        name: syn!(Ident) >>
-        punct!(:) >>
-        ty: syn!(Type) >>
-        punct!(=) >>
-        init: syn!(Expr) >>
-        punct!(;) >>
-        (LazyStatic { visibility, name, ty, init })
-    ));
+impl Parse for LazyStatic {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let visibility: Visibility = input.parse()?;
+        input.parse::<Token![static]>()?;
+        input.parse::<Token![ref]>()?;
+        let name: Ident = input.parse()?;
+        input.parse::<Token![:]>()?;
+        let ty: Type = input.parse()?;
+        input.parse::<Token![=]>()?;
+        let init: Expr = input.parse()?;
+        input.parse::<Token![;]>()?;
+        Ok(LazyStatic {
+            visibility,
+            name,
+            ty,
+            init,
+        })
+    }
 }
 
 #[proc_macro]
 pub fn lazy_static(input: TokenStream) -> TokenStream {
-    let LazyStatic { visibility, name, ty, init } = syn::parse(input).unwrap();
+    let LazyStatic {
+        visibility,
+        name,
+        ty,
+        init,
+    } = syn::parse(input).unwrap();
 
     // The warning looks like this.
     //
@@ -58,7 +68,8 @@
     //     10 |     static ref FOO: String = "lazy_static".to_owned();
     //        |                ^^^
     if name == "FOO" {
-        name.span().unstable()
+        name.span()
+            .unstable()
             .warning("come on, pick a more creative name")
             .emit();
     }
@@ -72,7 +83,8 @@
     //        |                           ^^
     if let Expr::Tuple(ref init) = init {
         if init.elems.is_empty() {
-            init.span().unstable()
+            init.span()
+                .unstable()
                 .error("I can't think of a legitimate use for lazily initializing the value `()`")
                 .emit();
             return TokenStream::new();
diff --git a/examples/trace-var/example/src/main.rs b/examples/trace-var/example/src/main.rs
index c9371f3..3e069ae 100644
--- a/examples/trace-var/example/src/main.rs
+++ b/examples/trace-var/example/src/main.rs
@@ -1,5 +1,3 @@
-#![feature(proc_macro)]
-
 extern crate trace_var;
 use trace_var::trace_var;
 
diff --git a/examples/trace-var/trace-var/src/lib.rs b/examples/trace-var/trace-var/src/lib.rs
index 5fb6ccf..6cf0a3c 100644
--- a/examples/trace-var/trace-var/src/lib.rs
+++ b/examples/trace-var/trace-var/src/lib.rs
@@ -1,5 +1,3 @@
-#![feature(proc_macro)]
-
 extern crate proc_macro;
 
 #[macro_use]
@@ -12,30 +10,30 @@
 use quote::ToTokens;
 use std::collections::HashSet as Set;
 use syn::fold::{self, Fold};
+use syn::parse::{Parse, ParseStream, Result};
 use syn::punctuated::Punctuated;
-use syn::synom::Synom;
 use syn::{Expr, Ident, ItemFn, Local, Pat, Stmt};
 
-/// Parses a parenthesized nonempty list of variable names separated by commas.
+/// Parses a list of variable names separated by commas.
 ///
-///     (a, b, c)
+///     a, b, c
 ///
 /// This is how the compiler passes in arguments to our attribute -- it is
-/// everything that comes after the attribute name.
+/// everything inside the delimiters after the attribute name.
 ///
 ///     #[trace_var(a, b, c)]
-///                ^^^^^^^^^
+///                 ^^^^^^^
 struct Args {
     vars: Set<Ident>,
 }
 
-impl Synom for Args {
-    named!(parse -> Self, map!(
-        call!(Punctuated::<Ident, Token![,]>::parse_terminated_nonempty),
-        |vars| Args {
+impl Parse for Args {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let vars = Punctuated::<Ident, Token![,]>::parse_terminated(input)?;
+        Ok(Args {
             vars: vars.into_iter().collect(),
-        }
-    ));
+        })
+    }
 }
 
 impl Args {
diff --git a/rustfmt.toml b/rustfmt.toml
deleted file mode 100644
index b2715b2..0000000
--- a/rustfmt.toml
+++ /dev/null
@@ -1 +0,0 @@
-wrap_comments = true
diff --git a/src/attr.rs b/src/attr.rs
index d818b4f..595f12a 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -13,6 +13,8 @@
 
 use proc_macro2::{Delimiter, Spacing, TokenStream, TokenTree};
 
+#[cfg(feature = "parsing")]
+use parse::{ParseStream, Result};
 #[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
 #[cfg(feature = "extra-traits")]
@@ -39,8 +41,8 @@
     ///
     /// The `style` field of type `AttrStyle` distinguishes whether an attribute
     /// is outer or inner. Doc comments and block comments are promoted to
-    /// attributes that have `is_sugared_doc` set to true, as this is how they
-    /// are processed by the compiler and by `macro_rules!` macros.
+    /// attributes, as this is how they are processed by the compiler and by
+    /// `macro_rules!` macros.
     ///
     /// The `path` field gives the possibly colon-delimited path against which
     /// the attribute is resolved. It is equal to `"doc"` for desugared doc
@@ -58,13 +60,57 @@
     /// across most Rust libraries.
     ///
     /// [`interpret_meta`]: #method.interpret_meta
+    ///
+    /// # Parsing
+    ///
+    /// This type does not implement the [`Parse`] trait and thus cannot be
+    /// parsed directly by [`ParseStream::parse`]. Instead use
+    /// [`ParseStream::call`] with one of the two parser functions
+    /// [`Attribute::parse_outer`] or [`Attribute::parse_inner`] depending on
+    /// which you intend to parse.
+    ///
+    /// [`Parse`]: parse/trait.Parse.html
+    /// [`ParseStream::parse`]: parse/struct.ParseBuffer.html#method.parse
+    /// [`ParseStream::call`]: parse/struct.ParseBuffer.html#method.call
+    /// [`Attribute::parse_outer`]: #method.parse_outer
+    /// [`Attribute::parse_inner`]: #method.parse_inner
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{Attribute, Ident, Token};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    ///
+    /// // Parses a unit struct with attributes.
+    /// //
+    /// //     #[path = "s.tmpl"]
+    /// //     struct S;
+    /// struct UnitStruct {
+    ///     attrs: Vec<Attribute>,
+    ///     struct_token: Token![struct],
+    ///     name: Ident,
+    ///     semi_token: Token![;],
+    /// }
+    ///
+    /// impl Parse for UnitStruct {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         Ok(UnitStruct {
+    ///             attrs: input.call(Attribute::parse_outer)?,
+    ///             struct_token: input.parse()?,
+    ///             name: input.parse()?,
+    ///             semi_token: input.parse()?,
+    ///         })
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
     pub struct Attribute #manual_extra_traits {
         pub pound_token: Token![#],
         pub style: AttrStyle,
         pub bracket_token: token::Bracket,
         pub path: Path,
         pub tts: TokenStream,
-        pub is_sugared_doc: bool,
     }
 }
 
@@ -79,7 +125,6 @@
             && self.bracket_token == other.bracket_token
             && self.path == other.path
             && TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
-            && self.is_sugared_doc == other.is_sugared_doc
     }
 }
 
@@ -94,7 +139,6 @@
         self.bracket_token.hash(state);
         self.path.hash(state);
         TokenStreamHelper(&self.tts).hash(state);
-        self.is_sugared_doc.hash(state);
     }
 }
 
@@ -129,6 +173,32 @@
         None
     }
 
+    /// Parses zero or more outer attributes from the stream.
+    ///
+    /// *This function is available if Syn is built with the `"parsing"`
+    /// feature.*
+    #[cfg(feature = "parsing")]
+    pub fn parse_outer(input: ParseStream) -> Result<Vec<Self>> {
+        let mut attrs = Vec::new();
+        while input.peek(Token![#]) {
+            attrs.push(input.call(parsing::single_parse_outer)?);
+        }
+        Ok(attrs)
+    }
+
+    /// Parses zero or more inner attributes from the stream.
+    ///
+    /// *This function is available if Syn is built with the `"parsing"`
+    /// feature.*
+    #[cfg(feature = "parsing")]
+    pub fn parse_inner(input: ParseStream) -> Result<Vec<Self>> {
+        let mut attrs = Vec::new();
+        while input.peek(Token![#]) && input.peek2(Token![!]) {
+            attrs.push(input.call(parsing::single_parse_inner)?);
+        }
+        Ok(attrs)
+    }
+
     fn extract_meta_list(ident: Ident, tt: &TokenTree) -> Option<Meta> {
         let g = match *tt {
             TokenTree::Group(ref g) => g,
@@ -396,122 +466,39 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use buffer::Cursor;
-    use parse_error;
-    use proc_macro2::{Literal, Punct, Spacing, Span, TokenTree};
-    use synom::PResult;
 
-    fn eq(span: Span) -> TokenTree {
-        let mut op = Punct::new('=', Spacing::Alone);
-        op.set_span(span);
-        op.into()
+    use parse::{ParseStream, Result};
+    #[cfg(feature = "full")]
+    use private;
+
+    pub fn single_parse_inner(input: ParseStream) -> Result<Attribute> {
+        let content;
+        Ok(Attribute {
+            pound_token: input.parse()?,
+            style: AttrStyle::Inner(input.parse()?),
+            bracket_token: bracketed!(content in input),
+            path: content.call(Path::parse_mod_style)?,
+            tts: content.parse()?,
+        })
     }
 
-    impl Attribute {
-        named!(pub parse_inner -> Self, alt!(
-            do_parse!(
-                pound: punct!(#) >>
-                bang: punct!(!) >>
-                path_and_tts: brackets!(tuple!(
-                    call!(Path::parse_mod_style),
-                    syn!(TokenStream),
-                )) >>
-                ({
-                    let (bracket, (path, tts)) = path_and_tts;
-
-                    Attribute {
-                        style: AttrStyle::Inner(bang),
-                        path: path,
-                        tts: tts,
-                        is_sugared_doc: false,
-                        pound_token: pound,
-                        bracket_token: bracket,
-                    }
-                })
-            )
-            |
-            map!(
-                call!(lit_doc_comment, Comment::Inner),
-                |lit| {
-                    let span = lit.span();
-                    Attribute {
-                        style: AttrStyle::Inner(<Token![!]>::new(span)),
-                        path: Ident::new("doc", span).into(),
-                        tts: vec![
-                            eq(span),
-                            lit,
-                        ].into_iter().collect(),
-                        is_sugared_doc: true,
-                        pound_token: <Token![#]>::new(span),
-                        bracket_token: token::Bracket(span),
-                    }
-                }
-            )
-        ));
-
-        named!(pub parse_outer -> Self, alt!(
-            do_parse!(
-                pound: punct!(#) >>
-                path_and_tts: brackets!(tuple!(
-                    call!(Path::parse_mod_style),
-                    syn!(TokenStream),
-                )) >>
-                ({
-                    let (bracket, (path, tts)) = path_and_tts;
-
-                    Attribute {
-                        style: AttrStyle::Outer,
-                        path: path,
-                        tts: tts,
-                        is_sugared_doc: false,
-                        pound_token: pound,
-                        bracket_token: bracket,
-                    }
-                })
-            )
-            |
-            map!(
-                call!(lit_doc_comment, Comment::Outer),
-                |lit| {
-                    let span = lit.span();
-                    Attribute {
-                        style: AttrStyle::Outer,
-                        path: Ident::new("doc", span).into(),
-                        tts: vec![
-                            eq(span),
-                            lit,
-                        ].into_iter().collect(),
-                        is_sugared_doc: true,
-                        pound_token: <Token![#]>::new(span),
-                        bracket_token: token::Bracket(span),
-                    }
-                }
-            )
-        ));
+    pub fn single_parse_outer(input: ParseStream) -> Result<Attribute> {
+        let content;
+        Ok(Attribute {
+            pound_token: input.parse()?,
+            style: AttrStyle::Outer,
+            bracket_token: bracketed!(content in input),
+            path: content.call(Path::parse_mod_style)?,
+            tts: content.parse()?,
+        })
     }
 
-    enum Comment {
-        Inner,
-        Outer,
-    }
-
-    fn lit_doc_comment(input: Cursor, style: Comment) -> PResult<TokenTree> {
-        match input.literal() {
-            Some((lit, rest)) => {
-                let string = lit.to_string();
-                let ok = match style {
-                    Comment::Inner => string.starts_with("//!") || string.starts_with("/*!"),
-                    Comment::Outer => string.starts_with("///") || string.starts_with("/**"),
-                };
-                if ok {
-                    let mut new = Literal::string(&string);
-                    new.set_span(lit.span());
-                    Ok((new.into(), rest))
-                } else {
-                    parse_error()
-                }
-            }
-            _ => parse_error(),
+    #[cfg(feature = "full")]
+    impl private {
+        pub fn attrs(outer: Vec<Attribute>, inner: Vec<Attribute>) -> Vec<Attribute> {
+            let mut attrs = outer;
+            attrs.extend(inner);
+            attrs
         }
     }
 }
diff --git a/src/buffer.rs b/src/buffer.rs
index 499c4f1..b918a9a 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -9,119 +9,7 @@
 //! A stably addressed token buffer supporting efficient traversal based on a
 //! cheaply copyable cursor.
 //!
-//! The [`Synom`] trait is implemented for syntax tree types that can be parsed
-//! from one of these token cursors.
-//!
-//! [`Synom`]: ../synom/trait.Synom.html
-//!
 //! *This module is available if Syn is built with the `"parsing"` feature.*
-//!
-//! # Example
-//!
-//! This example shows a basic token parser for parsing a token stream without
-//! using Syn's parser combinator macros.
-//!
-//! ```
-//! #![feature(proc_macro_diagnostic)]
-//!
-//! extern crate syn;
-//! extern crate proc_macro;
-//!
-//! #[macro_use]
-//! extern crate quote;
-//!
-//! use syn::{token, ExprTuple};
-//! use syn::buffer::{Cursor, TokenBuffer};
-//! use syn::spanned::Spanned;
-//! use syn::synom::Synom;
-//! use proc_macro::{Diagnostic, Span, TokenStream};
-//!
-//! /// A basic token parser for parsing a token stream without using Syn's
-//! /// parser combinator macros.
-//! pub struct Parser<'a> {
-//!     cursor: Cursor<'a>,
-//! }
-//!
-//! impl<'a> Parser<'a> {
-//!     pub fn new(cursor: Cursor<'a>) -> Self {
-//!         Parser { cursor }
-//!     }
-//!
-//!     pub fn current_span(&self) -> Span {
-//!         self.cursor.span().unstable()
-//!     }
-//!
-//!     pub fn parse<T: Synom>(&mut self) -> Result<T, Diagnostic> {
-//!         let (val, rest) = T::parse(self.cursor)
-//!             .map_err(|e| match T::description() {
-//!                 Some(desc) => {
-//!                     self.current_span().error(format!("{}: expected {}", e, desc))
-//!                 }
-//!                 None => {
-//!                     self.current_span().error(e.to_string())
-//!                 }
-//!             })?;
-//!
-//!         self.cursor = rest;
-//!         Ok(val)
-//!     }
-//!
-//!     pub fn expect_eof(&mut self) -> Result<(), Diagnostic> {
-//!         if !self.cursor.eof() {
-//!             return Err(self.current_span().error("trailing characters; expected eof"));
-//!         }
-//!
-//!         Ok(())
-//!     }
-//! }
-//!
-//! fn eval(input: TokenStream) -> Result<TokenStream, Diagnostic> {
-//!     let buffer = TokenBuffer::new(input);
-//!     let mut parser = Parser::new(buffer.begin());
-//!
-//!     // Parse some syntax tree types out of the input tokens. In this case we
-//!     // expect something like:
-//!     //
-//!     //     (a, b, c) = (1, 2, 3)
-//!     let a = parser.parse::<ExprTuple>()?;
-//!     parser.parse::<token::Eq>()?;
-//!     let b = parser.parse::<ExprTuple>()?;
-//!     parser.expect_eof()?;
-//!
-//!     // Perform some validation and report errors.
-//!     let (a_len, b_len) = (a.elems.len(), b.elems.len());
-//!     if a_len != b_len {
-//!         let diag = b.span().unstable()
-//!             .error(format!("expected {} element(s), got {}", a_len, b_len))
-//!             .span_note(a.span().unstable(), "because of this");
-//!
-//!         return Err(diag);
-//!     }
-//!
-//!     // Build the output tokens.
-//!     let out = quote! {
-//!         println!("All good! Received two tuples of size {}", #a_len);
-//!     };
-//!
-//!     Ok(out.into())
-//! }
-//! #
-//! # extern crate proc_macro2;
-//! #
-//! # // This method exists on proc_macro2::Span but is behind the "nightly"
-//! # // feature.
-//! # trait ToUnstableSpan {
-//! #     fn unstable(&self) -> Span;
-//! # }
-//! #
-//! # impl ToUnstableSpan for proc_macro2::Span {
-//! #     fn unstable(&self) -> Span {
-//! #         unimplemented!()
-//! #     }
-//! # }
-//! #
-//! # fn main() {}
-//! ```
 
 // This module is heavily commented as it contains the only unsafe code in Syn,
 // and caution should be used when editing it. The public-facing interface is
@@ -132,14 +20,12 @@
     feature = "proc-macro"
 ))]
 use proc_macro as pm;
-use proc_macro2::{Delimiter, Ident, Literal, Span, TokenStream};
-use proc_macro2::{Group, Punct, TokenTree};
+use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
 
 use std::marker::PhantomData;
 use std::ptr;
 
-#[cfg(synom_verbose_trace)]
-use std::fmt::{self, Debug};
+use Lifetime;
 
 /// Internal type which is used instead of `TokenTree` to represent a token tree
 /// within a `TokenBuffer`.
@@ -158,10 +44,6 @@
 /// `TokenStream` which requires a deep copy in order to traverse more than
 /// once.
 ///
-/// See the [module documentation] for an example of `TokenBuffer` in action.
-///
-/// [module documentation]: index.html
-///
 /// *This type is available if Syn is built with the `"parsing"` feature.*
 pub struct TokenBuffer {
     // NOTE: Do not derive clone on this - there are raw pointers inside which
@@ -259,10 +141,6 @@
 /// Two cursors are equal if they have the same location in the same input
 /// stream, and have the same scope.
 ///
-/// See the [module documentation] for an example of a `Cursor` in action.
-///
-/// [module documentation]: index.html
-///
 /// *This type is available if Syn is built with the `"parsing"` feature.*
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Cursor<'a> {
@@ -389,7 +267,9 @@
     pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
         self.ignore_none();
         match *self.entry() {
-            Entry::Punct(ref op) => Some((op.clone(), unsafe { self.bump() })),
+            Entry::Punct(ref op) if op.as_char() != '\'' => {
+                Some((op.clone(), unsafe { self.bump() }))
+            }
             _ => None,
         }
     }
@@ -404,6 +284,28 @@
         }
     }
 
+    /// If the cursor is pointing at a `Lifetime`, returns it along with a
+    /// cursor pointing at the next `TokenTree`.
+    pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
+        self.ignore_none();
+        match *self.entry() {
+            Entry::Punct(ref op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
+                let next = unsafe { self.bump() };
+                match next.ident() {
+                    Some((ident, rest)) => {
+                        let lifetime = Lifetime {
+                            apostrophe: op.span(),
+                            ident: ident,
+                        };
+                        Some((lifetime, rest))
+                    }
+                    None => None,
+                }
+            }
+            _ => None,
+        }
+    }
+
     /// Copies all remaining tokens visible from this cursor into a
     /// `TokenStream`.
     pub fn token_stream(self) -> TokenStream {
@@ -454,16 +356,3 @@
         }
     }
 }
-
-// We do a custom implementation for `Debug` as the default implementation is
-// pretty useless.
-#[cfg(synom_verbose_trace)]
-impl<'a> Debug for Cursor<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // Print what the cursor is currently looking at.
-        // This will look like Cursor("some remaining tokens here")
-        f.debug_tuple("Cursor")
-            .field(&self.token_stream().to_string())
-            .finish()
-    }
-}
diff --git a/src/data.rs b/src/data.rs
index 8ffc8a4..4f0986a 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -73,7 +73,7 @@
     /// [`Field`]: struct.Field.html
     pub fn iter(&self) -> punctuated::Iter<Field> {
         match *self {
-            Fields::Unit => punctuated::Iter::private_empty(),
+            Fields::Unit => private::empty_punctuated_iter(),
             Fields::Named(ref f) => f.named.iter(),
             Fields::Unnamed(ref f) => f.unnamed.iter(),
         }
@@ -86,7 +86,7 @@
     /// [`Field`]: struct.Field.html
     pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
         match *self {
-            Fields::Unit => punctuated::IterMut::private_empty(),
+            Fields::Unit => private::empty_punctuated_iter_mut(),
             Fields::Named(ref mut f) => f.named.iter_mut(),
             Fields::Unnamed(ref mut f) => f.unnamed.iter_mut(),
         }
@@ -185,160 +185,134 @@
 pub mod parsing {
     use super::*;
 
-    use synom::Synom;
+    use ext::IdentExt;
+    use parse::{Parse, ParseStream, Result};
 
-    impl Synom for Variant {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            id: syn!(Ident) >>
-            fields: alt!(
-                syn!(FieldsNamed) => { Fields::Named }
-                |
-                syn!(FieldsUnnamed) => { Fields::Unnamed }
-                |
-                epsilon!() => { |_| Fields::Unit }
-            ) >>
-            disr: option!(tuple!(punct!(=), syn!(Expr))) >>
-            (Variant {
-                ident: id,
-                attrs: attrs,
-                fields: fields,
-                discriminant: disr,
+    impl Parse for Variant {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(Variant {
+                attrs: input.call(Attribute::parse_outer)?,
+                ident: input.parse()?,
+                fields: {
+                    if input.peek(token::Brace) {
+                        Fields::Named(input.parse()?)
+                    } else if input.peek(token::Paren) {
+                        Fields::Unnamed(input.parse()?)
+                    } else {
+                        Fields::Unit
+                    }
+                },
+                discriminant: {
+                    if input.peek(Token![=]) {
+                        let eq_token: Token![=] = input.parse()?;
+                        let discriminant: Expr = input.parse()?;
+                        Some((eq_token, discriminant))
+                    } else {
+                        None
+                    }
+                },
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("enum variant")
         }
     }
 
-    impl Synom for FieldsNamed {
-        named!(parse -> Self, map!(
-            braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
-            |(brace, fields)| FieldsNamed {
-                brace_token: brace,
-                named: fields,
-            }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("named fields in a struct or struct variant")
+    impl Parse for FieldsNamed {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(FieldsNamed {
+                brace_token: braced!(content in input),
+                named: content.parse_terminated(Field::parse_named)?,
+            })
         }
     }
 
-    impl Synom for FieldsUnnamed {
-        named!(parse -> Self, map!(
-            parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
-            |(paren, fields)| FieldsUnnamed {
-                paren_token: paren,
-                unnamed: fields,
-            }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("unnamed fields in a tuple struct or tuple variant")
+    impl Parse for FieldsUnnamed {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(FieldsUnnamed {
+                paren_token: parenthesized!(content in input),
+                unnamed: content.parse_terminated(Field::parse_unnamed)?,
+            })
         }
     }
 
     impl Field {
-        named!(pub parse_named -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            vis: syn!(Visibility) >>
-            id: syn!(Ident) >>
-            colon: punct!(:) >>
-            ty: syn!(Type) >>
-            (Field {
-                ident: Some(id),
-                vis: vis,
-                attrs: attrs,
-                ty: ty,
-                colon_token: Some(colon),
+        /// Parses a named (braced struct) field.
+        pub fn parse_named(input: ParseStream) -> Result<Self> {
+            Ok(Field {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                ident: Some(input.parse()?),
+                colon_token: Some(input.parse()?),
+                ty: input.parse()?,
             })
-        ));
+        }
 
-        named!(pub parse_unnamed -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            vis: syn!(Visibility) >>
-            ty: syn!(Type) >>
-            (Field {
+        /// Parses an unnamed (tuple struct) field.
+        pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
+            Ok(Field {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
                 ident: None,
                 colon_token: None,
-                vis: vis,
-                attrs: attrs,
-                ty: ty,
+                ty: input.parse()?,
             })
-        ));
+        }
     }
 
-    impl Synom for Visibility {
-        named!(parse -> Self, alt!(
-            do_parse!(
-                pub_token: keyword!(pub) >>
-                other: parens!(keyword!(crate)) >>
-                (Visibility::Restricted(VisRestricted {
-                    pub_token: pub_token,
-                    paren_token: other.0,
-                    in_token: None,
-                    path: Box::new(other.1.into()),
-                }))
-            )
-            |
-            do_parse!(
-                crate_token: keyword!(crate) >>
-                not!(punct!(::)) >>
-                (Visibility::Crate(VisCrate {
-                    crate_token: crate_token,
-                }))
-            )
-            |
-            do_parse!(
-                pub_token: keyword!(pub) >>
-                other: parens!(keyword!(self)) >>
-                (Visibility::Restricted(VisRestricted {
-                    pub_token: pub_token,
-                    paren_token: other.0,
-                    in_token: None,
-                    path: Box::new(other.1.into()),
-                }))
-            )
-            |
-            do_parse!(
-                pub_token: keyword!(pub) >>
-                other: parens!(keyword!(super)) >>
-                (Visibility::Restricted(VisRestricted {
-                    pub_token: pub_token,
-                    paren_token: other.0,
-                    in_token: None,
-                    path: Box::new(other.1.into()),
-                }))
-            )
-            |
-            do_parse!(
-                pub_token: keyword!(pub) >>
-                other: parens!(do_parse!(
-                    in_tok: keyword!(in) >>
-                    restricted: call!(Path::parse_mod_style) >>
-                    (in_tok, restricted)
-                )) >>
-                (Visibility::Restricted(VisRestricted {
-                    pub_token: pub_token,
-                    paren_token: other.0,
-                    in_token: Some((other.1).0),
-                    path: Box::new((other.1).1),
-                }))
-            )
-            |
-            keyword!(pub) => { |tok| {
-                Visibility::Public(VisPublic {
-                    pub_token: tok,
-                })
-            } }
-            |
-            epsilon!() => { |_| Visibility::Inherited }
-        ));
+    impl Parse for Visibility {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![pub]) {
+                Self::parse_pub(input)
+            } else if input.peek(Token![crate]) {
+                Self::parse_crate(input)
+            } else {
+                Ok(Visibility::Inherited)
+            }
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("visibility qualifier such as `pub`")
+    impl Visibility {
+        fn parse_pub(input: ParseStream) -> Result<Self> {
+            let pub_token = input.parse::<Token![pub]>()?;
+
+            if input.peek(token::Paren) {
+                let ahead = input.fork();
+                let mut content;
+                parenthesized!(content in ahead);
+
+                if content.peek(Token![crate])
+                    || content.peek(Token![self])
+                    || content.peek(Token![super])
+                {
+                    return Ok(Visibility::Restricted(VisRestricted {
+                        pub_token: pub_token,
+                        paren_token: parenthesized!(content in input),
+                        in_token: None,
+                        path: Box::new(Path::from(content.call(Ident::parse_any)?)),
+                    }));
+                } else if content.peek(Token![in]) {
+                    return Ok(Visibility::Restricted(VisRestricted {
+                        pub_token: pub_token,
+                        paren_token: parenthesized!(content in input),
+                        in_token: Some(content.parse()?),
+                        path: Box::new(content.call(Path::parse_mod_style)?),
+                    }));
+                }
+            }
+
+            Ok(Visibility::Public(VisPublic {
+                pub_token: pub_token,
+            }))
+        }
+
+        fn parse_crate(input: ParseStream) -> Result<Self> {
+            if input.peek2(Token![::]) {
+                Ok(Visibility::Inherited)
+            } else {
+                Ok(Visibility::Crate(VisCrate {
+                    crate_token: input.parse()?,
+                }))
+            }
         }
     }
 }
@@ -346,9 +320,12 @@
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
+
     use proc_macro2::TokenStream;
     use quote::{ToTokens, TokenStreamExt};
 
+    use print::TokensOrDefault;
+
     impl ToTokens for Variant {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(&self.attrs);
@@ -405,7 +382,7 @@
         fn to_tokens(&self, tokens: &mut TokenStream) {
             self.pub_token.to_tokens(tokens);
             self.paren_token.surround(tokens, |tokens| {
-                // XXX: If we have a path which is not "self" or "super" or
+                // TODO: If we have a path which is not "self" or "super" or
                 // "crate", automatically add the "in" token.
                 self.in_token.to_tokens(tokens);
                 self.path.to_tokens(tokens);
diff --git a/src/derive.rs b/src/derive.rs
index ecef776..5c1bb17 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -79,124 +79,145 @@
 pub mod parsing {
     use super::*;
 
-    use synom::Synom;
+    use parse::{Parse, ParseStream, Result};
 
-    enum DeriveInputKind {
-        Struct(Token![struct]),
-        Enum(Token![enum]),
-        Union(Token![union]),
-    }
+    impl Parse for DeriveInput {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis = input.parse::<Visibility>()?;
 
-    impl Synom for DeriveInputKind {
-        named!(parse -> Self, alt!(
-            keyword!(struct) => { DeriveInputKind::Struct }
-            |
-            keyword!(enum) => { DeriveInputKind::Enum }
-            |
-            keyword!(union) => { DeriveInputKind::Union }
-        ));
-    }
-
-    impl Synom for DeriveInput {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            vis: syn!(Visibility) >>
-            which: syn!(DeriveInputKind) >>
-            id: syn!(Ident) >>
-            generics: syn!(Generics) >>
-            item: switch!(value!(which),
-                DeriveInputKind::Struct(s) => map!(data_struct, move |(wh, fields, semi)| DeriveInput {
-                    ident: id,
-                    vis: vis,
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![struct]) {
+                let struct_token = input.parse::<Token![struct]>()?;
+                let ident = input.parse::<Ident>()?;
+                let generics = input.parse::<Generics>()?;
+                let (where_clause, fields, semi) = data_struct(input)?;
+                Ok(DeriveInput {
                     attrs: attrs,
+                    vis: vis,
+                    ident: ident,
                     generics: Generics {
-                        where_clause: wh,
+                        where_clause: where_clause,
                         ..generics
                     },
                     data: Data::Struct(DataStruct {
-                        struct_token: s,
+                        struct_token: struct_token,
                         fields: fields,
                         semi_token: semi,
                     }),
                 })
-                |
-                DeriveInputKind::Enum(e) => map!(data_enum, move |(wh, brace, variants)| DeriveInput {
-                    ident: id,
-                    vis: vis,
+            } else if lookahead.peek(Token![enum]) {
+                let enum_token = input.parse::<Token![enum]>()?;
+                let ident = input.parse::<Ident>()?;
+                let generics = input.parse::<Generics>()?;
+                let (where_clause, brace, variants) = data_enum(input)?;
+                Ok(DeriveInput {
                     attrs: attrs,
+                    vis: vis,
+                    ident: ident,
                     generics: Generics {
-                        where_clause: wh,
+                        where_clause: where_clause,
                         ..generics
                     },
                     data: Data::Enum(DataEnum {
-                        variants: variants,
+                        enum_token: enum_token,
                         brace_token: brace,
-                        enum_token: e,
+                        variants: variants,
                     }),
                 })
-                |
-                DeriveInputKind::Union(u) => map!(data_union, move |(wh, fields)| DeriveInput {
-                    ident: id,
-                    vis: vis,
+            } else if lookahead.peek(Token![union]) {
+                let union_token = input.parse::<Token![union]>()?;
+                let ident = input.parse::<Ident>()?;
+                let generics = input.parse::<Generics>()?;
+                let (where_clause, fields) = data_union(input)?;
+                Ok(DeriveInput {
                     attrs: attrs,
+                    vis: vis,
+                    ident: ident,
                     generics: Generics {
-                        where_clause: wh,
+                        where_clause: where_clause,
                         ..generics
                     },
                     data: Data::Union(DataUnion {
-                        union_token: u,
+                        union_token: union_token,
                         fields: fields,
                     }),
                 })
-            ) >>
-            (item)
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("derive input")
+            } else {
+                Err(lookahead.error())
+            }
         }
     }
 
-    named!(data_struct -> (Option<WhereClause>, Fields, Option<Token![;]>), alt!(
-        do_parse!(
-            wh: option!(syn!(WhereClause)) >>
-            fields: syn!(FieldsNamed) >>
-            (wh, Fields::Named(fields), None)
-        )
-        |
-        do_parse!(
-            fields: syn!(FieldsUnnamed) >>
-            wh: option!(syn!(WhereClause)) >>
-            semi: punct!(;) >>
-            (wh, Fields::Unnamed(fields), Some(semi))
-        )
-        |
-        do_parse!(
-            wh: option!(syn!(WhereClause)) >>
-            semi: punct!(;) >>
-            (wh, Fields::Unit, Some(semi))
-        )
-    ));
+    pub fn data_struct(
+        input: ParseStream,
+    ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
+        let mut lookahead = input.lookahead1();
+        let mut where_clause = None;
+        if lookahead.peek(Token![where]) {
+            where_clause = Some(input.parse()?);
+            lookahead = input.lookahead1();
+        }
 
-    named!(data_enum -> (Option<WhereClause>, token::Brace, Punctuated<Variant, Token![,]>), do_parse!(
-        wh: option!(syn!(WhereClause)) >>
-        data: braces!(Punctuated::parse_terminated) >>
-        (wh, data.0, data.1)
-    ));
+        if where_clause.is_none() && lookahead.peek(token::Paren) {
+            let fields = input.parse()?;
 
-    named!(data_union -> (Option<WhereClause>, FieldsNamed), tuple!(
-        option!(syn!(WhereClause)),
-        syn!(FieldsNamed),
-    ));
+            lookahead = input.lookahead1();
+            if lookahead.peek(Token![where]) {
+                where_clause = Some(input.parse()?);
+                lookahead = input.lookahead1();
+            }
+
+            if lookahead.peek(Token![;]) {
+                let semi = input.parse()?;
+                Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
+            } else {
+                Err(lookahead.error())
+            }
+        } else if lookahead.peek(token::Brace) {
+            let fields = input.parse()?;
+            Ok((where_clause, Fields::Named(fields), None))
+        } else if lookahead.peek(Token![;]) {
+            let semi = input.parse()?;
+            Ok((where_clause, Fields::Unit, Some(semi)))
+        } else {
+            Err(lookahead.error())
+        }
+    }
+
+    pub fn data_enum(
+        input: ParseStream,
+    ) -> Result<(
+        Option<WhereClause>,
+        token::Brace,
+        Punctuated<Variant, Token![,]>,
+    )> {
+        let where_clause = input.parse()?;
+
+        let content;
+        let brace = braced!(content in input);
+        let variants = content.parse_terminated(Variant::parse)?;
+
+        Ok((where_clause, brace, variants))
+    }
+
+    pub fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
+        let where_clause = input.parse()?;
+        let fields = input.parse()?;
+        Ok((where_clause, fields))
+    }
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
-    use attr::FilterAttrs;
+
     use proc_macro2::TokenStream;
     use quote::ToTokens;
 
+    use attr::FilterAttrs;
+    use print::TokensOrDefault;
+
     impl ToTokens for DeriveInput {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             for attr in self.attrs.outer() {
diff --git a/src/error.rs b/src/error.rs
index 6673aa3..67e3939 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -6,27 +6,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use buffer::Cursor;
-use std::error::Error;
+use std;
 use std::fmt::{self, Display};
+use std::iter::FromIterator;
 
-/// The result of a `Synom` parser.
-///
-/// Refer to the [module documentation] for details about parsing in Syn.
-///
-/// [module documentation]: index.html
-///
-/// *This type is available if Syn is built with the `"parsing"` feature.*
-pub type PResult<'a, O> = Result<(O, Cursor<'a>), ParseError>;
+use proc_macro2::{
+    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
+};
 
-/// An error with a default error message.
-///
-/// NOTE: We should provide better error messages in the future.
-pub fn parse_error<'a, O>() -> PResult<'a, O> {
-    Err(ParseError(None))
-}
+use buffer::Cursor;
 
-/// Error returned when a `Synom` parser cannot parse the input tokens.
+/// The result of a Syn parser.
+pub type Result<T> = std::result::Result<T, Error>;
+
+/// Error returned when a Syn parser cannot parse the input tokens.
 ///
 /// Refer to the [module documentation] for details about parsing in Syn.
 ///
@@ -34,27 +27,110 @@
 ///
 /// *This type is available if Syn is built with the `"parsing"` feature.*
 #[derive(Debug)]
-pub struct ParseError(Option<String>);
+pub struct Error {
+    span: Span,
+    message: String,
+}
 
-impl Error for ParseError {
-    fn description(&self) -> &str {
-        match self.0 {
-            Some(ref desc) => desc,
-            None => "failed to parse",
+impl Error {
+    /// Usually the [`ParseStream::error`] method will be used instead, which
+    /// automatically uses the correct span from the current position of the
+    /// parse stream.
+    ///
+    /// Use `Error::new` when the error needs to be triggered on some span other
+    /// than where the parse stream is currently positioned.
+    ///
+    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{Ident, LitStr, Token};
+    /// use syn::parse::{Error, ParseStream, Result};
+    ///
+    /// // Parses input that looks like `name = "string"` where the key must be
+    /// // the identifier `name` and the value may be any string literal.
+    /// // Returns the string literal.
+    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
+    ///     let name_token: Ident = input.parse()?;
+    ///     if name_token != "name" {
+    ///         // Trigger an error not on the current position of the stream,
+    ///         // but on the position of the unexpected identifier.
+    ///         return Err(Error::new(name_token.span(), "expected `name`"));
+    ///     }
+    ///     input.parse::<Token![=]>()?;
+    ///     let s: LitStr = input.parse()?;
+    ///     Ok(s)
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    pub fn new<T: Display>(span: Span, message: T) -> Self {
+        Error {
+            span: span,
+            message: message.to_string(),
         }
     }
-}
 
-impl Display for ParseError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(self.description(), f)
+    pub fn span(&self) -> Span {
+        self.span
+    }
+
+    /// Render the error as an invocation of [`compile_error!`].
+    ///
+    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
+    /// this method correctly in a procedural macro.
+    ///
+    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
+    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
+    pub fn into_compile_error(self) -> TokenStream {
+        // compile_error!($message)
+        TokenStream::from_iter(vec![
+            TokenTree::Ident(Ident::new("compile_error", self.span)),
+            TokenTree::Punct({
+                let mut punct = Punct::new('!', Spacing::Alone);
+                punct.set_span(self.span);
+                punct
+            }),
+            TokenTree::Group({
+                let mut group = Group::new(Delimiter::Brace, {
+                    TokenStream::from_iter(vec![TokenTree::Literal({
+                        let mut string = Literal::string(&self.message);
+                        string.set_span(self.span);
+                        string
+                    })])
+                });
+                group.set_span(self.span);
+                group
+            }),
+        ])
     }
 }
 
-impl ParseError {
-    // For syn use only. Not public API.
-    #[doc(hidden)]
-    pub fn new<T: Into<String>>(msg: T) -> Self {
-        ParseError(Some(msg.into()))
+pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
+    if cursor.eof() {
+        Error::new(scope, format!("unexpected end of input, {}", message))
+    } else {
+        Error::new(cursor.span(), message)
+    }
+}
+
+impl Display for Error {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(&self.message)
+    }
+}
+
+impl std::error::Error for Error {
+    fn description(&self) -> &str {
+        "parse error"
+    }
+}
+
+impl From<LexError> for Error {
+    fn from(err: LexError) -> Self {
+        Error::new(Span::call_site(), format!("{:?}", err))
     }
 }
diff --git a/src/export.rs b/src/export.rs
new file mode 100644
index 0000000..9608a01
--- /dev/null
+++ b/src/export.rs
@@ -0,0 +1,7 @@
+pub use std::result::Result::{Err, Ok};
+
+#[cfg(feature = "parsing")]
+pub use std::convert::From;
+
+#[cfg(feature = "proc-macro")]
+pub use proc_macro::TokenStream;
diff --git a/src/expr.rs b/src/expr.rs
index 3742fb4..9440c1c 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -11,7 +11,7 @@
 use punctuated::Punctuated;
 #[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
-#[cfg(feature = "full")]
+#[cfg(all(feature = "parsing", feature = "full"))]
 use std::mem;
 #[cfg(feature = "extra-traits")]
 use tt::TokenStreamHelper;
@@ -313,6 +313,7 @@
         /// *This type is available if Syn is built with the `"full"` feature.*
         pub Closure(ExprClosure #full {
             pub attrs: Vec<Attribute>,
+            pub asyncness: Option<Token![async]>,
             pub movability: Option<Token![static]>,
             pub capture: Option<Token![move]>,
             pub or1_token: Token![|],
@@ -336,6 +337,7 @@
         /// *This type is available if Syn is built with the `"full"` feature.*
         pub Block(ExprBlock #full {
             pub attrs: Vec<Attribute>,
+            pub label: Option<Label>,
             pub block: Block,
         }),
 
@@ -508,13 +510,22 @@
             pub question_token: Token![?],
         }),
 
-        /// A catch expression: `do catch { ... }`.
+        /// An async block: `async { ... }`.
         ///
         /// *This type is available if Syn is built with the `"full"` feature.*
-        pub Catch(ExprCatch #full {
+        pub Async(ExprAsync #full {
             pub attrs: Vec<Attribute>,
-            pub do_token: Token![do],
-            pub catch_token: Token![catch],
+            pub async_token: Token![async],
+            pub capture: Option<Token![move]>,
+            pub block: Block,
+        }),
+
+        /// A try block: `try { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub TryBlock(ExprTryBlock #full {
+            pub attrs: Vec<Attribute>,
+            pub try_token: Token![try],
             pub block: Block,
         }),
 
@@ -558,10 +569,8 @@
 }
 
 impl Expr {
-    // Not public API.
-    #[doc(hidden)]
-    #[cfg(feature = "full")]
-    pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
+    #[cfg(all(feature = "parsing", feature = "full"))]
+    fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
         match *self {
             Expr::Box(ExprBox { ref mut attrs, .. })
             | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
@@ -600,12 +609,10 @@
             | 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::Async(ExprAsync { ref mut attrs, .. })
+            | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
             | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
-            Expr::Verbatim(_) => {
-                // TODO
-                Vec::new()
-            }
+            Expr::Verbatim(_) => Vec::new(),
         }
     }
 }
@@ -995,9 +1002,8 @@
 
 #[cfg(any(feature = "parsing", feature = "printing"))]
 #[cfg(feature = "full")]
-fn arm_expr_requires_comma(expr: &Expr) -> bool {
-    // see https://github.com/rust-lang/rust/blob/eb8f2586e
-    //                       /src/libsyntax/parse/classify.rs#L17-L37
+fn requires_terminator(expr: &Expr) -> bool {
+    // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
     match *expr {
         Expr::Unsafe(..)
         | Expr::Block(..)
@@ -1008,7 +1014,8 @@
         | Expr::WhileLet(..)
         | Expr::Loop(..)
         | Expr::ForLoop(..)
-        | Expr::Catch(..) => false,
+        | Expr::Async(..)
+        | Expr::TryBlock(..) => false,
         _ => true,
     }
 }
@@ -1016,446 +1023,331 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use path::parsing::mod_style_path_segment;
-    #[cfg(feature = "full")]
-    use path::parsing::ty_no_eq_after;
 
-    use buffer::Cursor;
     #[cfg(feature = "full")]
-    use parse_error;
-    #[cfg(feature = "full")]
-    use proc_macro2::TokenStream;
-    use synom::PResult;
-    use synom::Synom;
+    use ext::IdentExt;
+    use parse::{Parse, ParseStream, Result};
+    use path;
 
     // When we're parsing expressions which occur before blocks, like in an if
     // statement's condition, we cannot parse a struct literal.
     //
     // Struct literals are ambiguous in certain positions
     // https://github.com/rust-lang/rfcs/pull/92
-    macro_rules! ambiguous_expr {
-        ($i:expr, $allow_struct:ident) => {
-            ambiguous_expr($i, $allow_struct, true)
-        };
+    #[derive(Copy, Clone)]
+    pub struct AllowStruct(bool);
+
+    #[derive(Copy, Clone, PartialEq, PartialOrd)]
+    enum Precedence {
+        Any,
+        Assign,
+        Placement,
+        Range,
+        Or,
+        And,
+        Compare,
+        BitOr,
+        BitXor,
+        BitAnd,
+        Shift,
+        Arithmetic,
+        Term,
+        Cast,
     }
 
-    // When we are parsing an optional suffix expression, we cannot allow blocks
-    // if structs are not allowed.
-    //
-    // Example:
-    //
-    //     if break {} {}
-    //
-    // is ambiguous between:
-    //
-    //     if (break {}) {}
-    //     if (break) {} {}
-    #[cfg(feature = "full")]
-    macro_rules! opt_ambiguous_expr {
-        ($i:expr, $allow_struct:ident) => {
-            option!($i, call!(ambiguous_expr, $allow_struct, $allow_struct))
-        };
+    impl Precedence {
+        fn of(op: &BinOp) -> Self {
+            match *op {
+                BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
+                BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
+                BinOp::And(_) => Precedence::And,
+                BinOp::Or(_) => Precedence::Or,
+                BinOp::BitXor(_) => Precedence::BitXor,
+                BinOp::BitAnd(_) => Precedence::BitAnd,
+                BinOp::BitOr(_) => Precedence::BitOr,
+                BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
+                BinOp::Eq(_)
+                | BinOp::Lt(_)
+                | BinOp::Le(_)
+                | BinOp::Ne(_)
+                | BinOp::Ge(_)
+                | BinOp::Gt(_) => Precedence::Compare,
+                BinOp::AddEq(_)
+                | BinOp::SubEq(_)
+                | BinOp::MulEq(_)
+                | BinOp::DivEq(_)
+                | BinOp::RemEq(_)
+                | BinOp::BitXorEq(_)
+                | BinOp::BitAndEq(_)
+                | BinOp::BitOrEq(_)
+                | BinOp::ShlEq(_)
+                | BinOp::ShrEq(_) => Precedence::Assign,
+            }
+        }
     }
 
-    impl Synom for Expr {
-        named!(parse -> Self, ambiguous_expr!(true));
-
-        fn description() -> Option<&'static str> {
-            Some("expression")
+    impl Parse for Expr {
+        fn parse(input: ParseStream) -> Result<Self> {
+            ambiguous_expr(input, AllowStruct(true))
         }
     }
 
     #[cfg(feature = "full")]
-    named!(expr_no_struct -> Expr, ambiguous_expr!(false));
+    fn expr_no_struct(input: ParseStream) -> Result<Expr> {
+        ambiguous_expr(input, AllowStruct(false))
+    }
 
-    // Parse an arbitrary expression.
     #[cfg(feature = "full")]
-    fn ambiguous_expr(i: Cursor, allow_struct: bool, allow_block: bool) -> PResult<Expr> {
-        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> {
-        // 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.
-    macro_rules! binop {
-        (
-            $name: ident,
-            $next: ident,
-            $submac: ident!( $($args:tt)* )
-        ) => {
-            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()),
-                        }.into();
-                    })
-                )) >>
-                (e)
-            ));
-        }
-    }
-
-    // <placement> = <placement> ..
-    // <placement> += <placement> ..
-    // <placement> -= <placement> ..
-    // <placement> *= <placement> ..
-    // <placement> /= <placement> ..
-    // <placement> %= <placement> ..
-    // <placement> ^= <placement> ..
-    // <placement> &= <placement> ..
-    // <placement> |= <placement> ..
-    // <placement> <<= <placement> ..
-    // <placement> >>= <placement> ..
-    //
-    // NOTE: This operator is right-associative.
-    #[cfg(feature = "full")]
-    named!(assign_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
-        mut e: call!(placement_expr, allow_struct, allow_block) >>
-        alt!(
-            do_parse!(
-                eq: punct!(=) >>
-                // Recurse into self to parse right-associative operator.
-                rhs: call!(assign_expr, allow_struct, true) >>
-                ({
-                    e = ExprAssign {
+    fn parse_expr(
+        input: ParseStream,
+        mut lhs: Expr,
+        allow_struct: AllowStruct,
+        base: Precedence,
+    ) -> Result<Expr> {
+        loop {
+            if input
+                .fork()
+                .parse::<BinOp>()
+                .ok()
+                .map_or(false, |op| Precedence::of(&op) >= base)
+            {
+                let op: BinOp = input.parse()?;
+                let precedence = Precedence::of(&op);
+                let mut rhs = unary_expr(input, allow_struct)?;
+                loop {
+                    let next = peek_precedence(input);
+                    if next > precedence || next == precedence && precedence == Precedence::Assign {
+                        rhs = parse_expr(input, rhs, allow_struct, next)?;
+                    } else {
+                        break;
+                    }
+                }
+                lhs = if precedence == Precedence::Assign {
+                    Expr::AssignOp(ExprAssignOp {
                         attrs: Vec::new(),
-                        left: Box::new(e),
-                        eq_token: eq,
-                        right: Box::new(rhs),
-                    }.into();
-                })
-            )
-            |
-            do_parse!(
-                op: call!(BinOp::parse_assign_op) >>
-                // Recurse into self to parse right-associative operator.
-                rhs: call!(assign_expr, allow_struct, true) >>
-                ({
-                    e = ExprAssignOp {
-                        attrs: Vec::new(),
-                        left: Box::new(e),
+                        left: Box::new(lhs),
                         op: op,
                         right: Box::new(rhs),
-                    }.into();
-                })
-            )
-            |
-            epsilon!()
-        ) >>
-        (e)
-    ));
-
-    // <range> <- <range> ..
-    //
-    // NOTE: The `in place { expr }` version of this syntax is parsed in
-    // `atom_expr`, not here.
-    //
-    // NOTE: This operator is right-associative.
-    #[cfg(feature = "full")]
-    named!(placement_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
-        mut e: call!(range_expr, allow_struct, allow_block) >>
-        alt!(
-            do_parse!(
-                arrow: punct!(<-) >>
-                // Recurse into self to parse right-associative operator.
-                rhs: call!(placement_expr, allow_struct, true) >>
-                ({
-                    e = ExprInPlace {
+                    })
+                } else {
+                    Expr::Binary(ExprBinary {
                         attrs: Vec::new(),
-                        // op: BinOp::Place(larrow),
-                        place: Box::new(e),
-                        arrow_token: arrow,
-                        value: Box::new(rhs),
-                    }.into();
-                })
-            )
-            |
-            epsilon!()
-        ) >>
-        (e)
-    ));
-
-    // <or> ... <or> ..
-    // <or> .. <or> ..
-    // <or> ..
-    //
-    // NOTE: This is currently parsed oddly - I'm not sure of what the exact
-    // rules are for parsing these expressions are, but this is not correct.
-    // For example, `a .. b .. c` is not a legal expression. It should not
-    // be parsed as either `(a .. b) .. c` or `a .. (b .. c)` apparently.
-    //
-    // 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) -> Expr, do_parse!(
-        mut e: call!(or_expr, allow_struct, allow_block) >>
-        many0!(do_parse!(
-            limits: syn!(RangeLimits) >>
-            // We don't want to allow blocks here if we don't allow structs. See
-            // the reasoning for `opt_ambiguous_expr!` above.
-            hi: option!(call!(or_expr, allow_struct, allow_struct)) >>
-            ({
-                e = ExprRange {
+                        left: Box::new(lhs),
+                        op: op,
+                        right: Box::new(rhs),
+                    })
+                };
+            } else if Precedence::Assign >= base
+                && input.peek(Token![=])
+                && !input.peek(Token![==])
+                && !input.peek(Token![=>])
+            {
+                let eq_token: Token![=] = input.parse()?;
+                let mut rhs = unary_expr(input, allow_struct)?;
+                loop {
+                    let next = peek_precedence(input);
+                    if next >= Precedence::Assign {
+                        rhs = parse_expr(input, rhs, allow_struct, next)?;
+                    } else {
+                        break;
+                    }
+                }
+                lhs = Expr::Assign(ExprAssign {
                     attrs: Vec::new(),
-                    from: Some(Box::new(e)),
+                    left: Box::new(lhs),
+                    eq_token: eq_token,
+                    right: Box::new(rhs),
+                });
+            } else if Precedence::Placement >= base && input.peek(Token![<-]) {
+                let arrow_token: Token![<-] = input.parse()?;
+                let mut rhs = unary_expr(input, allow_struct)?;
+                loop {
+                    let next = peek_precedence(input);
+                    if next > Precedence::Placement {
+                        rhs = parse_expr(input, rhs, allow_struct, next)?;
+                    } else {
+                        break;
+                    }
+                }
+                lhs = Expr::InPlace(ExprInPlace {
+                    attrs: Vec::new(),
+                    place: Box::new(lhs),
+                    arrow_token: arrow_token,
+                    value: Box::new(rhs),
+                });
+            } else if Precedence::Range >= base && input.peek(Token![..]) {
+                let limits: RangeLimits = input.parse()?;
+                let rhs = if input.is_empty()
+                    || input.peek(Token![,])
+                    || input.peek(Token![;])
+                    || !allow_struct.0 && input.peek(token::Brace)
+                {
+                    None
+                } else {
+                    let mut rhs = unary_expr(input, allow_struct)?;
+                    loop {
+                        let next = peek_precedence(input);
+                        if next > Precedence::Range {
+                            rhs = parse_expr(input, rhs, allow_struct, next)?;
+                        } else {
+                            break;
+                        }
+                    }
+                    Some(rhs)
+                };
+                lhs = Expr::Range(ExprRange {
+                    attrs: Vec::new(),
+                    from: Some(Box::new(lhs)),
                     limits: limits,
-                    to: hi.map(|e| Box::new(e)),
-                }.into();
-            })
-        )) >>
-        (e)
-    ));
-
-    // <and> || <and> ...
-    binop!(or_expr, and_expr, map!(punct!(||), BinOp::Or));
-
-    // <compare> && <compare> ...
-    binop!(and_expr, compare_expr, map!(punct!(&&), BinOp::And));
-
-    // <bitor> == <bitor> ...
-    // <bitor> != <bitor> ...
-    // <bitor> >= <bitor> ...
-    // <bitor> <= <bitor> ...
-    // <bitor> > <bitor> ...
-    // <bitor> < <bitor> ...
-    //
-    // NOTE: This operator appears to be parsed as left-associative, but errors
-    // if it is used in a non-associative manner.
-    binop!(
-        compare_expr,
-        bitor_expr,
-        alt!(
-        punct!(==) => { BinOp::Eq }
-        |
-        punct!(!=) => { BinOp::Ne }
-        |
-        // must be above Lt
-        punct!(<=) => { BinOp::Le }
-        |
-        // must be above Gt
-        punct!(>=) => { BinOp::Ge }
-        |
-        do_parse!(
-            // Make sure that we don't eat the < part of a <- operator
-            not!(punct!(<-)) >>
-            t: punct!(<) >>
-            (BinOp::Lt(t))
-        )
-        |
-        punct!(>) => { BinOp::Gt }
-    )
-    );
-
-    // <bitxor> | <bitxor> ...
-    binop!(
-        bitor_expr,
-        bitxor_expr,
-        do_parse!(not!(punct!(||)) >> not!(punct!(|=)) >> t: punct!(|) >> (BinOp::BitOr(t)))
-    );
-
-    // <bitand> ^ <bitand> ...
-    binop!(
-        bitxor_expr,
-        bitand_expr,
-        do_parse!(
-            // NOTE: Make sure we aren't looking at ^=.
-            not!(punct!(^=)) >> t: punct!(^) >> (BinOp::BitXor(t))
-        )
-    );
-
-    // <shift> & <shift> ...
-    binop!(
-        bitand_expr,
-        shift_expr,
-        do_parse!(
-            // NOTE: Make sure we aren't looking at && or &=.
-            not!(punct!(&&)) >> not!(punct!(&=)) >> t: punct!(&) >> (BinOp::BitAnd(t))
-        )
-    );
-
-    // <arith> << <arith> ...
-    // <arith> >> <arith> ...
-    binop!(
-        shift_expr,
-        arith_expr,
-        alt!(
-        punct!(<<) => { BinOp::Shl }
-        |
-        punct!(>>) => { BinOp::Shr }
-    )
-    );
-
-    // <term> + <term> ...
-    // <term> - <term> ...
-    binop!(
-        arith_expr,
-        term_expr,
-        alt!(
-        punct!(+) => { BinOp::Add }
-        |
-        punct!(-) => { BinOp::Sub }
-    )
-    );
-
-    // <cast> * <cast> ...
-    // <cast> / <cast> ...
-    // <cast> % <cast> ...
-    binop!(
-        term_expr,
-        cast_expr,
-        alt!(
-        punct!(*) => { BinOp::Mul }
-        |
-        punct!(/) => { BinOp::Div }
-        |
-        punct!(%) => { BinOp::Rem }
-    )
-    );
-
-    // <unary> as <ty>
-    // <unary> : <ty>
-    #[cfg(feature = "full")]
-    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!(
-                as_: keyword!(as) >>
-                // We can't accept `A + B` in cast expressions, as it's
-                // ambiguous with the + expression.
-                ty: call!(Type::without_plus) >>
-                ({
-                    e = ExprCast {
-                        attrs: Vec::new(),
-                        expr: Box::new(e),
-                        as_token: as_,
-                        ty: Box::new(ty),
-                    }.into();
-                })
-            )
-            |
-            do_parse!(
-                colon: punct!(:) >>
-                // We can't accept `A + B` in cast expressions, as it's
-                // ambiguous with the + expression.
-                ty: call!(Type::without_plus) >>
-                ({
-                    e = ExprType {
-                        attrs: Vec::new(),
-                        expr: Box::new(e),
-                        colon_token: colon,
-                        ty: Box::new(ty),
-                    }.into();
-                })
-            )
-        )) >>
-        (e)
-    ));
-
-    // <unary> as <ty>
-    #[cfg(not(feature = "full"))]
-    named!(cast_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
-        mut e: call!(unary_expr, allow_struct, allow_block) >>
-        many0!(do_parse!(
-            as_: keyword!(as) >>
-            // We can't accept `A + B` in cast expressions, as it's
-            // ambiguous with the + expression.
-            ty: call!(Type::without_plus) >>
-            ({
-                e = ExprCast {
+                    to: rhs.map(Box::new),
+                });
+            } else if Precedence::Cast >= base && input.peek(Token![as]) {
+                let as_token: Token![as] = input.parse()?;
+                let ty = input.call(Type::without_plus)?;
+                lhs = Expr::Cast(ExprCast {
                     attrs: Vec::new(),
-                    expr: Box::new(e),
-                    as_token: as_,
+                    expr: Box::new(lhs),
+                    as_token: as_token,
                     ty: Box::new(ty),
-                }.into();
-            })
-        )) >>
-        (e)
-    ));
+                });
+            } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
+                let colon_token: Token![:] = input.parse()?;
+                let ty = input.call(Type::without_plus)?;
+                lhs = Expr::Type(ExprType {
+                    attrs: Vec::new(),
+                    expr: Box::new(lhs),
+                    colon_token: colon_token,
+                    ty: Box::new(ty),
+                });
+            } else {
+                break;
+            }
+        }
+        Ok(lhs)
+    }
+
+    #[cfg(not(feature = "full"))]
+    fn parse_expr(
+        input: ParseStream,
+        mut lhs: Expr,
+        allow_struct: AllowStruct,
+        base: Precedence,
+    ) -> Result<Expr> {
+        loop {
+            if input
+                .fork()
+                .parse::<BinOp>()
+                .ok()
+                .map_or(false, |op| Precedence::of(&op) >= base)
+            {
+                let op: BinOp = input.parse()?;
+                let precedence = Precedence::of(&op);
+                let mut rhs = unary_expr(input, allow_struct)?;
+                loop {
+                    let next = peek_precedence(input);
+                    if next > precedence || next == precedence && precedence == Precedence::Assign {
+                        rhs = parse_expr(input, rhs, allow_struct, next)?;
+                    } else {
+                        break;
+                    }
+                }
+                lhs = Expr::Binary(ExprBinary {
+                    attrs: Vec::new(),
+                    left: Box::new(lhs),
+                    op: op,
+                    right: Box::new(rhs),
+                });
+            } else if Precedence::Cast >= base && input.peek(Token![as]) {
+                let as_token: Token![as] = input.parse()?;
+                let ty = input.call(Type::without_plus)?;
+                lhs = Expr::Cast(ExprCast {
+                    attrs: Vec::new(),
+                    expr: Box::new(lhs),
+                    as_token: as_token,
+                    ty: Box::new(ty),
+                });
+            } else {
+                break;
+            }
+        }
+        Ok(lhs)
+    }
+
+    fn peek_precedence(input: ParseStream) -> Precedence {
+        if let Ok(op) = input.fork().parse() {
+            Precedence::of(&op)
+        } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
+            Precedence::Assign
+        } else if input.peek(Token![<-]) {
+            Precedence::Placement
+        } else if input.peek(Token![..]) {
+            Precedence::Range
+        } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
+            Precedence::Cast
+        } else {
+            Precedence::Any
+        }
+    }
+
+    // Parse an arbitrary expression.
+    fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+        let lhs = unary_expr(input, allow_struct)?;
+        parse_expr(input, lhs, allow_struct, Precedence::Any)
+    }
 
     // <UnOp> <trailer>
     // & <trailer>
     // &mut <trailer>
     // box <trailer>
     #[cfg(feature = "full")]
-    named!(unary_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
-        do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            op: syn!(UnOp) >>
-            expr: call!(unary_expr, allow_struct, true) >>
-            (ExprUnary {
-                attrs: attrs,
-                op: op,
-                expr: Box::new(expr),
-            }.into())
-        )
-        |
-        do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            and: punct!(&) >>
-            mutability: option!(keyword!(mut)) >>
-            expr: call!(unary_expr, allow_struct, true) >>
-            (ExprReference {
-                attrs: attrs,
-                and_token: and,
-                mutability: mutability,
-                expr: Box::new(expr),
-            }.into())
-        )
-        |
-        do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            box_: keyword!(box) >>
-            expr: call!(unary_expr, allow_struct, true) >>
-            (ExprBox {
-                attrs: attrs,
-                box_token: box_,
-                expr: Box::new(expr),
-            }.into())
-        )
-        |
-        call!(trailer_expr, allow_struct, allow_block)
-    ));
-
-    // XXX: This duplication is ugly
-    #[cfg(not(feature = "full"))]
-    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())
-        )
-        |
-        call!(trailer_expr, allow_struct, allow_block)
-    ));
-
-    #[cfg(feature = "full")]
-    fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
-        let mut outer = Vec::new();
-        let mut inner = Vec::new();
-        for attr in mem::replace(attrs, Vec::new()) {
-            match attr.style {
-                AttrStyle::Outer => outer.push(attr),
-                AttrStyle::Inner(_) => inner.push(attr),
+    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+        let ahead = input.fork();
+        ahead.call(Attribute::parse_outer)?;
+        if ahead.peek(Token![&])
+            || ahead.peek(Token![box])
+            || ahead.peek(Token![*])
+            || ahead.peek(Token![!])
+            || ahead.peek(Token![-])
+        {
+            let attrs = input.call(Attribute::parse_outer)?;
+            if input.peek(Token![&]) {
+                Ok(Expr::Reference(ExprReference {
+                    attrs: attrs,
+                    and_token: input.parse()?,
+                    mutability: input.parse()?,
+                    expr: Box::new(unary_expr(input, allow_struct)?),
+                }))
+            } else if input.peek(Token![box]) {
+                Ok(Expr::Box(ExprBox {
+                    attrs: attrs,
+                    box_token: input.parse()?,
+                    expr: Box::new(unary_expr(input, allow_struct)?),
+                }))
+            } else {
+                Ok(Expr::Unary(ExprUnary {
+                    attrs: attrs,
+                    op: input.parse()?,
+                    expr: Box::new(unary_expr(input, allow_struct)?),
+                }))
             }
+        } else {
+            trailer_expr(input, allow_struct)
         }
-        *attrs = inner;
-        outer
+    }
+
+    #[cfg(not(feature = "full"))]
+    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+        let ahead = input.fork();
+        ahead.call(Attribute::parse_outer)?;
+        if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
+            Ok(Expr::Unary(ExprUnary {
+                attrs: input.call(Attribute::parse_outer)?,
+                op: input.parse()?,
+                expr: Box::new(unary_expr(input, allow_struct)?),
+            }))
+        } else {
+            trailer_expr(input, allow_struct)
+        }
     }
 
     // <atom> (..<args>) ...
@@ -1465,1673 +1357,1667 @@
     // <atom> [ <expr> ] ...
     // <atom> ? ...
     #[cfg(feature = "full")]
-    named!(trailer_expr(allow_struct: bool, allow_block: bool) -> Expr, do_parse!(
-        mut e: call!(atom_expr, allow_struct, allow_block) >>
-        outer_attrs: value!({
-            let mut attrs = e.replace_attrs(Vec::new());
-            let outer_attrs = take_outer(&mut attrs);
-            e.replace_attrs(attrs);
-            outer_attrs
-        }) >>
-        many0!(alt!(
-            tap!(args: and_call => {
-                let (paren, args) = args;
-                e = ExprCall {
-                    attrs: Vec::new(),
-                    func: Box::new(e),
-                    args: args,
-                    paren_token: paren,
-                }.into();
-            })
-            |
-            tap!(more: and_method_call => {
-                let mut call = more;
-                call.receiver = Box::new(e);
-                e = call.into();
-            })
-            |
-            tap!(field: and_field => {
-                let (token, member) = field;
-                e = ExprField {
-                    attrs: Vec::new(),
-                    base: Box::new(e),
-                    dot_token: token,
-                    member: member,
-                }.into();
-            })
-            |
-            tap!(i: and_index => {
-                let (bracket, i) = i;
-                e = ExprIndex {
-                    attrs: Vec::new(),
-                    expr: Box::new(e),
-                    bracket_token: bracket,
-                    index: Box::new(i),
-                }.into();
-            })
-            |
-            tap!(question: punct!(?) => {
-                e = ExprTry {
-                    attrs: Vec::new(),
-                    expr: Box::new(e),
-                    question_token: question,
-                }.into();
-            })
-        )) >>
-        ({
-            let mut attrs = outer_attrs;
-            attrs.extend(e.replace_attrs(Vec::new()));
-            e.replace_attrs(attrs);
-            e
-        })
-    ));
+    fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+        if input.peek(token::Group) {
+            return input.call(expr_group).map(Expr::Group);
+        }
 
-    // XXX: Duplication == ugly
-    #[cfg(not(feature = "full"))]
-    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 => {
-                e = ExprCall {
+        let outer_attrs = input.call(Attribute::parse_outer)?;
+
+        let atom = atom_expr(input, allow_struct)?;
+        let mut e = trailer_helper(input, atom)?;
+
+        let inner_attrs = e.replace_attrs(Vec::new());
+        let attrs = private::attrs(outer_attrs, inner_attrs);
+        e.replace_attrs(attrs);
+        Ok(e)
+    }
+
+    #[cfg(feature = "full")]
+    fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
+        loop {
+            if input.peek(token::Paren) {
+                let content;
+                e = Expr::Call(ExprCall {
                     attrs: Vec::new(),
                     func: Box::new(e),
-                    paren_token: args.0,
-                    args: args.1,
-                }.into();
-            })
-            |
-            tap!(field: and_field => {
-                let (token, member) = field;
-                e = ExprField {
+                    paren_token: parenthesized!(content in input),
+                    args: content.parse_terminated(Expr::parse)?,
+                });
+            } else if input.peek(Token![.]) && !input.peek(Token![..]) {
+                let dot_token: Token![.] = input.parse()?;
+                let member: Member = input.parse()?;
+                let turbofish = if member.is_named() && input.peek(Token![::]) {
+                    Some(MethodTurbofish {
+                        colon2_token: input.parse()?,
+                        lt_token: input.parse()?,
+                        args: {
+                            let mut args = Punctuated::new();
+                            loop {
+                                if input.peek(Token![>]) {
+                                    break;
+                                }
+                                let value = input.call(generic_method_argument)?;
+                                args.push_value(value);
+                                if input.peek(Token![>]) {
+                                    break;
+                                }
+                                let punct = input.parse()?;
+                                args.push_punct(punct);
+                            }
+                            args
+                        },
+                        gt_token: input.parse()?,
+                    })
+                } else {
+                    None
+                };
+
+                if turbofish.is_some() || input.peek(token::Paren) {
+                    if let Member::Named(method) = member {
+                        let content;
+                        e = Expr::MethodCall(ExprMethodCall {
+                            attrs: Vec::new(),
+                            receiver: Box::new(e),
+                            dot_token: dot_token,
+                            method: method,
+                            turbofish: turbofish,
+                            paren_token: parenthesized!(content in input),
+                            args: content.parse_terminated(Expr::parse)?,
+                        });
+                        continue;
+                    }
+                }
+
+                e = Expr::Field(ExprField {
                     attrs: Vec::new(),
                     base: Box::new(e),
-                    dot_token: token,
+                    dot_token: dot_token,
                     member: member,
-                }.into();
-            })
-            |
-            tap!(i: and_index => {
-                e = ExprIndex {
+                });
+            } else if input.peek(token::Bracket) {
+                let content;
+                e = Expr::Index(ExprIndex {
                     attrs: Vec::new(),
                     expr: Box::new(e),
-                    bracket_token: i.0,
-                    index: Box::new(i.1),
-                }.into();
-            })
-        )) >>
-        (e)
-    ));
+                    bracket_token: bracketed!(content in input),
+                    index: content.parse()?,
+                });
+            } else if input.peek(Token![?]) {
+                e = Expr::Try(ExprTry {
+                    attrs: Vec::new(),
+                    expr: Box::new(e),
+                    question_token: input.parse()?,
+                });
+            } else {
+                break;
+            }
+        }
+        Ok(e)
+    }
+
+    #[cfg(not(feature = "full"))]
+    fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+        let mut e = atom_expr(input, allow_struct)?;
+
+        loop {
+            if input.peek(token::Paren) {
+                let content;
+                e = Expr::Call(ExprCall {
+                    attrs: Vec::new(),
+                    func: Box::new(e),
+                    paren_token: parenthesized!(content in input),
+                    args: content.parse_terminated(Expr::parse)?,
+                });
+            } else if input.peek(Token![.]) {
+                e = Expr::Field(ExprField {
+                    attrs: Vec::new(),
+                    base: Box::new(e),
+                    dot_token: input.parse()?,
+                    member: input.parse()?,
+                });
+            } else if input.peek(token::Bracket) {
+                let content;
+                e = Expr::Index(ExprIndex {
+                    attrs: Vec::new(),
+                    expr: Box::new(e),
+                    bracket_token: bracketed!(content in input),
+                    index: content.parse()?,
+                });
+            } else {
+                break;
+            }
+        }
+
+        Ok(e)
+    }
 
     // Parse all atomic expressions which don't have to worry about precedence
     // interactions, as they are fully contained.
     #[cfg(feature = "full")]
-    named!(atom_expr(allow_struct: bool, allow_block: bool) -> Expr, alt!(
-        syn!(ExprGroup) => { Expr::Group } // must be placed first
-        |
-        syn!(ExprLit) => { Expr::Lit } // must be before expr_struct
-        |
-        // must be before ExprStruct
-        call!(unstable_async_block) => { Expr::Verbatim }
-        |
-        // must be before ExprStruct
-        call!(unstable_try_block) => { Expr::Verbatim }
-        |
-        // must be before expr_path
-        cond_reduce!(allow_struct, syn!(ExprStruct)) => { Expr::Struct }
-        |
-        syn!(ExprParen) => { Expr::Paren } // must be before expr_tup
-        |
-        syn!(ExprMacro) => { Expr::Macro } // must be before expr_path
-        |
-        call!(expr_break, allow_struct) // must be before expr_path
-        |
-        syn!(ExprContinue) => { Expr::Continue } // must be before expr_path
-        |
-        call!(expr_ret, allow_struct) // must be before expr_path
-        |
-        syn!(ExprArray) => { Expr::Array }
-        |
-        syn!(ExprTuple) => { Expr::Tuple }
-        |
-        syn!(ExprIf) => { Expr::If }
-        |
-        syn!(ExprIfLet) => { Expr::IfLet }
-        |
-        syn!(ExprWhile) => { Expr::While }
-        |
-        syn!(ExprWhileLet) => { Expr::WhileLet }
-        |
-        syn!(ExprForLoop) => { Expr::ForLoop }
-        |
-        syn!(ExprLoop) => { Expr::Loop }
-        |
-        syn!(ExprMatch) => { Expr::Match }
-        |
-        syn!(ExprCatch) => { Expr::Catch }
-        |
-        syn!(ExprYield) => { Expr::Yield }
-        |
-        syn!(ExprUnsafe) => { Expr::Unsafe }
-        |
-        call!(expr_closure, allow_struct)
-        |
-        cond_reduce!(allow_block, syn!(ExprBlock)) => { Expr::Block }
-        |
-        call!(unstable_labeled_block) => { Expr::Verbatim }
-        |
-        // NOTE: This is the prefix-form of range
-        call!(expr_range, allow_struct)
-        |
-        syn!(ExprPath) => { Expr::Path }
-        |
-        syn!(ExprRepeat) => { Expr::Repeat }
-    ));
+    fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+        if input.peek(token::Group) {
+            input.call(expr_group).map(Expr::Group)
+        } else if input.peek(Lit) {
+            input.call(expr_lit).map(Expr::Lit)
+        } else if input.peek(Token![async])
+            && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
+        {
+            input.call(expr_async).map(Expr::Async)
+        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
+            input.call(expr_try_block).map(Expr::TryBlock)
+        } else if input.peek(Token![|])
+            || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
+            || input.peek(Token![static])
+            || input.peek(Token![move])
+        {
+            expr_closure(input, allow_struct).map(Expr::Closure)
+        } else if input.peek(Ident)
+            || input.peek(Token![::])
+            || input.peek(Token![<])
+            || input.peek(Token![self])
+            || input.peek(Token![Self])
+            || input.peek(Token![super])
+            || input.peek(Token![extern])
+            || input.peek(Token![crate])
+        {
+            path_or_macro_or_struct(input, allow_struct)
+        } else if input.peek(token::Paren) {
+            paren_or_tuple(input)
+        } else if input.peek(Token![break]) {
+            expr_break(input, allow_struct).map(Expr::Break)
+        } else if input.peek(Token![continue]) {
+            input.call(expr_continue).map(Expr::Continue)
+        } else if input.peek(Token![return]) {
+            expr_ret(input, allow_struct).map(Expr::Return)
+        } else if input.peek(token::Bracket) {
+            array_or_repeat(input)
+        } else if input.peek(Token![if]) {
+            if input.peek2(Token![let]) {
+                input.call(expr_if_let).map(Expr::IfLet)
+            } else {
+                input.call(expr_if).map(Expr::If)
+            }
+        } else if input.peek(Token![while]) {
+            if input.peek2(Token![let]) {
+                input.call(expr_while_let).map(Expr::WhileLet)
+            } else {
+                input.call(expr_while).map(Expr::While)
+            }
+        } else if input.peek(Token![for]) {
+            input.call(expr_for_loop).map(Expr::ForLoop)
+        } else if input.peek(Token![loop]) {
+            input.call(expr_loop).map(Expr::Loop)
+        } else if input.peek(Token![match]) {
+            input.call(expr_match).map(Expr::Match)
+        } else if input.peek(Token![yield]) {
+            input.call(expr_yield).map(Expr::Yield)
+        } else if input.peek(Token![unsafe]) {
+            input.call(expr_unsafe).map(Expr::Unsafe)
+        } else if input.peek(token::Brace) {
+            input.call(expr_block).map(Expr::Block)
+        } else if input.peek(Token![..]) {
+            expr_range(input, allow_struct).map(Expr::Range)
+        } else if input.peek(Lifetime) {
+            let the_label: Label = input.parse()?;
+            let mut expr = if input.peek(Token![while]) {
+                if input.peek2(Token![let]) {
+                    Expr::WhileLet(input.call(expr_while_let)?)
+                } else {
+                    Expr::While(input.call(expr_while)?)
+                }
+            } else if input.peek(Token![for]) {
+                Expr::ForLoop(input.call(expr_for_loop)?)
+            } else if input.peek(Token![loop]) {
+                Expr::Loop(input.call(expr_loop)?)
+            } else if input.peek(token::Brace) {
+                Expr::Block(input.call(expr_block)?)
+            } else {
+                return Err(input.error("expected loop or block expression"));
+            };
+            match expr {
+                Expr::WhileLet(ExprWhileLet { ref mut label, .. })
+                | Expr::While(ExprWhile { ref mut label, .. })
+                | Expr::ForLoop(ExprForLoop { ref mut label, .. })
+                | Expr::Loop(ExprLoop { ref mut label, .. })
+                | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
+                _ => unreachable!(),
+            }
+            Ok(expr)
+        } else {
+            Err(input.error("expected expression"))
+        }
+    }
 
     #[cfg(not(feature = "full"))]
-    named!(atom_expr(_allow_struct: bool, _allow_block: bool) -> Expr, alt!(
-        syn!(ExprLit) => { Expr::Lit }
-        |
-        syn!(ExprParen) => { Expr::Paren }
-        |
-        syn!(ExprPath) => { Expr::Path }
-    ));
-
-    #[cfg(feature = "full")]
-    named!(expr_nosemi -> Expr, do_parse!(
-        nosemi: alt!(
-            syn!(ExprIf) => { Expr::If }
-            |
-            syn!(ExprIfLet) => { Expr::IfLet }
-            |
-            syn!(ExprWhile) => { Expr::While }
-            |
-            syn!(ExprWhileLet) => { Expr::WhileLet }
-            |
-            syn!(ExprForLoop) => { Expr::ForLoop }
-            |
-            syn!(ExprLoop) => { Expr::Loop }
-            |
-            syn!(ExprMatch) => { Expr::Match }
-            |
-            syn!(ExprCatch) => { Expr::Catch }
-            |
-            syn!(ExprYield) => { Expr::Yield }
-            |
-            syn!(ExprUnsafe) => { Expr::Unsafe }
-            |
-            syn!(ExprBlock) => { Expr::Block }
-            |
-            call!(unstable_labeled_block) => { Expr::Verbatim }
-        ) >>
-        // If the next token is a `.` or a `?` it is special-cased to parse
-        // as an expression instead of a blockexpression.
-        not!(punct!(.)) >>
-        not!(punct!(?)) >>
-        (nosemi)
-    ));
-
-    impl Synom for ExprLit {
-        #[cfg(not(feature = "full"))]
-        named!(parse -> Self, do_parse!(
-            lit: syn!(Lit) >>
-            (ExprLit {
-                attrs: Vec::new(),
-                lit: lit,
-            })
-        ));
-
-        #[cfg(feature = "full")]
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            lit: syn!(Lit) >>
-            (ExprLit {
-                attrs: attrs,
-                lit: lit,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("literal")
+    fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
+        if input.peek(Lit) {
+            input.call(expr_lit).map(Expr::Lit)
+        } else if input.peek(token::Paren) {
+            input.call(expr_paren).map(Expr::Paren)
+        } else if input.peek(Ident)
+            || input.peek(Token![::])
+            || input.peek(Token![<])
+            || input.peek(Token![self])
+            || input.peek(Token![Self])
+            || input.peek(Token![super])
+            || input.peek(Token![extern])
+            || input.peek(Token![crate])
+        {
+            input.parse().map(Expr::Path)
+        } else {
+            Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
         }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprMacro {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            mac: syn!(Macro) >>
-            (ExprMacro {
-                attrs: attrs,
-                mac: mac,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("macro invocation expression")
+    fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+        let expr: ExprPath = input.parse()?;
+        if expr.qself.is_some() {
+            return Ok(Expr::Path(expr));
         }
-    }
 
-    #[cfg(feature = "full")]
-    impl Synom for ExprGroup {
-        named!(parse -> Self, do_parse!(
-            e: grouped!(syn!(Expr)) >>
-            (ExprGroup {
-                attrs: Vec::new(),
-                expr: Box::new(e.1),
-                group_token: e.0,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("expression surrounded by invisible delimiters")
-        }
-    }
-
-    impl Synom for ExprParen {
-        #[cfg(not(feature = "full"))]
-        named!(parse -> Self, do_parse!(
-            e: parens!(syn!(Expr)) >>
-            (ExprParen {
-                attrs: Vec::new(),
-                paren_token: e.0,
-                expr: Box::new(e.1),
-            })
-        ));
-
-        #[cfg(feature = "full")]
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            e: parens!(tuple!(
-                many0!(Attribute::parse_inner),
-                syn!(Expr),
-            )) >>
-            (ExprParen {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((e.1).0);
-                    attrs
-                },
-                paren_token: e.0,
-                expr: Box::new((e.1).1),
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("parenthesized expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprArray {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            elems: brackets!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Punctuated::parse_terminated),
-            )) >>
-            (ExprArray {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((elems.1).0);
-                    attrs
-                },
-                bracket_token: elems.0,
-                elems: (elems.1).1,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("array expression")
-        }
-    }
-
-    named!(and_call -> (token::Paren, Punctuated<Expr, Token![,]>),
-        parens!(Punctuated::parse_terminated)
-    );
-
-    #[cfg(feature = "full")]
-    named!(and_method_call -> ExprMethodCall, do_parse!(
-        dot: punct!(.) >>
-        method: syn!(Ident) >>
-        turbofish: option!(tuple!(
-            punct!(::),
-            punct!(<),
-            call!(Punctuated::parse_terminated),
-            punct!(>),
-        )) >>
-        args: parens!(Punctuated::parse_terminated) >>
-        ({
-            ExprMethodCall {
-                attrs: Vec::new(),
-                // this expr will get overwritten after being returned
-                receiver: Box::new(Expr::Verbatim(ExprVerbatim {
-                    tts: TokenStream::new(),
-                })),
-
-                method: method,
-                turbofish: turbofish.map(|fish| MethodTurbofish {
-                    colon2_token: fish.0,
-                    lt_token: fish.1,
-                    args: fish.2,
-                    gt_token: fish.3,
-                }),
-                args: args.1,
-                paren_token: args.0,
-                dot_token: dot,
-            }
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for GenericMethodArgument {
-        // TODO parse const generics as well
-        named!(parse -> Self, map!(ty_no_eq_after, GenericMethodArgument::Type));
-
-        fn description() -> Option<&'static str> {
-            Some("generic method argument")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprTuple {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            elems: parens!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Punctuated::parse_terminated),
-            )) >>
-            (ExprTuple {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((elems.1).0);
-                    attrs
-                },
-                elems: (elems.1).1,
-                paren_token: elems.0,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("tuple")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprIfLet {
-        named!(parse -> Self, do_parse!(
-            if_: keyword!(if) >>
-            let_: keyword!(let) >>
-            pats: call!(Punctuated::parse_separated_nonempty) >>
-            eq: punct!(=) >>
-            cond: expr_no_struct >>
-            then_block: braces!(Block::parse_within) >>
-            else_block: option!(else_block) >>
-            (ExprIfLet {
-                attrs: Vec::new(),
-                pats: pats,
-                let_token: let_,
-                eq_token: eq,
-                expr: Box::new(cond),
-                then_branch: Block {
-                    brace_token: then_block.0,
-                    stmts: then_block.1,
-                },
-                if_token: if_,
-                else_branch: else_block,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`if let` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprIf {
-        named!(parse -> Self, do_parse!(
-            if_: keyword!(if) >>
-            cond: expr_no_struct >>
-            then_block: braces!(Block::parse_within) >>
-            else_block: option!(else_block) >>
-            (ExprIf {
-                attrs: Vec::new(),
-                cond: Box::new(cond),
-                then_branch: Block {
-                    brace_token: then_block.0,
-                    stmts: then_block.1,
-                },
-                if_token: if_,
-                else_branch: else_block,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`if` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    named!(else_block -> (Token![else], Box<Expr>), do_parse!(
-        else_: keyword!(else) >>
-        expr: alt!(
-            syn!(ExprIf) => { Expr::If }
-            |
-            syn!(ExprIfLet) => { Expr::IfLet }
-            |
-            do_parse!(
-                else_block: braces!(Block::parse_within) >>
-                (Expr::Block(ExprBlock {
-                    attrs: Vec::new(),
-                    block: Block {
-                        brace_token: else_block.0,
-                        stmts: else_block.1,
-                    },
-                }))
-            )
-        ) >>
-        (else_, Box::new(expr))
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprForLoop {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            label: option!(syn!(Label)) >>
-            for_: keyword!(for) >>
-            pat: syn!(Pat) >>
-            in_: keyword!(in) >>
-            expr: expr_no_struct >>
-            block: braces!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Block::parse_within),
-            )) >>
-            (ExprForLoop {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
-                    attrs
-                },
-                label: label,
-                for_token: for_,
-                pat: Box::new(pat),
-                in_token: in_,
-                expr: Box::new(expr),
-                body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
-                },
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`for` loop")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprLoop {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            label: option!(syn!(Label)) >>
-            loop_: keyword!(loop) >>
-            block: braces!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Block::parse_within),
-            )) >>
-            (ExprLoop {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
-                    attrs
-                },
-                label: label,
-                loop_token: loop_,
-                body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
-                },
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`loop`")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprMatch {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            match_: keyword!(match) >>
-            obj: expr_no_struct >>
-            braced_content: braces!(tuple!(
-                many0!(Attribute::parse_inner),
-                many0!(syn!(Arm)),
-            )) >>
-            (ExprMatch {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((braced_content.1).0);
-                    attrs
-                },
-                expr: Box::new(obj),
-                match_token: match_,
-                brace_token: braced_content.0,
-                arms: (braced_content.1).1,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`match` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprCatch {
-        named!(parse -> Self, do_parse!(
-            do_: keyword!(do) >>
-            catch_: keyword!(catch) >>
-            catch_block: syn!(Block) >>
-            (ExprCatch {
-                attrs: Vec::new(),
-                block: catch_block,
-                do_token: do_,
-                catch_token: catch_,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`catch` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprYield {
-        named!(parse -> Self, do_parse!(
-            yield_: keyword!(yield) >>
-            expr: option!(syn!(Expr)) >>
-            (ExprYield {
-                attrs: Vec::new(),
-                yield_token: yield_,
-                expr: expr.map(Box::new),
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`yield` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for Arm {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            leading_vert: option!(punct!(|)) >>
-            pats: call!(Punctuated::parse_separated_nonempty) >>
-            guard: option!(tuple!(keyword!(if), syn!(Expr))) >>
-            fat_arrow: punct!(=>) >>
-            body: do_parse!(
-                expr: alt!(expr_nosemi | syn!(Expr)) >>
-                comma: switch!(value!(arm_expr_requires_comma(&expr)),
-                    true => alt!(
-                        input_end!() => { |_| None }
-                        |
-                        punct!(,) => { Some }
-                    )
-                    |
-                    false => option!(punct!(,))
-                ) >>
-                (expr, comma)
-            ) >>
-            (Arm {
-                fat_arrow_token: fat_arrow,
-                attrs: attrs,
-                leading_vert: leading_vert,
-                pats: pats,
-                guard: guard.map(|(if_, guard)| (if_, Box::new(guard))),
-                body: Box::new(body.0),
-                comma: body.1,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`match` arm")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    named!(expr_closure(allow_struct: bool) -> Expr, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        attrs: many0!(Attribute::parse_outer) >>
-        asyncness: option!(keyword!(async)) >>
-        movability: option!(cond_reduce!(asyncness.is_none(), keyword!(static))) >>
-        capture: option!(keyword!(move)) >>
-        or1: punct!(|) >>
-        inputs: call!(Punctuated::parse_terminated_with, fn_arg) >>
-        or2: punct!(|) >>
-        ret_and_body: alt!(
-            do_parse!(
-                arrow: punct!(->) >>
-                ty: syn!(Type) >>
-                body: syn!(Block) >>
-                (
-                    ReturnType::Type(arrow, Box::new(ty)),
-                    Expr::Block(ExprBlock {
-                        attrs: Vec::new(),
-                        block: body,
-                    },
-                ))
-            )
-            |
-            map!(ambiguous_expr!(allow_struct), |e| (ReturnType::Default, e))
-        ) >>
-        end: call!(verbatim::grab_cursor) >>
-        ({
-            if asyncness.is_some() {
-                // TODO: include asyncness in ExprClosure
-                // https://github.com/dtolnay/syn/issues/396
-                Expr::Verbatim(ExprVerbatim {
-                    tts: verbatim::token_range(begin..end),
-                })
-            } else {
-                Expr::Closure(ExprClosure {
-                    attrs: attrs,
-                    movability: movability,
-                    capture: capture,
-                    or1_token: or1,
-                    inputs: inputs,
-                    or2_token: or2,
-                    output: ret_and_body.0,
-                    body: Box::new(ret_and_body.1),
-                })
-            }
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    named!(unstable_async_block -> ExprVerbatim, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        many0!(Attribute::parse_outer) >>
-        keyword!(async) >>
-        option!(keyword!(move)) >>
-        syn!(Block) >>
-        end: call!(verbatim::grab_cursor) >>
-        (ExprVerbatim {
-            tts: verbatim::token_range(begin..end),
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    named!(unstable_try_block -> ExprVerbatim, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        many0!(Attribute::parse_outer) >>
-        keyword!(try) >>
-        syn!(Block) >>
-        end: call!(verbatim::grab_cursor) >>
-        (ExprVerbatim {
-            tts: verbatim::token_range(begin..end),
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    named!(fn_arg -> FnArg, do_parse!(
-        pat: syn!(Pat) >>
-        ty: option!(tuple!(punct!(:), syn!(Type))) >>
-        ({
-            if let Some((colon, ty)) = ty {
-                FnArg::Captured(ArgCaptured {
-                    pat: pat,
-                    colon_token: colon,
-                    ty: ty,
-                })
-            } else {
-                FnArg::Inferred(pat)
-            }
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprWhile {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            label: option!(syn!(Label)) >>
-            while_: keyword!(while) >>
-            cond: expr_no_struct >>
-            block: braces!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Block::parse_within),
-            )) >>
-            (ExprWhile {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
-                    attrs
-                },
-                label: label,
-                while_token: while_,
-                cond: Box::new(cond),
-                body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
-                },
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`while` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprWhileLet {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            label: option!(syn!(Label)) >>
-            while_: keyword!(while) >>
-            let_: keyword!(let) >>
-            pats: call!(Punctuated::parse_separated_nonempty) >>
-            eq: punct!(=) >>
-            value: expr_no_struct >>
-            block: braces!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Block::parse_within),
-            )) >>
-            (ExprWhileLet {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
-                    attrs
-                },
-                label: label,
-                while_token: while_,
-                let_token: let_,
-                pats: pats,
-                eq_token: eq,
-                expr: Box::new(value),
-                body: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
-                },
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`while let` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for Label {
-        named!(parse -> Self, do_parse!(
-            name: syn!(Lifetime) >>
-            colon: punct!(:) >>
-            (Label {
-                name: name,
-                colon_token: colon,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`while let` expression")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprContinue {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            cont: keyword!(continue) >>
-            label: option!(syn!(Lifetime)) >>
-            (ExprContinue {
-                attrs: attrs,
-                continue_token: cont,
-                label: label,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`continue`")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    named!(expr_break(allow_struct: bool) -> Expr, do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        break_: keyword!(break) >>
-        label: 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: attrs,
-            label: label,
-            expr: val.map(Box::new),
-            break_token: break_,
-        }.into())
-    ));
-
-    #[cfg(feature = "full")]
-    named!(expr_ret(allow_struct: bool) -> Expr, do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        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
-        // conditions. For example:
-        //
-        // if return { println!("A") } {} // Prints "A"
-        ret_value: option!(ambiguous_expr!(allow_struct)) >>
-        (ExprReturn {
-            attrs: attrs,
-            expr: ret_value.map(Box::new),
-            return_token: return_,
-        }.into())
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprStruct {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            path: syn!(Path) >>
-            data: braces!(do_parse!(
-                inner_attrs: many0!(Attribute::parse_inner) >>
-                fields: call!(Punctuated::parse_terminated) >>
-                base: option!(cond!(fields.empty_or_trailing(), do_parse!(
-                    dots: punct!(..) >>
-                    base: syn!(Expr) >>
-                    (dots, base)
-                ))) >>
-                (inner_attrs, fields, base)
-            )) >>
-            ({
-                let (brace, (inner_attrs, fields, base)) = data;
-                let (dots, rest) = match base.and_then(|b| b) {
-                    Some((dots, base)) => (Some(dots), Some(base)),
-                    None => (None, None),
-                };
-                ExprStruct {
-                    attrs: {
-                        let mut attrs = outer_attrs;
-                        attrs.extend(inner_attrs);
-                        attrs
-                    },
-                    brace_token: brace,
-                    path: path,
-                    fields: fields,
-                    dot2_token: dots,
-                    rest: rest.map(Box::new),
+        if input.peek(Token![!]) && !input.peek(Token![!=]) {
+            let mut contains_arguments = false;
+            for segment in &expr.path.segments {
+                match segment.arguments {
+                    PathArguments::None => {}
+                    PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
+                        contains_arguments = true;
+                    }
                 }
-            })
-        ));
+            }
 
-        fn description() -> Option<&'static str> {
-            Some("struct literal expression")
+            if !contains_arguments {
+                let bang_token: Token![!] = input.parse()?;
+                let (delimiter, tts) = mac::parse_delimiter(input)?;
+                return Ok(Expr::Macro(ExprMacro {
+                    attrs: Vec::new(),
+                    mac: Macro {
+                        path: expr.path,
+                        bang_token: bang_token,
+                        delimiter: delimiter,
+                        tts: tts,
+                    },
+                }));
+            }
+        }
+
+        if allow_struct.0 && input.peek(token::Brace) {
+            let outer_attrs = Vec::new();
+            expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
+        } else {
+            Ok(Expr::Path(expr))
         }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for FieldValue {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            field_value: alt!(
-                tuple!(syn!(Member), map!(punct!(:), Some), syn!(Expr))
-                |
-                map!(syn!(Ident), |name| (
-                    Member::Named(name.clone()),
-                    None,
-                    Expr::Path(ExprPath {
-                        attrs: Vec::new(),
-                        qself: None,
-                        path: name.into(),
-                    }),
-                ))
-            ) >>
-            (FieldValue {
-                attrs: attrs,
-                member: field_value.0,
-                colon_token: field_value.1,
-                expr: field_value.2,
-            })
-        ));
+    fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
+        let content;
+        let paren_token = parenthesized!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        if content.is_empty() {
+            return Ok(Expr::Tuple(ExprTuple {
+                attrs: inner_attrs,
+                paren_token: paren_token,
+                elems: Punctuated::new(),
+            }));
+        }
 
-        fn description() -> Option<&'static str> {
-            Some("field-value pair: `field: value`")
+        let first: Expr = content.parse()?;
+        if content.is_empty() {
+            return Ok(Expr::Paren(ExprParen {
+                attrs: inner_attrs,
+                paren_token: paren_token,
+                expr: Box::new(first),
+            }));
+        }
+
+        let mut elems = Punctuated::new();
+        elems.push_value(first);
+        while !content.is_empty() {
+            let punct = content.parse()?;
+            elems.push_punct(punct);
+            if content.is_empty() {
+                break;
+            }
+            let value = content.parse()?;
+            elems.push_value(value);
+        }
+        Ok(Expr::Tuple(ExprTuple {
+            attrs: inner_attrs,
+            paren_token: paren_token,
+            elems: elems,
+        }))
+    }
+
+    #[cfg(feature = "full")]
+    fn array_or_repeat(input: ParseStream) -> Result<Expr> {
+        let content;
+        let bracket_token = bracketed!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        if content.is_empty() {
+            return Ok(Expr::Array(ExprArray {
+                attrs: inner_attrs,
+                bracket_token: bracket_token,
+                elems: Punctuated::new(),
+            }));
+        }
+
+        let first: Expr = content.parse()?;
+        if content.is_empty() || content.peek(Token![,]) {
+            let mut elems = Punctuated::new();
+            elems.push_value(first);
+            while !content.is_empty() {
+                let punct = content.parse()?;
+                elems.push_punct(punct);
+                if content.is_empty() {
+                    break;
+                }
+                let value = content.parse()?;
+                elems.push_value(value);
+            }
+            Ok(Expr::Array(ExprArray {
+                attrs: inner_attrs,
+                bracket_token: bracket_token,
+                elems: elems,
+            }))
+        } else if content.peek(Token![;]) {
+            let semi_token: Token![;] = content.parse()?;
+            let len: Expr = content.parse()?;
+            Ok(Expr::Repeat(ExprRepeat {
+                attrs: inner_attrs,
+                bracket_token: bracket_token,
+                expr: Box::new(first),
+                semi_token: semi_token,
+                len: Box::new(len),
+            }))
+        } else {
+            Err(content.error("expected `,` or `;`"))
         }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for ExprRepeat {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            data: brackets!(tuple!(
-                many0!(Attribute::parse_inner),
-                syn!(Expr),
-                punct!(;),
-                syn!(Expr),
-            )) >>
-            (ExprRepeat {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((data.1).0);
-                    attrs
-                },
-                expr: Box::new((data.1).1),
-                len: Box::new((data.1).3),
-                bracket_token: data.0,
-                semi_token: (data.1).2,
-            })
-        ));
+    fn expr_early(input: ParseStream) -> Result<Expr> {
+        let mut attrs = input.call(Attribute::parse_outer)?;
+        let mut expr = if input.peek(Token![if]) {
+            if input.peek2(Token![let]) {
+                Expr::IfLet(input.call(expr_if_let)?)
+            } else {
+                Expr::If(input.call(expr_if)?)
+            }
+        } else if input.peek(Token![while]) {
+            if input.peek2(Token![let]) {
+                Expr::WhileLet(input.call(expr_while_let)?)
+            } else {
+                Expr::While(input.call(expr_while)?)
+            }
+        } else if input.peek(Token![for]) {
+            Expr::ForLoop(input.call(expr_for_loop)?)
+        } else if input.peek(Token![loop]) {
+            Expr::Loop(input.call(expr_loop)?)
+        } else if input.peek(Token![match]) {
+            Expr::Match(input.call(expr_match)?)
+        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
+            Expr::TryBlock(input.call(expr_try_block)?)
+        } else if input.peek(Token![unsafe]) {
+            Expr::Unsafe(input.call(expr_unsafe)?)
+        } else if input.peek(token::Brace) {
+            Expr::Block(input.call(expr_block)?)
+        } else {
+            let allow_struct = AllowStruct(true);
+            let mut expr = unary_expr(input, allow_struct)?;
 
-        fn description() -> Option<&'static str> {
-            Some("repeated array literal: `[val; N]`")
+            attrs.extend(expr.replace_attrs(Vec::new()));
+            expr.replace_attrs(attrs);
+
+            return parse_expr(input, expr, allow_struct, Precedence::Any);
+        };
+
+        if input.peek(Token![.]) || input.peek(Token![?]) {
+            expr = trailer_helper(input, expr)?;
+
+            attrs.extend(expr.replace_attrs(Vec::new()));
+            expr.replace_attrs(attrs);
+
+            let allow_struct = AllowStruct(true);
+            return parse_expr(input, expr, allow_struct, Precedence::Any);
         }
+
+        attrs.extend(expr.replace_attrs(Vec::new()));
+        expr.replace_attrs(attrs);
+        Ok(expr)
     }
 
-    #[cfg(feature = "full")]
-    impl Synom for ExprUnsafe {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            unsafe_: keyword!(unsafe) >>
-            block: braces!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Block::parse_within),
-            )) >>
-            (ExprUnsafe {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
-                    attrs
-                },
-                unsafe_token: unsafe_,
-                block: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
-                },
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("unsafe block: `unsafe { .. }`")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for ExprBlock {
-        named!(parse -> Self, do_parse!(
-            outer_attrs: many0!(Attribute::parse_outer) >>
-            block: braces!(tuple!(
-                many0!(Attribute::parse_inner),
-                call!(Block::parse_within),
-            )) >>
-            (ExprBlock {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend((block.1).0);
-                    attrs
-                },
-                block: Block {
-                    brace_token: block.0,
-                    stmts: (block.1).1,
-                },
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("block: `{ .. }`")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    named!(unstable_labeled_block -> ExprVerbatim, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        many0!(Attribute::parse_outer) >>
-        syn!(Label) >>
-        braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            call!(Block::parse_within),
-        )) >>
-        end: call!(verbatim::grab_cursor) >>
-        (ExprVerbatim {
-            tts: verbatim::token_range(begin..end),
+    pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
+        Ok(ExprLit {
+            attrs: Vec::new(),
+            lit: input.parse()?,
         })
-    ));
+    }
 
     #[cfg(feature = "full")]
-    named!(expr_range(allow_struct: bool) -> Expr, do_parse!(
-        limits: syn!(RangeLimits) >>
-        hi: opt_ambiguous_expr!(allow_struct) >>
-        (ExprRange {
+    fn expr_group(input: ParseStream) -> Result<ExprGroup> {
+        let group = private::parse_group(input)?;
+        Ok(ExprGroup {
+            attrs: Vec::new(),
+            group_token: group.token,
+            expr: group.content.parse()?,
+        })
+    }
+
+    #[cfg(not(feature = "full"))]
+    fn expr_paren(input: ParseStream) -> Result<ExprParen> {
+        let content;
+        Ok(ExprParen {
+            attrs: Vec::new(),
+            paren_token: parenthesized!(content in input),
+            expr: content.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
+        // TODO parse const generics as well
+        input.parse().map(GenericMethodArgument::Type)
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_if_let(input: ParseStream) -> Result<ExprIfLet> {
+        Ok(ExprIfLet {
+            attrs: Vec::new(),
+            if_token: input.parse()?,
+            let_token: input.parse()?,
+            pats: {
+                let mut pats = Punctuated::new();
+                let value: Pat = input.parse()?;
+                pats.push_value(value);
+                while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
+                    let punct = input.parse()?;
+                    pats.push_punct(punct);
+                    let value: Pat = input.parse()?;
+                    pats.push_value(value);
+                }
+                pats
+            },
+            eq_token: input.parse()?,
+            expr: Box::new(input.call(expr_no_struct)?),
+            then_branch: input.parse()?,
+            else_branch: {
+                if input.peek(Token![else]) {
+                    Some(input.call(else_block)?)
+                } else {
+                    None
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_if(input: ParseStream) -> Result<ExprIf> {
+        Ok(ExprIf {
+            attrs: Vec::new(),
+            if_token: input.parse()?,
+            cond: Box::new(input.call(expr_no_struct)?),
+            then_branch: input.parse()?,
+            else_branch: {
+                if input.peek(Token![else]) {
+                    Some(input.call(else_block)?)
+                } else {
+                    None
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
+        let else_token: Token![else] = input.parse()?;
+
+        let lookahead = input.lookahead1();
+        let else_branch = if input.peek(Token![if]) {
+            if input.peek2(Token![let]) {
+                input.call(expr_if_let).map(Expr::IfLet)?
+            } else {
+                input.call(expr_if).map(Expr::If)?
+            }
+        } else if input.peek(token::Brace) {
+            Expr::Block(ExprBlock {
+                attrs: Vec::new(),
+                label: None,
+                block: input.parse()?,
+            })
+        } else {
+            return Err(lookahead.error());
+        };
+
+        Ok((else_token, Box::new(else_branch)))
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
+        let label: Option<Label> = input.parse()?;
+        let for_token: Token![for] = input.parse()?;
+        let pat: Pat = input.parse()?;
+        let in_token: Token![in] = input.parse()?;
+        let expr: Expr = input.call(expr_no_struct)?;
+
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        let stmts = content.call(Block::parse_within)?;
+
+        Ok(ExprForLoop {
+            attrs: inner_attrs,
+            label: label,
+            for_token: for_token,
+            pat: Box::new(pat),
+            in_token: in_token,
+            expr: Box::new(expr),
+            body: Block {
+                brace_token: brace_token,
+                stmts: stmts,
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
+        let label: Option<Label> = input.parse()?;
+        let loop_token: Token![loop] = input.parse()?;
+
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        let stmts = content.call(Block::parse_within)?;
+
+        Ok(ExprLoop {
+            attrs: inner_attrs,
+            label: label,
+            loop_token: loop_token,
+            body: Block {
+                brace_token: brace_token,
+                stmts: stmts,
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_match(input: ParseStream) -> Result<ExprMatch> {
+        let match_token: Token![match] = input.parse()?;
+        let expr = expr_no_struct(input)?;
+
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+
+        let mut arms = Vec::new();
+        while !content.is_empty() {
+            arms.push(content.call(match_arm)?);
+        }
+
+        Ok(ExprMatch {
+            attrs: inner_attrs,
+            match_token: match_token,
+            expr: Box::new(expr),
+            brace_token: brace_token,
+            arms: arms,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
+        Ok(ExprTryBlock {
+            attrs: Vec::new(),
+            try_token: input.parse()?,
+            block: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_yield(input: ParseStream) -> Result<ExprYield> {
+        Ok(ExprYield {
+            attrs: Vec::new(),
+            yield_token: input.parse()?,
+            expr: {
+                if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
+                    Some(input.parse()?)
+                } else {
+                    None
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn match_arm(input: ParseStream) -> Result<Arm> {
+        let requires_comma;
+        Ok(Arm {
+            attrs: input.call(Attribute::parse_outer)?,
+            leading_vert: input.parse()?,
+            pats: {
+                let mut pats = Punctuated::new();
+                let value: Pat = input.parse()?;
+                pats.push_value(value);
+                loop {
+                    if !input.peek(Token![|]) {
+                        break;
+                    }
+                    let punct = input.parse()?;
+                    pats.push_punct(punct);
+                    let value: Pat = input.parse()?;
+                    pats.push_value(value);
+                }
+                pats
+            },
+            guard: {
+                if input.peek(Token![if]) {
+                    let if_token: Token![if] = input.parse()?;
+                    let guard: Expr = input.parse()?;
+                    Some((if_token, Box::new(guard)))
+                } else {
+                    None
+                }
+            },
+            fat_arrow_token: input.parse()?,
+            body: {
+                let body = input.call(expr_early)?;
+                requires_comma = requires_terminator(&body);
+                Box::new(body)
+            },
+            comma: {
+                if requires_comma && !input.is_empty() {
+                    Some(input.parse()?)
+                } else {
+                    input.parse()?
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
+        let asyncness: Option<Token![async]> = input.parse()?;
+        let movability: Option<Token![static]> = if asyncness.is_none() {
+            input.parse()?
+        } else {
+            None
+        };
+        let capture: Option<Token![move]> = input.parse()?;
+        let or1_token: Token![|] = input.parse()?;
+
+        let mut inputs = Punctuated::new();
+        loop {
+            if input.peek(Token![|]) {
+                break;
+            }
+            let value = fn_arg(input)?;
+            inputs.push_value(value);
+            if input.peek(Token![|]) {
+                break;
+            }
+            let punct: Token![,] = input.parse()?;
+            inputs.push_punct(punct);
+        }
+
+        let or2_token: Token![|] = input.parse()?;
+
+        let (output, body) = if input.peek(Token![->]) {
+            let arrow_token: Token![->] = input.parse()?;
+            let ty: Type = input.parse()?;
+            let body: Block = input.parse()?;
+            let output = ReturnType::Type(arrow_token, Box::new(ty));
+            let block = Expr::Block(ExprBlock {
+                attrs: Vec::new(),
+                label: None,
+                block: body,
+            });
+            (output, block)
+        } else {
+            let body = ambiguous_expr(input, allow_struct)?;
+            (ReturnType::Default, body)
+        };
+
+        Ok(ExprClosure {
+            attrs: Vec::new(),
+            asyncness: asyncness,
+            movability: movability,
+            capture: capture,
+            or1_token: or1_token,
+            inputs: inputs,
+            or2_token: or2_token,
+            output: output,
+            body: Box::new(body),
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_async(input: ParseStream) -> Result<ExprAsync> {
+        Ok(ExprAsync {
+            attrs: Vec::new(),
+            async_token: input.parse()?,
+            capture: input.parse()?,
+            block: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn fn_arg(input: ParseStream) -> Result<FnArg> {
+        let pat: Pat = input.parse()?;
+
+        if input.peek(Token![:]) {
+            Ok(FnArg::Captured(ArgCaptured {
+                pat: pat,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+            }))
+        } else {
+            Ok(FnArg::Inferred(pat))
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_while(input: ParseStream) -> Result<ExprWhile> {
+        let label: Option<Label> = input.parse()?;
+        let while_token: Token![while] = input.parse()?;
+        let cond = expr_no_struct(input)?;
+
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        let stmts = content.call(Block::parse_within)?;
+
+        Ok(ExprWhile {
+            attrs: inner_attrs,
+            label: label,
+            while_token: while_token,
+            cond: Box::new(cond),
+            body: Block {
+                brace_token: brace_token,
+                stmts: stmts,
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_while_let(input: ParseStream) -> Result<ExprWhileLet> {
+        let label: Option<Label> = input.parse()?;
+        let while_token: Token![while] = input.parse()?;
+        let let_token: Token![let] = input.parse()?;
+
+        let mut pats = Punctuated::new();
+        let value: Pat = input.parse()?;
+        pats.push_value(value);
+        while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
+            let punct = input.parse()?;
+            pats.push_punct(punct);
+            let value: Pat = input.parse()?;
+            pats.push_value(value);
+        }
+
+        let eq_token: Token![=] = input.parse()?;
+        let expr = expr_no_struct(input)?;
+
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        let stmts = content.call(Block::parse_within)?;
+
+        Ok(ExprWhileLet {
+            attrs: inner_attrs,
+            label: label,
+            while_token: while_token,
+            let_token: let_token,
+            pats: pats,
+            eq_token: eq_token,
+            expr: Box::new(expr),
+            body: Block {
+                brace_token: brace_token,
+                stmts: stmts,
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for Label {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(Label {
+                name: input.parse()?,
+                colon_token: input.parse()?,
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for Option<Label> {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Lifetime) {
+                input.parse().map(Some)
+            } else {
+                Ok(None)
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
+        Ok(ExprContinue {
+            attrs: Vec::new(),
+            continue_token: input.parse()?,
+            label: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
+        Ok(ExprBreak {
+            attrs: Vec::new(),
+            break_token: input.parse()?,
+            label: input.parse()?,
+            expr: {
+                if input.is_empty()
+                    || input.peek(Token![,])
+                    || input.peek(Token![;])
+                    || !allow_struct.0 && input.peek(token::Brace)
+                {
+                    None
+                } else {
+                    let expr = ambiguous_expr(input, allow_struct)?;
+                    Some(Box::new(expr))
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
+        Ok(ExprReturn {
+            attrs: Vec::new(),
+            return_token: input.parse()?,
+            expr: {
+                if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
+                    None
+                } else {
+                    // NOTE: return is greedy and eats blocks after it even when in a
+                    // position where structs are not allowed, such as in if statement
+                    // conditions. For example:
+                    //
+                    // if return { println!("A") } {} // Prints "A"
+                    let expr = ambiguous_expr(input, allow_struct)?;
+                    Some(Box::new(expr))
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_struct_helper(
+        input: ParseStream,
+        outer_attrs: Vec<Attribute>,
+        path: Path,
+    ) -> Result<ExprStruct> {
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+
+        let mut fields = Punctuated::new();
+        loop {
+            let attrs = content.call(Attribute::parse_outer)?;
+            if content.fork().parse::<Member>().is_err() {
+                if attrs.is_empty() {
+                    break;
+                } else {
+                    return Err(content.error("expected struct field"));
+                }
+            }
+
+            let member: Member = content.parse()?;
+            let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
+                let colon_token: Token![:] = content.parse()?;
+                let value: Expr = content.parse()?;
+                (Some(colon_token), value)
+            } else if let Member::Named(ref ident) = member {
+                let value = Expr::Path(ExprPath {
+                    attrs: Vec::new(),
+                    qself: None,
+                    path: Path::from(ident.clone()),
+                });
+                (None, value)
+            } else {
+                unreachable!()
+            };
+
+            fields.push(FieldValue {
+                attrs: attrs,
+                member: member,
+                colon_token: colon_token,
+                expr: value,
+            });
+
+            if !content.peek(Token![,]) {
+                break;
+            }
+            let punct: Token![,] = content.parse()?;
+            fields.push_punct(punct);
+        }
+
+        let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
+            let dot2_token: Token![..] = content.parse()?;
+            let rest: Expr = content.parse()?;
+            (Some(dot2_token), Some(Box::new(rest)))
+        } else {
+            (None, None)
+        };
+
+        Ok(ExprStruct {
+            attrs: private::attrs(outer_attrs, inner_attrs),
+            brace_token: brace_token,
+            path: path,
+            fields: fields,
+            dot2_token: dot2_token,
+            rest: rest,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
+        let unsafe_token: Token![unsafe] = input.parse()?;
+
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        let stmts = content.call(Block::parse_within)?;
+
+        Ok(ExprUnsafe {
+            attrs: inner_attrs,
+            unsafe_token: unsafe_token,
+            block: Block {
+                brace_token: brace_token,
+                stmts: stmts,
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
+        let label: Option<Label> = input.parse()?;
+
+        let content;
+        let brace_token = braced!(content in input);
+        let inner_attrs = content.call(Attribute::parse_inner)?;
+        let stmts = content.call(Block::parse_within)?;
+
+        Ok(ExprBlock {
+            attrs: inner_attrs,
+            label: label,
+            block: Block {
+                brace_token: brace_token,
+                stmts: stmts,
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
+        Ok(ExprRange {
             attrs: Vec::new(),
             from: None,
-            to: hi.map(Box::new),
-            limits: limits,
-        }.into())
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for RangeLimits {
-        named!(parse -> Self, alt!(
-            // Must come before Dot2
-            punct!(..=) => { RangeLimits::Closed }
-            |
-            // Must come before Dot2
-            punct!(...) => { |dot3| RangeLimits::Closed(Token![..=](dot3.0)) }
-            |
-            punct!(..) => { RangeLimits::HalfOpen }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("range limit: `..`, `...` or `..=`")
-        }
-    }
-
-    impl Synom for ExprPath {
-        #[cfg(not(feature = "full"))]
-        named!(parse -> Self, do_parse!(
-            pair: qpath >>
-            (ExprPath {
-                attrs: Vec::new(),
-                qself: pair.0,
-                path: pair.1,
-            })
-        ));
-
-        #[cfg(feature = "full")]
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            pair: qpath >>
-            (ExprPath {
-                attrs: attrs,
-                qself: pair.0,
-                path: pair.1,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("path: `a::b::c`")
-        }
-    }
-
-    named!(path -> Path, do_parse!(
-        colon: option!(punct!(::)) >>
-        segments: call!(Punctuated::<_, Token![::]>::parse_separated_nonempty_with, path_segment) >>
-        cond_reduce!(segments.first().map_or(true, |seg| seg.value().ident != "dyn")) >>
-        (Path {
-            leading_colon: colon,
-            segments: segments,
+            limits: input.parse()?,
+            to: {
+                if input.is_empty()
+                    || input.peek(Token![,])
+                    || input.peek(Token![;])
+                    || !allow_struct.0 && input.peek(token::Brace)
+                {
+                    None
+                } else {
+                    let to = ambiguous_expr(input, allow_struct)?;
+                    Some(Box::new(to))
+                }
+            },
         })
-    ));
-
-    named!(path_segment -> PathSegment, alt!(
-        do_parse!(
-            ident: syn!(Ident) >>
-            colon2: punct!(::) >>
-            lt: punct!(<) >>
-            args: call!(Punctuated::parse_terminated) >>
-            gt: punct!(>) >>
-            (PathSegment {
-                ident: ident,
-                arguments: PathArguments::AngleBracketed(AngleBracketedGenericArguments {
-                    colon2_token: Some(colon2),
-                    lt_token: lt,
-                    args: args,
-                    gt_token: gt,
-                }),
-            })
-        )
-        |
-        mod_style_path_segment
-    ));
-
-    named!(qpath -> (Option<QSelf>, Path), alt!(
-        map!(path, |p| (None, p))
-        |
-        do_parse!(
-            lt: punct!(<) >>
-            this: syn!(Type) >>
-            path: option!(tuple!(keyword!(as), syn!(Path))) >>
-            gt: punct!(>) >>
-            colon2: punct!(::) >>
-            rest: call!(Punctuated::parse_separated_nonempty_with, path_segment) >>
-            ({
-                let (pos, as_, path) = match path {
-                    Some((as_, mut path)) => {
-                        let pos = path.segments.len();
-                        path.segments.push_punct(colon2);
-                        path.segments.extend(rest.into_pairs());
-                        (pos, Some(as_), path)
-                    }
-                    None => {
-                        (0, None, Path {
-                            leading_colon: Some(colon2),
-                            segments: rest,
-                        })
-                    }
-                };
-                (Some(QSelf {
-                    lt_token: lt,
-                    ty: Box::new(this),
-                    position: pos,
-                    as_token: as_,
-                    gt_token: gt,
-                }), path)
-            })
-        )
-        |
-        map!(keyword!(self), |s| (None, s.into()))
-    ));
-
-    named!(and_field -> (Token![.], Member), tuple!(punct!(.), syn!(Member)));
-
-    named!(and_index -> (token::Bracket, Expr), brackets!(syn!(Expr)));
+    }
 
     #[cfg(feature = "full")]
-    impl Synom for Block {
-        named!(parse -> Self, do_parse!(
-            stmts: braces!(Block::parse_within) >>
-            (Block {
-                brace_token: stmts.0,
-                stmts: stmts.1,
-            })
-        ));
+    impl Parse for RangeLimits {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![..=]) {
+                input.parse().map(RangeLimits::Closed)
+            } else if lookahead.peek(Token![...]) {
+                let dot3: Token![...] = input.parse()?;
+                Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
+            } else if lookahead.peek(Token![..]) {
+                input.parse().map(RangeLimits::HalfOpen)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("block: `{ .. }`")
+    impl Parse for ExprPath {
+        fn parse(input: ParseStream) -> Result<Self> {
+            #[cfg(not(feature = "full"))]
+            let attrs = Vec::new();
+            #[cfg(feature = "full")]
+            let attrs = input.call(Attribute::parse_outer)?;
+
+            let (qself, path) = path::parsing::qpath(input, true)?;
+
+            Ok(ExprPath {
+                attrs: attrs,
+                qself: qself,
+                path: path,
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for Block {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(Block {
+                brace_token: braced!(content in input),
+                stmts: content.call(Block::parse_within)?,
+            })
         }
     }
 
     #[cfg(feature = "full")]
     impl Block {
-        named!(pub parse_within -> Vec<Stmt>, do_parse!(
-            many0!(punct!(;)) >>
-            mut standalone: many0!(do_parse!(
-                stmt: syn!(Stmt) >>
-                many0!(punct!(;)) >>
-                (stmt)
-            )) >>
-            last: option!(do_parse!(
-                attrs: many0!(Attribute::parse_outer) >>
-                mut e: syn!(Expr) >>
-                ({
-                    e.replace_attrs(attrs);
-                    Stmt::Expr(e)
-                })
-            )) >>
-            (match last {
-                None => standalone,
-                Some(last) => {
-                    standalone.push(last);
-                    standalone
+        /// Parse the body of a block as zero or more statements, possibly
+        /// including one trailing expression.
+        ///
+        /// *This function is available if Syn is built with the `"parsing"`
+        /// feature.*
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// # extern crate syn;
+        /// #
+        /// use syn::{braced, token, Attribute, Block, Ident, Stmt, Token};
+        /// use syn::parse::{Parse, ParseStream, Result};
+        ///
+        /// // Parse a function with no generics or parameter list.
+        /// struct MiniFunction {
+        ///     attrs: Vec<Attribute>,
+        ///     fn_token: Token![fn],
+        ///     name: Ident,
+        ///     brace_token: token::Brace,
+        ///     stmts: Vec<Stmt>,
+        /// }
+        ///
+        /// impl Parse for MiniFunction {
+        ///     fn parse(input: ParseStream) -> Result<Self> {
+        ///         let outer_attrs = input.call(Attribute::parse_outer)?;
+        ///         let fn_token: Token![fn] = input.parse()?;
+        ///         let name: Ident = input.parse()?;
+        ///
+        ///         let content;
+        ///         let brace_token = braced!(content in input);
+        ///         let inner_attrs = content.call(Attribute::parse_inner)?;
+        ///         let stmts = content.call(Block::parse_within)?;
+        ///
+        ///         Ok(MiniFunction {
+        ///             attrs: {
+        ///                 let mut attrs = outer_attrs;
+        ///                 attrs.extend(inner_attrs);
+        ///                 attrs
+        ///             },
+        ///             fn_token: fn_token,
+        ///             name: name,
+        ///             brace_token: brace_token,
+        ///             stmts: stmts,
+        ///         })
+        ///     }
+        /// }
+        /// #
+        /// # fn main() {}
+        /// ```
+        pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
+            let mut stmts = Vec::new();
+            loop {
+                while input.peek(Token![;]) {
+                    input.parse::<Token![;]>()?;
                 }
-            })
-        ));
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for Stmt {
-        named!(parse -> Self, alt!(
-            stmt_mac
-            |
-            stmt_local
-            |
-            stmt_item
-            |
-            stmt_blockexpr
-            |
-            stmt_expr
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("statement")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    named!(stmt_mac -> Stmt, do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        what: call!(Path::parse_mod_style) >>
-        bang: punct!(!) >>
-    // Only parse braces here; paren and bracket will get parsed as
-    // expression statements
-        data: braces!(syn!(TokenStream)) >>
-        semi: option!(punct!(;)) >>
-        (Stmt::Item(Item::Macro(ItemMacro {
-            attrs: attrs,
-            ident: None,
-            mac: Macro {
-                path: what,
-                bang_token: bang,
-                delimiter: MacroDelimiter::Brace(data.0),
-                tts: data.1,
-            },
-            semi_token: semi,
-        })))
-    ));
-
-    #[cfg(feature = "full")]
-    named!(stmt_local -> Stmt, do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        let_: keyword!(let) >>
-        pats: call!(Punctuated::parse_separated_nonempty) >>
-        ty: option!(tuple!(punct!(:), syn!(Type))) >>
-        init: option!(tuple!(punct!(=), syn!(Expr))) >>
-        semi: punct!(;) >>
-        (Stmt::Local(Local {
-            attrs: attrs,
-            let_token: let_,
-            pats: pats,
-            ty: ty.map(|(colon, ty)| (colon, Box::new(ty))),
-            init: init.map(|(eq, expr)| (eq, Box::new(expr))),
-            semi_token: semi,
-        }))
-    ));
-
-    #[cfg(feature = "full")]
-    named!(stmt_item -> Stmt, map!(syn!(Item), |i| Stmt::Item(i)));
-
-    #[cfg(feature = "full")]
-    named!(stmt_blockexpr -> Stmt, do_parse!(
-        mut attrs: many0!(Attribute::parse_outer) >>
-        mut e: expr_nosemi >>
-        semi: option!(punct!(;)) >>
-        ({
-            attrs.extend(e.replace_attrs(Vec::new()));
-            e.replace_attrs(attrs);
-            if let Some(semi) = semi {
-                Stmt::Semi(e, semi)
-            } else {
-                Stmt::Expr(e)
+                if input.is_empty() {
+                    break;
+                }
+                let s = parse_stmt(input, true)?;
+                let requires_semicolon = if let Stmt::Expr(ref s) = s {
+                    requires_terminator(s)
+                } else {
+                    false
+                };
+                stmts.push(s);
+                if input.is_empty() {
+                    break;
+                } else if requires_semicolon {
+                    return Err(input.error("unexpected token"));
+                }
             }
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    named!(stmt_expr -> Stmt, do_parse!(
-        mut attrs: many0!(Attribute::parse_outer) >>
-        mut e: syn!(Expr) >>
-        semi: punct!(;) >>
-        ({
-            attrs.extend(e.replace_attrs(Vec::new()));
-            e.replace_attrs(attrs);
-            Stmt::Semi(e, semi)
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for Pat {
-        named!(parse -> Self, alt!(
-            syn!(PatWild) => { Pat::Wild } // must be before pat_ident
-            |
-            syn!(PatBox) => { Pat::Box }  // must be before pat_ident
-            |
-            syn!(PatRange) => { Pat::Range } // must be before pat_lit
-            |
-            syn!(PatTupleStruct) => { Pat::TupleStruct }  // must be before pat_ident
-            |
-            syn!(PatStruct) => { Pat::Struct } // must be before pat_ident
-            |
-            syn!(PatMacro) => { Pat::Macro } // must be before pat_ident
-            |
-            syn!(PatLit) => { Pat::Lit } // must be before pat_ident
-            |
-            syn!(PatIdent) => { Pat::Ident } // must be before pat_path
-            |
-            syn!(PatPath) => { Pat::Path }
-            |
-            syn!(PatTuple) => { Pat::Tuple }
-            |
-            syn!(PatRef) => { Pat::Ref }
-            |
-            syn!(PatSlice) => { Pat::Slice }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("pattern")
+            Ok(stmts)
         }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatWild {
-        named!(parse -> Self, map!(
-            punct!(_),
-            |u| PatWild { underscore_token: u }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("wild pattern: `_`")
+    impl Parse for Stmt {
+        fn parse(input: ParseStream) -> Result<Self> {
+            parse_stmt(input, false)
         }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatBox {
-        named!(parse -> Self, do_parse!(
-            boxed: keyword!(box) >>
-            pat: syn!(Pat) >>
-            (PatBox {
+    fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
+        let ahead = input.fork();
+        ahead.call(Attribute::parse_outer)?;
+
+        if {
+            let ahead = ahead.fork();
+            // Only parse braces here; paren and bracket will get parsed as
+            // expression statements
+            ahead.call(Path::parse_mod_style).is_ok()
+                && ahead.parse::<Token![!]>().is_ok()
+                && (ahead.peek(token::Brace) || ahead.peek(Ident))
+        } {
+            stmt_mac(input)
+        } else if ahead.peek(Token![let]) {
+            stmt_local(input).map(Stmt::Local)
+        } else if ahead.peek(Token![pub])
+            || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
+            || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
+            || ahead.peek(Token![use])
+            || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
+            || ahead.peek(Token![const])
+            || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
+            || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
+            || ahead.peek(Token![fn])
+            || ahead.peek(Token![mod])
+            || ahead.peek(Token![type])
+            || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
+            || ahead.peek(Token![struct])
+            || ahead.peek(Token![enum])
+            || ahead.peek(Token![union]) && ahead.peek2(Ident)
+            || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
+            || ahead.peek(Token![trait])
+            || ahead.peek(Token![default])
+                && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl ]))
+            || ahead.peek(Token![impl ])
+            || ahead.peek(Token![macro])
+        {
+            input.parse().map(Stmt::Item)
+        } else {
+            stmt_expr(input, allow_nosemi)
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn stmt_mac(input: ParseStream) -> Result<Stmt> {
+        let attrs = input.call(Attribute::parse_outer)?;
+        let path = input.call(Path::parse_mod_style)?;
+        let bang_token: Token![!] = input.parse()?;
+        let ident: Option<Ident> = input.parse()?;
+        let (delimiter, tts) = mac::parse_delimiter(input)?;
+        let semi_token: Option<Token![;]> = input.parse()?;
+
+        Ok(Stmt::Item(Item::Macro(ItemMacro {
+            attrs: attrs,
+            ident: ident,
+            mac: Macro {
+                path: path,
+                bang_token: bang_token,
+                delimiter: delimiter,
+                tts: tts,
+            },
+            semi_token: semi_token,
+        })))
+    }
+
+    #[cfg(feature = "full")]
+    fn stmt_local(input: ParseStream) -> Result<Local> {
+        Ok(Local {
+            attrs: input.call(Attribute::parse_outer)?,
+            let_token: input.parse()?,
+            pats: {
+                let mut pats = Punctuated::new();
+                let value: Pat = input.parse()?;
+                pats.push_value(value);
+                while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
+                    let punct = input.parse()?;
+                    pats.push_punct(punct);
+                    let value: Pat = input.parse()?;
+                    pats.push_value(value);
+                }
+                pats
+            },
+            ty: {
+                if input.peek(Token![:]) {
+                    let colon_token: Token![:] = input.parse()?;
+                    let ty: Type = input.parse()?;
+                    Some((colon_token, Box::new(ty)))
+                } else {
+                    None
+                }
+            },
+            init: {
+                if input.peek(Token![=]) {
+                    let eq_token: Token![=] = input.parse()?;
+                    let init: Expr = input.parse()?;
+                    Some((eq_token, Box::new(init)))
+                } else {
+                    None
+                }
+            },
+            semi_token: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
+        let mut attrs = input.call(Attribute::parse_outer)?;
+        let mut e = expr_early(input)?;
+
+        attrs.extend(e.replace_attrs(Vec::new()));
+        e.replace_attrs(attrs);
+
+        if input.peek(Token![;]) {
+            return Ok(Stmt::Semi(e, input.parse()?));
+        }
+
+        if allow_nosemi || !requires_terminator(&e) {
+            Ok(Stmt::Expr(e))
+        } else {
+            Err(input.error("expected semicolon"))
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Parse for Pat {
+        fn parse(input: ParseStream) -> Result<Self> {
+            // TODO: better error messages
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![_]) {
+                input.call(pat_wild).map(Pat::Wild)
+            } else if lookahead.peek(Token![box]) {
+                input.call(pat_box).map(Pat::Box)
+            } else if input.fork().call(pat_range).is_ok() {
+                // must be before Pat::Lit
+                input.call(pat_range).map(Pat::Range)
+            } else if input.fork().call(pat_tuple_struct).is_ok() {
+                // must be before Pat::Ident
+                input.call(pat_tuple_struct).map(Pat::TupleStruct)
+            } else if input.fork().call(pat_struct).is_ok() {
+                // must be before Pat::Ident
+                input.call(pat_struct).map(Pat::Struct)
+            } else if input.fork().call(pat_macro).is_ok() {
+                // must be before Pat::Ident
+                input.call(pat_macro).map(Pat::Macro)
+            } else if input.fork().call(pat_lit).is_ok() {
+                // must be before Pat::Ident
+                input.call(pat_lit).map(Pat::Lit)
+            } else if input.fork().call(pat_ident).is_ok() {
+                input.call(pat_ident).map(Pat::Ident)
+            } else if input.fork().call(pat_path).is_ok() {
+                input.call(pat_path).map(Pat::Path)
+            } else if lookahead.peek(token::Paren) {
+                input.call(pat_tuple).map(Pat::Tuple)
+            } else if lookahead.peek(Token![&]) {
+                input.call(pat_ref).map(Pat::Ref)
+            } else if lookahead.peek(token::Bracket) {
+                input.call(pat_slice).map(Pat::Slice)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_wild(input: ParseStream) -> Result<PatWild> {
+        Ok(PatWild {
+            underscore_token: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_box(input: ParseStream) -> Result<PatBox> {
+        Ok(PatBox {
+            box_token: input.parse()?,
+            pat: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_ident(input: ParseStream) -> Result<PatIdent> {
+        Ok(PatIdent {
+            by_ref: input.parse()?,
+            mutability: input.parse()?,
+            ident: {
+                let ident = if input.peek(Ident) || input.peek(Token![self]) {
+                    input.call(Ident::parse_any)?
+                } else {
+                    return Err(input.error("expected identifier or `self`"));
+                };
+                if input.peek(Token![<]) || input.peek(Token![::]) {
+                    return Err(input.error("unexpected token"));
+                }
+                ident
+            },
+            subpat: {
+                if input.peek(Token![@]) {
+                    let at_token: Token![@] = input.parse()?;
+                    let subpat: Pat = input.parse()?;
+                    Some((at_token, Box::new(subpat)))
+                } else {
+                    None
+                }
+            },
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_tuple_struct(input: ParseStream) -> Result<PatTupleStruct> {
+        Ok(PatTupleStruct {
+            path: input.parse()?,
+            pat: input.call(pat_tuple)?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_struct(input: ParseStream) -> Result<PatStruct> {
+        let path: Path = input.parse()?;
+
+        let content;
+        let brace_token = braced!(content in input);
+
+        let mut fields = Punctuated::new();
+        while !content.is_empty() && !content.peek(Token![..]) {
+            let value = content.call(field_pat)?;
+            fields.push_value(value);
+            if !content.peek(Token![,]) {
+                break;
+            }
+            let punct: Token![,] = content.parse()?;
+            fields.push_punct(punct);
+        }
+
+        let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
+            Some(content.parse()?)
+        } else {
+            None
+        };
+
+        Ok(PatStruct {
+            path: path,
+            brace_token: brace_token,
+            fields: fields,
+            dot2_token: dot2_token,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn field_pat(input: ParseStream) -> Result<FieldPat> {
+        let boxed: Option<Token![box]> = input.parse()?;
+        let by_ref: Option<Token![ref]> = input.parse()?;
+        let mutability: Option<Token![mut]> = input.parse()?;
+        let member: Member = input.parse()?;
+
+        if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
+            || member.is_unnamed()
+        {
+            return Ok(FieldPat {
+                attrs: Vec::new(),
+                member: member,
+                colon_token: input.parse()?,
+                pat: input.parse()?,
+            });
+        }
+
+        let ident = match member {
+            Member::Named(ident) => ident,
+            Member::Unnamed(_) => unreachable!(),
+        };
+
+        let mut pat = Pat::Ident(PatIdent {
+            by_ref: by_ref,
+            mutability: mutability,
+            ident: ident.clone(),
+            subpat: None,
+        });
+
+        if let Some(boxed) = boxed {
+            pat = Pat::Box(PatBox {
                 pat: Box::new(pat),
                 box_token: boxed,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("box pattern")
+            });
         }
+
+        Ok(FieldPat {
+            member: Member::Named(ident),
+            pat: Box::new(pat),
+            attrs: Vec::new(),
+            colon_token: None,
+        })
     }
 
-    #[cfg(feature = "full")]
-    impl Synom for PatIdent {
-        named!(parse -> Self, do_parse!(
-            by_ref: option!(keyword!(ref)) >>
-            mutability: option!(keyword!(mut)) >>
-            name: alt!(
-                syn!(Ident)
-                |
-                keyword!(self) => { Into::into }
-            ) >>
-            not!(punct!(<)) >>
-            not!(punct!(::)) >>
-            subpat: option!(tuple!(punct!(@), syn!(Pat))) >>
-            (PatIdent {
-                by_ref: by_ref,
-                mutability: mutability,
-                ident: name,
-                subpat: subpat.map(|(at, pat)| (at, Box::new(pat))),
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("pattern identifier binding")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatTupleStruct {
-        named!(parse -> Self, do_parse!(
-            path: syn!(Path) >>
-            tuple: syn!(PatTuple) >>
-            (PatTupleStruct {
-                path: path,
-                pat: tuple,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("tuple struct pattern")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatStruct {
-        named!(parse -> Self, do_parse!(
-            path: syn!(Path) >>
-            data: braces!(do_parse!(
-                fields: call!(Punctuated::parse_terminated) >>
-                base: option!(cond!(fields.empty_or_trailing(), punct!(..))) >>
-                (fields, base)
-            )) >>
-            (PatStruct {
-                path: path,
-                fields: (data.1).0,
-                brace_token: data.0,
-                dot2_token: (data.1).1.and_then(|m| m),
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("struct pattern")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for FieldPat {
-        named!(parse -> Self, alt!(
-            do_parse!(
-                member: syn!(Member) >>
-                colon: punct!(:) >>
-                pat: syn!(Pat) >>
-                (FieldPat {
-                    member: member,
-                    pat: Box::new(pat),
-                    attrs: Vec::new(),
-                    colon_token: Some(colon),
-                })
-            )
-            |
-            do_parse!(
-                boxed: option!(keyword!(box)) >>
-                by_ref: option!(keyword!(ref)) >>
-                mutability: option!(keyword!(mut)) >>
-                ident: syn!(Ident) >>
-                ({
-                    let mut pat: Pat = PatIdent {
-                        by_ref: by_ref,
-                        mutability: mutability,
-                        ident: ident.clone(),
-                        subpat: None,
-                    }.into();
-                    if let Some(boxed) = boxed {
-                        pat = PatBox {
-                            pat: Box::new(pat),
-                            box_token: boxed,
-                        }.into();
-                    }
-                    FieldPat {
-                        member: Member::Named(ident),
-                        pat: Box::new(pat),
-                        attrs: Vec::new(),
-                        colon_token: None,
-                    }
-                })
-            )
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("field pattern")
-        }
-    }
-
-    impl Synom for Member {
-        named!(parse -> Self, alt!(
-            syn!(Ident) => { Member::Named }
-            |
-            syn!(Index) => { Member::Unnamed }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("field member")
-        }
-    }
-
-    impl Synom for Index {
-        named!(parse -> Self, do_parse!(
-            lit: syn!(LitInt) >>
-            ({
-                if let IntSuffix::None = lit.suffix() {
-                    Index { index: lit.value() as u32, span: lit.span() }
-                } else {
-                    return parse_error();
-                }
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("field index")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatPath {
-        named!(parse -> Self, map!(
-            syn!(ExprPath),
-            |p| PatPath { qself: p.qself, path: p.path }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("path pattern")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatTuple {
-        named!(parse -> Self, do_parse!(
-            data: parens!(do_parse!(
-                front: call!(Punctuated::parse_terminated) >>
-                dotdot: option!(cond_reduce!(front.empty_or_trailing(),
-                    tuple!(punct!(..), option!(punct!(,)))
-                )) >>
-                back: cond!(match dotdot {
-                                Some((_, Some(_))) => true,
-                                _ => false,
-                            },
-                            Punctuated::parse_terminated) >>
-                (front, dotdot, back)
-            )) >>
-            ({
-                let (parens, (front, dotdot, back)) = data;
-                let (dotdot, trailing) = match dotdot {
-                    Some((a, b)) => (Some(a), Some(b)),
-                    None => (None, None),
-                };
-                PatTuple {
-                    paren_token: parens,
-                    front: front,
-                    dot2_token: dotdot,
-                    comma_token: trailing.unwrap_or_default(),
-                    back: back.unwrap_or_default(),
-                }
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("tuple pattern")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatRef {
-        named!(parse -> Self, do_parse!(
-            and: punct!(&) >>
-            mutability: option!(keyword!(mut)) >>
-            pat: syn!(Pat) >>
-            (PatRef {
-                pat: Box::new(pat),
-                mutability: mutability,
-                and_token: and,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("reference pattern")
-        }
-    }
-
-    #[cfg(feature = "full")]
-    impl Synom for PatLit {
-        named!(parse -> Self, do_parse!(
-            lit: pat_lit_expr >>
-            (if let Expr::Path(_) = lit {
-                return parse_error(); // these need to be parsed by pat_path
+    impl Parse for Member {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Ident) {
+                input.parse().map(Member::Named)
+            } else if input.peek(LitInt) {
+                input.parse().map(Member::Unnamed)
             } else {
-                PatLit {
-                    expr: Box::new(lit),
-                }
-            })
-        ));
+                Err(input.error("expected identifier or integer"))
+            }
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("literal pattern")
+    impl Parse for Index {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let lit: LitInt = input.parse()?;
+            if let IntSuffix::None = lit.suffix() {
+                Ok(Index {
+                    index: lit.value() as u32,
+                    span: lit.span(),
+                })
+            } else {
+                Err(Error::new(lit.span(), "expected unsuffixed integer"))
+            }
         }
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatRange {
-        named!(parse -> Self, do_parse!(
-            lo: pat_lit_expr >>
-            limits: syn!(RangeLimits) >>
-            hi: pat_lit_expr >>
-            (PatRange {
-                lo: Box::new(lo),
-                hi: Box::new(hi),
-                limits: limits,
-            })
-        ));
+    fn pat_path(input: ParseStream) -> Result<PatPath> {
+        let p: ExprPath = input.parse()?;
+        Ok(PatPath {
+            qself: p.qself,
+            path: p.path,
+        })
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("range pattern")
+    #[cfg(feature = "full")]
+    fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
+        let content;
+        let paren_token = parenthesized!(content in input);
+
+        let mut front = Punctuated::new();
+        let mut dot2_token = None::<Token![..]>;
+        let mut comma_token = None::<Token![,]>;
+        loop {
+            if content.is_empty() {
+                break;
+            }
+            if content.peek(Token![..]) {
+                dot2_token = Some(content.parse()?);
+                comma_token = content.parse()?;
+                break;
+            }
+            let value: Pat = content.parse()?;
+            front.push_value(value);
+            if content.is_empty() {
+                break;
+            }
+            let punct = content.parse()?;
+            front.push_punct(punct);
+        }
+
+        let mut back = Punctuated::new();
+        while !content.is_empty() {
+            let value: Pat = content.parse()?;
+            back.push_value(value);
+            if content.is_empty() {
+                break;
+            }
+            let punct = content.parse()?;
+            back.push_punct(punct);
+        }
+
+        Ok(PatTuple {
+            paren_token: paren_token,
+            front: front,
+            dot2_token: dot2_token,
+            comma_token: comma_token,
+            back: back,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_ref(input: ParseStream) -> Result<PatRef> {
+        Ok(PatRef {
+            and_token: input.parse()?,
+            mutability: input.parse()?,
+            pat: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_lit(input: ParseStream) -> Result<PatLit> {
+        if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
+            Ok(PatLit {
+                expr: input.call(pat_lit_expr)?,
+            })
+        } else {
+            Err(input.error("expected literal pattern"))
         }
     }
 
     #[cfg(feature = "full")]
-    named!(pat_lit_expr -> Expr, do_parse!(
-        neg: option!(punct!(-)) >>
-        v: alt!(
-            syn!(ExprLit) => { Expr::Lit }
-            |
-            syn!(ExprPath) => { Expr::Path }
-        ) >>
-        (if let Some(neg) = neg {
+    fn pat_range(input: ParseStream) -> Result<PatRange> {
+        Ok(PatRange {
+            lo: input.call(pat_lit_expr)?,
+            limits: input.parse()?,
+            hi: input.call(pat_lit_expr)?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
+        let neg: Option<Token![-]> = input.parse()?;
+
+        let lookahead = input.lookahead1();
+        let expr = if lookahead.peek(Lit) {
+            Expr::Lit(input.call(expr_lit)?)
+        } else if lookahead.peek(Ident)
+            || lookahead.peek(Token![::])
+            || lookahead.peek(Token![<])
+            || lookahead.peek(Token![self])
+            || lookahead.peek(Token![Self])
+            || lookahead.peek(Token![super])
+            || lookahead.peek(Token![extern])
+            || lookahead.peek(Token![crate])
+        {
+            Expr::Path(input.parse()?)
+        } else {
+            return Err(lookahead.error());
+        };
+
+        Ok(Box::new(if let Some(neg) = neg {
             Expr::Unary(ExprUnary {
                 attrs: Vec::new(),
                 op: UnOp::Neg(neg),
-                expr: Box::new(v)
+                expr: Box::new(expr),
             })
         } else {
-            v
-        })
-    ));
-
-    #[cfg(feature = "full")]
-    impl Synom for PatSlice {
-        named!(parse -> Self, map!(
-            brackets!(do_parse!(
-                before: call!(Punctuated::parse_terminated) >>
-                middle: option!(do_parse!(
-                    dots: punct!(..) >>
-                    trailing: option!(punct!(,)) >>
-                    (dots, trailing)
-                )) >>
-                after: cond!(
-                    match middle {
-                        Some((_, ref trailing)) => trailing.is_some(),
-                        _ => false,
-                    },
-                    Punctuated::parse_terminated
-                ) >>
-                (before, middle, after)
-            )),
-            |(brackets, (before, middle, after))| {
-                let mut before: Punctuated<Pat, Token![,]> = before;
-                let after: Option<Punctuated<Pat, Token![,]>> = after;
-                let middle: Option<(Token![..], Option<Token![,]>)> = middle;
-                PatSlice {
-                    dot2_token: middle.as_ref().map(|m| Token![..]((m.0).0)),
-                    comma_token: middle.as_ref().and_then(|m| {
-                        m.1.as_ref().map(|m| Token![,](m.0))
-                    }),
-                    bracket_token: brackets,
-                    middle: middle.and_then(|_| {
-                        if before.empty_or_trailing() {
-                            None
-                        } else {
-                            Some(Box::new(before.pop().unwrap().into_value()))
-                        }
-                    }),
-                    front: before,
-                    back: after.unwrap_or_default(),
-                }
-            }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("slice pattern")
-        }
+            expr
+        }))
     }
 
     #[cfg(feature = "full")]
-    impl Synom for PatMacro {
-        named!(parse -> Self, map!(syn!(Macro), |mac| PatMacro { mac: mac }));
+    fn pat_slice(input: ParseStream) -> Result<PatSlice> {
+        let content;
+        let bracket_token = bracketed!(content in input);
 
-        fn description() -> Option<&'static str> {
-            Some("macro pattern")
+        let mut front = Punctuated::new();
+        let mut middle = None;
+        loop {
+            if content.is_empty() || content.peek(Token![..]) {
+                break;
+            }
+            let value: Pat = content.parse()?;
+            if content.peek(Token![..]) {
+                middle = Some(Box::new(value));
+                break;
+            }
+            front.push_value(value);
+            if content.is_empty() {
+                break;
+            }
+            let punct = content.parse()?;
+            front.push_punct(punct);
+        }
+
+        let dot2_token: Option<Token![..]> = content.parse()?;
+        let mut comma_token = None::<Token![,]>;
+        let mut back = Punctuated::new();
+        if dot2_token.is_some() {
+            comma_token = content.parse()?;
+            if comma_token.is_some() {
+                loop {
+                    if content.is_empty() {
+                        break;
+                    }
+                    let value: Pat = content.parse()?;
+                    back.push_value(value);
+                    if content.is_empty() {
+                        break;
+                    }
+                    let punct = content.parse()?;
+                    back.push_punct(punct);
+                }
+            }
+        }
+
+        Ok(PatSlice {
+            bracket_token: bracket_token,
+            front: front,
+            middle: middle,
+            dot2_token: dot2_token,
+            comma_token: comma_token,
+            back: back,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    fn pat_macro(input: ParseStream) -> Result<PatMacro> {
+        Ok(PatMacro {
+            mac: input.parse()?,
+        })
+    }
+
+    #[cfg(feature = "full")]
+    impl Member {
+        fn is_named(&self) -> bool {
+            match *self {
+                Member::Named(_) => true,
+                Member::Unnamed(_) => false,
+            }
+        }
+
+        fn is_unnamed(&self) -> bool {
+            match *self {
+                Member::Named(_) => false,
+                Member::Unnamed(_) => true,
+            }
         }
     }
 }
@@ -3139,11 +3025,15 @@
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
-    #[cfg(feature = "full")]
-    use attr::FilterAttrs;
+
     use proc_macro2::{Literal, TokenStream};
     use quote::{ToTokens, TokenStreamExt};
 
+    #[cfg(feature = "full")]
+    use attr::FilterAttrs;
+    #[cfg(feature = "full")]
+    use print::TokensOrDefault;
+
     // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
     // before appending it to `TokenStream`.
     #[cfg(feature = "full")]
@@ -3424,7 +3314,7 @@
                     // Ensure that we have a comma after a non-block arm, except
                     // for the last one.
                     let is_last = i == self.arms.len() - 1;
-                    if !is_last && arm_expr_requires_comma(&arm.body) && arm.comma.is_none() {
+                    if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
                         <Token![,]>::default().to_tokens(tokens);
                     }
                 }
@@ -3433,11 +3323,20 @@
     }
 
     #[cfg(feature = "full")]
-    impl ToTokens for ExprCatch {
+    impl ToTokens for ExprAsync {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             outer_attrs_to_tokens(&self.attrs, tokens);
-            self.do_token.to_tokens(tokens);
-            self.catch_token.to_tokens(tokens);
+            self.async_token.to_tokens(tokens);
+            self.capture.to_tokens(tokens);
+            self.block.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprTryBlock {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.try_token.to_tokens(tokens);
             self.block.to_tokens(tokens);
         }
     }
@@ -3455,6 +3354,7 @@
     impl ToTokens for ExprClosure {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             outer_attrs_to_tokens(&self.attrs, tokens);
+            self.asyncness.to_tokens(tokens);
             self.movability.to_tokens(tokens);
             self.capture.to_tokens(tokens);
             self.or1_token.to_tokens(tokens);
@@ -3493,6 +3393,7 @@
     impl ToTokens for ExprBlock {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             outer_attrs_to_tokens(&self.attrs, tokens);
+            self.label.to_tokens(tokens);
             self.block.brace_token.surround(tokens, |tokens| {
                 inner_attrs_to_tokens(&self.attrs, tokens);
                 tokens.append_all(&self.block.stmts);
@@ -3572,7 +3473,7 @@
     impl ToTokens for ExprPath {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             outer_attrs_to_tokens(&self.attrs, tokens);
-            ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
+            private::print_path(tokens, &self.qself, &self.path);
         }
     }
 
@@ -3768,7 +3669,7 @@
     #[cfg(feature = "full")]
     impl ToTokens for PatPath {
         fn to_tokens(&self, tokens: &mut TokenStream) {
-            ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
+            private::print_path(tokens, &self.qself, &self.path);
         }
     }
 
@@ -3824,7 +3725,7 @@
             self.lo.to_tokens(tokens);
             match self.limits {
                 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
-                RangeLimits::Closed(ref t) => Token![...](t.0).to_tokens(tokens),
+                RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
             }
             self.hi.to_tokens(tokens);
         }
@@ -3833,8 +3734,6 @@
     #[cfg(feature = "full")]
     impl ToTokens for PatSlice {
         fn to_tokens(&self, tokens: &mut TokenStream) {
-            // XXX: This is a mess, and it will be so easy to screw it up. How
-            // do we make this correct itself better?
             self.bracket_token.surround(tokens, |tokens| {
                 self.front.to_tokens(tokens);
 
diff --git a/src/ext.rs b/src/ext.rs
new file mode 100644
index 0000000..0a412e4
--- /dev/null
+++ b/src/ext.rs
@@ -0,0 +1,64 @@
+//! Extension traits to provide parsing methods on foreign types.
+//!
+//! *This module is available if Syn is built with the `"parsing"` feature.*
+
+use proc_macro2::Ident;
+
+use parse::{ParseStream, Result};
+
+/// Additional parsing methods for `Ident`.
+///
+/// This trait is sealed and cannot be implemented for types outside of Syn.
+///
+/// *This trait is available if Syn is built with the `"parsing"` feature.*
+pub trait IdentExt: Sized + private::Sealed {
+    /// Parses any identifier including keywords.
+    ///
+    /// This is useful when parsing a DSL which allows Rust keywords as
+    /// identifiers.
+    ///
+    /// ```rust
+    /// # extern crate syn;
+    /// #
+    /// use syn::{Ident, Token};
+    /// use syn::ext::IdentExt;
+    /// use syn::parse::{Error, ParseStream, Result};
+    ///
+    /// // Parses input that looks like `name = NAME` where `NAME` can be
+    /// // any identifier.
+    /// //
+    /// // Examples:
+    /// //
+    /// //     name = anything
+    /// //     name = impl
+    /// fn parse_dsl(input: ParseStream) -> Result<Ident> {
+    ///     let name_token: Ident = input.parse()?;
+    ///     if name_token != "name" {
+    ///         return Err(Error::new(name_token.span(), "expected `name`"));
+    ///     }
+    ///     input.parse::<Token![=]>()?;
+    ///     let name = input.call(Ident::parse_any)?;
+    ///     Ok(name)
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    fn parse_any(input: ParseStream) -> Result<Self>;
+}
+
+impl IdentExt for Ident {
+    fn parse_any(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| match cursor.ident() {
+            Some((ident, rest)) => Ok((ident, rest)),
+            None => Err(cursor.error("expected ident")),
+        })
+    }
+}
+
+mod private {
+    use proc_macro2::Ident;
+
+    pub trait Sealed {}
+
+    impl Sealed for Ident {}
+}
diff --git a/src/file.rs b/src/file.rs
index 9b5b11f..1f6054a 100644
--- a/src/file.rs
+++ b/src/file.rs
@@ -19,8 +19,8 @@
     /// representation of the syntax tree.
     ///
     /// ```
-    /// extern crate syn;
-    ///
+    /// # extern crate syn;
+    /// #
     /// use std::env;
     /// use std::fs::File;
     /// use std::io::Read;
@@ -88,21 +88,21 @@
 pub mod parsing {
     use super::*;
 
-    use synom::Synom;
+    use parse::{Parse, ParseStream, Result};
 
-    impl Synom for File {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_inner) >>
-            items: many0!(Item::parse) >>
-            (File {
+    impl Parse for File {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(File {
                 shebang: None,
-                attrs: attrs,
-                items: items,
+                attrs: input.call(Attribute::parse_inner)?,
+                items: {
+                    let mut items = Vec::new();
+                    while !input.is_empty() {
+                        items.push(input.parse()?);
+                    }
+                    items
+                },
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("crate")
         }
     }
 }
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index 54eb51a..31d1cf3 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -132,6 +132,11 @@
     fn fold_expr_assign_op(&mut self, i: ExprAssignOp) -> ExprAssignOp {
         fold_expr_assign_op(self, i)
     }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_async(&mut self, i: ExprAsync) -> ExprAsync {
+        fold_expr_async(self, i)
+    }
     #[cfg(any(feature = "full", feature = "derive"))]
     fn fold_expr_binary(&mut self, i: ExprBinary) -> ExprBinary {
         fold_expr_binary(self, i)
@@ -161,11 +166,6 @@
     }
     #[cfg(feature = "full")]
     #[cfg(any(feature = "full", feature = "derive"))]
-    fn fold_expr_catch(&mut self, i: ExprCatch) -> ExprCatch {
-        fold_expr_catch(self, i)
-    }
-    #[cfg(feature = "full")]
-    #[cfg(any(feature = "full", feature = "derive"))]
     fn fold_expr_closure(&mut self, i: ExprClosure) -> ExprClosure {
         fold_expr_closure(self, i)
     }
@@ -271,6 +271,11 @@
     }
     #[cfg(feature = "full")]
     #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_try_block(&mut self, i: ExprTryBlock) -> ExprTryBlock {
+        fold_expr_try_block(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
     fn fold_expr_tuple(&mut self, i: ExprTuple) -> ExprTuple {
         fold_expr_tuple(self, i)
     }
@@ -354,6 +359,10 @@
         fold_foreign_item_fn(self, i)
     }
     #[cfg(feature = "full")]
+    fn fold_foreign_item_macro(&mut self, i: ForeignItemMacro) -> ForeignItemMacro {
+        fold_foreign_item_macro(self, i)
+    }
+    #[cfg(feature = "full")]
     fn fold_foreign_item_static(&mut self, i: ForeignItemStatic) -> ForeignItemStatic {
         fold_foreign_item_static(self, i)
     }
@@ -394,6 +403,10 @@
         fold_impl_item_const(self, i)
     }
     #[cfg(feature = "full")]
+    fn fold_impl_item_existential(&mut self, i: ImplItemExistential) -> ImplItemExistential {
+        fold_impl_item_existential(self, i)
+    }
+    #[cfg(feature = "full")]
     fn fold_impl_item_macro(&mut self, i: ImplItemMacro) -> ImplItemMacro {
         fold_impl_item_macro(self, i)
     }
@@ -426,6 +439,10 @@
         fold_item_enum(self, i)
     }
     #[cfg(feature = "full")]
+    fn fold_item_existential(&mut self, i: ItemExistential) -> ItemExistential {
+        fold_item_existential(self, i)
+    }
+    #[cfg(feature = "full")]
     fn fold_item_extern_crate(&mut self, i: ItemExternCrate) -> ItemExternCrate {
         fold_item_extern_crate(self, i)
     }
@@ -466,6 +483,10 @@
         fold_item_trait(self, i)
     }
     #[cfg(feature = "full")]
+    fn fold_item_trait_alias(&mut self, i: ItemTraitAlias) -> ItemTraitAlias {
+        fold_item_trait_alias(self, i)
+    }
+    #[cfg(feature = "full")]
     fn fold_item_type(&mut self, i: ItemType) -> ItemType {
         fold_item_type(self, i)
     }
@@ -486,7 +507,6 @@
     fn fold_label(&mut self, i: Label) -> Label {
         fold_label(self, i)
     }
-    #[cfg(any(feature = "full", feature = "derive"))]
     fn fold_lifetime(&mut self, i: Lifetime) -> Lifetime {
         fold_lifetime(self, i)
     }
@@ -880,7 +900,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_abi<V: Fold + ?Sized>(_visitor: &mut V, _i: Abi) -> Abi {
     Abi {
-        extern_token: Token![extern](tokens_helper(_visitor, &(_i.extern_token).0)),
+        extern_token: Token![extern](tokens_helper(_visitor, &_i.extern_token.span)),
         name: (_i.name).map(|it| _visitor.fold_lit_str(it)),
     }
 }
@@ -890,34 +910,35 @@
     _i: AngleBracketedGenericArguments,
 ) -> AngleBracketedGenericArguments {
     AngleBracketedGenericArguments {
-        colon2_token: (_i.colon2_token).map(|it| Token ! [ :: ](tokens_helper(_visitor, &(it).0))),
-        lt_token: Token ! [ < ](tokens_helper(_visitor, &(_i.lt_token).0)),
+        colon2_token: (_i.colon2_token)
+            .map(|it| Token ! [ :: ](tokens_helper(_visitor, &it.spans))),
+        lt_token: Token ! [ < ](tokens_helper(_visitor, &_i.lt_token.spans)),
         args: FoldHelper::lift(_i.args, |it| _visitor.fold_generic_argument(it)),
-        gt_token: Token ! [ > ](tokens_helper(_visitor, &(_i.gt_token).0)),
+        gt_token: Token ! [ > ](tokens_helper(_visitor, &_i.gt_token.spans)),
     }
 }
 #[cfg(feature = "full")]
 pub fn fold_arg_captured<V: Fold + ?Sized>(_visitor: &mut V, _i: ArgCaptured) -> ArgCaptured {
     ArgCaptured {
         pat: _visitor.fold_pat(_i.pat),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: _visitor.fold_type(_i.ty),
     }
 }
 #[cfg(feature = "full")]
 pub fn fold_arg_self<V: Fold + ?Sized>(_visitor: &mut V, _i: ArgSelf) -> ArgSelf {
     ArgSelf {
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
-        self_token: Token![self](tokens_helper(_visitor, &(_i.self_token).0)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
+        self_token: Token![self](tokens_helper(_visitor, &_i.self_token.span)),
     }
 }
 #[cfg(feature = "full")]
 pub fn fold_arg_self_ref<V: Fold + ?Sized>(_visitor: &mut V, _i: ArgSelfRef) -> ArgSelfRef {
     ArgSelfRef {
-        and_token: Token ! [ & ](tokens_helper(_visitor, &(_i.and_token).0)),
+        and_token: Token ! [ & ](tokens_helper(_visitor, &_i.and_token.spans)),
         lifetime: (_i.lifetime).map(|it| _visitor.fold_lifetime(it)),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
-        self_token: Token![self](tokens_helper(_visitor, &(_i.self_token).0)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
+        self_token: Token![self](tokens_helper(_visitor, &_i.self_token.span)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -925,17 +946,17 @@
 pub fn fold_arm<V: Fold + ?Sized>(_visitor: &mut V, _i: Arm) -> Arm {
     Arm {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        leading_vert: (_i.leading_vert).map(|it| Token ! [ | ](tokens_helper(_visitor, &(it).0))),
+        leading_vert: (_i.leading_vert).map(|it| Token ! [ | ](tokens_helper(_visitor, &it.spans))),
         pats: FoldHelper::lift(_i.pats, |it| _visitor.fold_pat(it)),
         guard: (_i.guard).map(|it| {
             (
-                Token ! [ if ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ if ](tokens_helper(_visitor, &(it).0.span)),
                 Box::new(_visitor.fold_expr(*(it).1)),
             )
         }),
-        fat_arrow_token: Token ! [ => ](tokens_helper(_visitor, &(_i.fat_arrow_token).0)),
+        fat_arrow_token: Token ! [ => ](tokens_helper(_visitor, &_i.fat_arrow_token.spans)),
         body: Box::new(_visitor.fold_expr(*_i.body)),
-        comma: (_i.comma).map(|it| Token ! [ , ](tokens_helper(_visitor, &(it).0))),
+        comma: (_i.comma).map(|it| Token ! [ , ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -943,19 +964,18 @@
     match _i {
         AttrStyle::Outer => AttrStyle::Outer,
         AttrStyle::Inner(_binding_0) => {
-            AttrStyle::Inner(Token![!](tokens_helper(_visitor, &(_binding_0).0)))
+            AttrStyle::Inner(Token![!](tokens_helper(_visitor, &_binding_0.spans)))
         }
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_attribute<V: Fold + ?Sized>(_visitor: &mut V, _i: Attribute) -> Attribute {
     Attribute {
-        pound_token: Token ! [ # ](tokens_helper(_visitor, &(_i.pound_token).0)),
+        pound_token: Token ! [ # ](tokens_helper(_visitor, &_i.pound_token.spans)),
         style: _visitor.fold_attr_style(_i.style),
-        bracket_token: Bracket(tokens_helper(_visitor, &(_i.bracket_token).0)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
         path: _visitor.fold_path(_i.path),
         tts: _i.tts,
-        is_sugared_doc: _i.is_sugared_doc,
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -964,7 +984,7 @@
         name: (_i.name).map(|it| {
             (
                 _visitor.fold_bare_fn_arg_name((it).0),
-                Token ! [ : ](tokens_helper(_visitor, &((it).1).0)),
+                Token ! [ : ](tokens_helper(_visitor, &(it).1.spans)),
             )
         }),
         ty: _visitor.fold_type(_i.ty),
@@ -978,7 +998,7 @@
     match _i {
         BareFnArgName::Named(_binding_0) => BareFnArgName::Named(_visitor.fold_ident(_binding_0)),
         BareFnArgName::Wild(_binding_0) => {
-            BareFnArgName::Wild(Token![_](tokens_helper(_visitor, &(_binding_0).0)))
+            BareFnArgName::Wild(Token![_](tokens_helper(_visitor, &_binding_0.spans)))
         }
     }
 }
@@ -986,84 +1006,88 @@
 pub fn fold_bin_op<V: Fold + ?Sized>(_visitor: &mut V, _i: BinOp) -> BinOp {
     match _i {
         BinOp::Add(_binding_0) => {
-            BinOp::Add(Token ! [ + ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Add(Token ! [ + ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Sub(_binding_0) => {
-            BinOp::Sub(Token ! [ - ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Sub(Token ! [ - ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Mul(_binding_0) => {
-            BinOp::Mul(Token ! [ * ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Mul(Token ! [ * ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Div(_binding_0) => {
-            BinOp::Div(Token ! [ / ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Div(Token ! [ / ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Rem(_binding_0) => {
-            BinOp::Rem(Token ! [ % ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Rem(Token ! [ % ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::And(_binding_0) => {
-            BinOp::And(Token ! [ && ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::And(Token ! [ && ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Or(_binding_0) => {
-            BinOp::Or(Token ! [ || ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Or(Token ! [ || ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::BitXor(_binding_0) => {
-            BinOp::BitXor(Token ! [ ^ ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::BitXor(Token ! [ ^ ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::BitAnd(_binding_0) => {
-            BinOp::BitAnd(Token ! [ & ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::BitAnd(Token ! [ & ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::BitOr(_binding_0) => {
-            BinOp::BitOr(Token ! [ | ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::BitOr(Token ! [ | ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Shl(_binding_0) => {
-            BinOp::Shl(Token ! [ << ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Shl(Token ! [ << ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Shr(_binding_0) => {
-            BinOp::Shr(Token ! [ >> ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Shr(Token ! [ >> ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Eq(_binding_0) => {
-            BinOp::Eq(Token ! [ == ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Eq(Token ! [ == ](tokens_helper(_visitor, &_binding_0.spans)))
         }
-        BinOp::Lt(_binding_0) => BinOp::Lt(Token ! [ < ](tokens_helper(_visitor, &(_binding_0).0))),
+        BinOp::Lt(_binding_0) => {
+            BinOp::Lt(Token ! [ < ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
         BinOp::Le(_binding_0) => {
-            BinOp::Le(Token ! [ <= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Le(Token ! [ <= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Ne(_binding_0) => {
-            BinOp::Ne(Token ! [ != ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Ne(Token ! [ != ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::Ge(_binding_0) => {
-            BinOp::Ge(Token ! [ >= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::Ge(Token ! [ >= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
-        BinOp::Gt(_binding_0) => BinOp::Gt(Token ! [ > ](tokens_helper(_visitor, &(_binding_0).0))),
+        BinOp::Gt(_binding_0) => {
+            BinOp::Gt(Token ! [ > ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
         BinOp::AddEq(_binding_0) => {
-            BinOp::AddEq(Token ! [ += ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::AddEq(Token ! [ += ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::SubEq(_binding_0) => {
-            BinOp::SubEq(Token ! [ -= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::SubEq(Token ! [ -= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::MulEq(_binding_0) => {
-            BinOp::MulEq(Token ! [ *= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::MulEq(Token ! [ *= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::DivEq(_binding_0) => {
-            BinOp::DivEq(Token ! [ /= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::DivEq(Token ! [ /= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::RemEq(_binding_0) => {
-            BinOp::RemEq(Token ! [ %= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::RemEq(Token ! [ %= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::BitXorEq(_binding_0) => {
-            BinOp::BitXorEq(Token ! [ ^= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::BitXorEq(Token ! [ ^= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::BitAndEq(_binding_0) => {
-            BinOp::BitAndEq(Token ! [ &= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::BitAndEq(Token ! [ &= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::BitOrEq(_binding_0) => {
-            BinOp::BitOrEq(Token ! [ |= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::BitOrEq(Token ! [ |= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::ShlEq(_binding_0) => {
-            BinOp::ShlEq(Token ! [ <<= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::ShlEq(Token ! [ <<= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
         BinOp::ShrEq(_binding_0) => {
-            BinOp::ShrEq(Token ! [ >>= ](tokens_helper(_visitor, &(_binding_0).0)))
+            BinOp::ShrEq(Token ! [ >>= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
     }
 }
@@ -1071,7 +1095,7 @@
 pub fn fold_binding<V: Fold + ?Sized>(_visitor: &mut V, _i: Binding) -> Binding {
     Binding {
         ident: _visitor.fold_ident(_i.ident),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         ty: _visitor.fold_type(_i.ty),
     }
 }
@@ -1079,7 +1103,7 @@
 #[cfg(feature = "full")]
 pub fn fold_block<V: Fold + ?Sized>(_visitor: &mut V, _i: Block) -> Block {
     Block {
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         stmts: FoldHelper::lift(_i.stmts, |it| _visitor.fold_stmt(it)),
     }
 }
@@ -1089,21 +1113,21 @@
     _i: BoundLifetimes,
 ) -> BoundLifetimes {
     BoundLifetimes {
-        for_token: Token ! [ for ](tokens_helper(_visitor, &(_i.for_token).0)),
-        lt_token: Token ! [ < ](tokens_helper(_visitor, &(_i.lt_token).0)),
+        for_token: Token ! [ for ](tokens_helper(_visitor, &_i.for_token.span)),
+        lt_token: Token ! [ < ](tokens_helper(_visitor, &_i.lt_token.spans)),
         lifetimes: FoldHelper::lift(_i.lifetimes, |it| _visitor.fold_lifetime_def(it)),
-        gt_token: Token ! [ > ](tokens_helper(_visitor, &(_i.gt_token).0)),
+        gt_token: Token ! [ > ](tokens_helper(_visitor, &_i.gt_token.spans)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_const_param<V: Fold + ?Sized>(_visitor: &mut V, _i: ConstParam) -> ConstParam {
     ConstParam {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        const_token: Token ! [ const ](tokens_helper(_visitor, &(_i.const_token).0)),
+        const_token: Token ! [ const ](tokens_helper(_visitor, &_i.const_token.span)),
         ident: _visitor.fold_ident(_i.ident),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: _visitor.fold_type(_i.ty),
-        eq_token: (_i.eq_token).map(|it| Token ! [ = ](tokens_helper(_visitor, &(it).0))),
+        eq_token: (_i.eq_token).map(|it| Token ! [ = ](tokens_helper(_visitor, &it.spans))),
         default: (_i.default).map(|it| _visitor.fold_expr(it)),
     }
 }
@@ -1118,23 +1142,23 @@
 #[cfg(feature = "derive")]
 pub fn fold_data_enum<V: Fold + ?Sized>(_visitor: &mut V, _i: DataEnum) -> DataEnum {
     DataEnum {
-        enum_token: Token ! [ enum ](tokens_helper(_visitor, &(_i.enum_token).0)),
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        enum_token: Token ! [ enum ](tokens_helper(_visitor, &_i.enum_token.span)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         variants: FoldHelper::lift(_i.variants, |it| _visitor.fold_variant(it)),
     }
 }
 #[cfg(feature = "derive")]
 pub fn fold_data_struct<V: Fold + ?Sized>(_visitor: &mut V, _i: DataStruct) -> DataStruct {
     DataStruct {
-        struct_token: Token ! [ struct ](tokens_helper(_visitor, &(_i.struct_token).0)),
+        struct_token: Token ! [ struct ](tokens_helper(_visitor, &_i.struct_token.span)),
         fields: _visitor.fold_fields(_i.fields),
-        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &(it).0))),
+        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "derive")]
 pub fn fold_data_union<V: Fold + ?Sized>(_visitor: &mut V, _i: DataUnion) -> DataUnion {
     DataUnion {
-        union_token: Token![union](tokens_helper(_visitor, &(_i.union_token).0)),
+        union_token: Token![union](tokens_helper(_visitor, &_i.union_token.span)),
         fields: _visitor.fold_fields_named(_i.fields),
     }
 }
@@ -1198,7 +1222,10 @@
         Expr::Paren(_binding_0) => Expr::Paren(_visitor.fold_expr_paren(_binding_0)),
         Expr::Group(_binding_0) => Expr::Group(full!(_visitor.fold_expr_group(_binding_0))),
         Expr::Try(_binding_0) => Expr::Try(full!(_visitor.fold_expr_try(_binding_0))),
-        Expr::Catch(_binding_0) => Expr::Catch(full!(_visitor.fold_expr_catch(_binding_0))),
+        Expr::Async(_binding_0) => Expr::Async(full!(_visitor.fold_expr_async(_binding_0))),
+        Expr::TryBlock(_binding_0) => {
+            Expr::TryBlock(full!(_visitor.fold_expr_try_block(_binding_0)))
+        }
         Expr::Yield(_binding_0) => Expr::Yield(full!(_visitor.fold_expr_yield(_binding_0))),
         Expr::Verbatim(_binding_0) => Expr::Verbatim(_visitor.fold_expr_verbatim(_binding_0)),
     }
@@ -1208,7 +1235,7 @@
 pub fn fold_expr_array<V: Fold + ?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)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
         elems: FoldHelper::lift(_i.elems, |it| _visitor.fold_expr(it)),
     }
 }
@@ -1218,7 +1245,7 @@
     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)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         right: Box::new(_visitor.fold_expr(*_i.right)),
     }
 }
@@ -1232,6 +1259,16 @@
         right: Box::new(_visitor.fold_expr(*_i.right)),
     }
 }
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_async<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprAsync) -> ExprAsync {
+    ExprAsync {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        async_token: Token![async](tokens_helper(_visitor, &_i.async_token.span)),
+        capture: (_i.capture).map(|it| Token ! [ move ](tokens_helper(_visitor, &it.span))),
+        block: _visitor.fold_block(_i.block),
+    }
+}
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_expr_binary<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprBinary) -> ExprBinary {
     ExprBinary {
@@ -1246,6 +1283,7 @@
 pub fn fold_expr_block<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprBlock) -> ExprBlock {
     ExprBlock {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        label: (_i.label).map(|it| _visitor.fold_label(it)),
         block: _visitor.fold_block(_i.block),
     }
 }
@@ -1254,7 +1292,7 @@
 pub fn fold_expr_box<V: Fold + ?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)),
+        box_token: Token ! [ box ](tokens_helper(_visitor, &_i.box_token.span)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
     }
 }
@@ -1263,7 +1301,7 @@
 pub fn fold_expr_break<V: Fold + ?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)),
+        break_token: Token![break](tokens_helper(_visitor, &_i.break_token.span)),
         label: (_i.label).map(|it| _visitor.fold_lifetime(it)),
         expr: (_i.expr).map(|it| Box::new(_visitor.fold_expr(*it))),
     }
@@ -1273,7 +1311,7 @@
     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)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         args: FoldHelper::lift(_i.args, |it| _visitor.fold_expr(it)),
     }
 }
@@ -1282,30 +1320,21 @@
     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)),
+        as_token: Token ! [ as ](tokens_helper(_visitor, &_i.as_token.span)),
         ty: Box::new(_visitor.fold_type(*_i.ty)),
     }
 }
 #[cfg(feature = "full")]
 #[cfg(any(feature = "full", feature = "derive"))]
-pub fn fold_expr_catch<V: Fold + ?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")]
-#[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_expr_closure<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprClosure) -> ExprClosure {
     ExprClosure {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        movability: (_i.movability).map(|it| Token ! [ static ](tokens_helper(_visitor, &(it).0))),
-        capture: (_i.capture).map(|it| Token ! [ move ](tokens_helper(_visitor, &(it).0))),
-        or1_token: Token ! [ | ](tokens_helper(_visitor, &(_i.or1_token).0)),
+        asyncness: (_i.asyncness).map(|it| Token![async](tokens_helper(_visitor, &it.span))),
+        movability: (_i.movability).map(|it| Token ! [ static ](tokens_helper(_visitor, &it.span))),
+        capture: (_i.capture).map(|it| Token ! [ move ](tokens_helper(_visitor, &it.span))),
+        or1_token: Token ! [ | ](tokens_helper(_visitor, &_i.or1_token.spans)),
         inputs: FoldHelper::lift(_i.inputs, |it| _visitor.fold_fn_arg(it)),
-        or2_token: Token ! [ | ](tokens_helper(_visitor, &(_i.or2_token).0)),
+        or2_token: Token ! [ | ](tokens_helper(_visitor, &_i.or2_token.spans)),
         output: _visitor.fold_return_type(_i.output),
         body: Box::new(_visitor.fold_expr(*_i.body)),
     }
@@ -1315,7 +1344,7 @@
 pub fn fold_expr_continue<V: Fold + ?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)),
+        continue_token: Token![continue](tokens_helper(_visitor, &_i.continue_token.span)),
         label: (_i.label).map(|it| _visitor.fold_lifetime(it)),
     }
 }
@@ -1324,7 +1353,7 @@
     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)),
+        dot_token: Token ! [ . ](tokens_helper(_visitor, &_i.dot_token.spans)),
         member: _visitor.fold_member(_i.member),
     }
 }
@@ -1334,9 +1363,9 @@
     ExprForLoop {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         label: (_i.label).map(|it| _visitor.fold_label(it)),
-        for_token: Token ! [ for ](tokens_helper(_visitor, &(_i.for_token).0)),
+        for_token: Token ! [ for ](tokens_helper(_visitor, &_i.for_token.span)),
         pat: Box::new(_visitor.fold_pat(*_i.pat)),
-        in_token: Token ! [ in ](tokens_helper(_visitor, &(_i.in_token).0)),
+        in_token: Token ! [ in ](tokens_helper(_visitor, &_i.in_token.span)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
         body: _visitor.fold_block(_i.body),
     }
@@ -1346,7 +1375,7 @@
 pub fn fold_expr_group<V: Fold + ?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)),
+        group_token: Group(tokens_helper(_visitor, &_i.group_token.span)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
     }
 }
@@ -1355,12 +1384,12 @@
 pub fn fold_expr_if<V: Fold + ?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)),
+        if_token: Token ! [ if ](tokens_helper(_visitor, &_i.if_token.span)),
         cond: Box::new(_visitor.fold_expr(*_i.cond)),
         then_branch: _visitor.fold_block(_i.then_branch),
         else_branch: (_i.else_branch).map(|it| {
             (
-                Token ! [ else ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ else ](tokens_helper(_visitor, &(it).0.span)),
                 Box::new(_visitor.fold_expr(*(it).1)),
             )
         }),
@@ -1371,15 +1400,15 @@
 pub fn fold_expr_if_let<V: Fold + ?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)),
+        if_token: Token ! [ if ](tokens_helper(_visitor, &_i.if_token.span)),
+        let_token: Token ! [ let ](tokens_helper(_visitor, &_i.let_token.span)),
         pats: FoldHelper::lift(_i.pats, |it| _visitor.fold_pat(it)),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
         then_branch: _visitor.fold_block(_i.then_branch),
         else_branch: (_i.else_branch).map(|it| {
             (
-                Token ! [ else ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ else ](tokens_helper(_visitor, &(it).0.span)),
                 Box::new(_visitor.fold_expr(*(it).1)),
             )
         }),
@@ -1391,7 +1420,7 @@
     ExprInPlace {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         place: Box::new(_visitor.fold_expr(*_i.place)),
-        arrow_token: Token ! [ <- ](tokens_helper(_visitor, &(_i.arrow_token).0)),
+        arrow_token: Token ! [ <- ](tokens_helper(_visitor, &_i.arrow_token.spans)),
         value: Box::new(_visitor.fold_expr(*_i.value)),
     }
 }
@@ -1400,7 +1429,7 @@
     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)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
         index: Box::new(_visitor.fold_expr(*_i.index)),
     }
 }
@@ -1417,7 +1446,7 @@
     ExprLoop {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         label: (_i.label).map(|it| _visitor.fold_label(it)),
-        loop_token: Token ! [ loop ](tokens_helper(_visitor, &(_i.loop_token).0)),
+        loop_token: Token ! [ loop ](tokens_helper(_visitor, &_i.loop_token.span)),
         body: _visitor.fold_block(_i.body),
     }
 }
@@ -1434,9 +1463,9 @@
 pub fn fold_expr_match<V: Fold + ?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)),
+        match_token: Token ! [ match ](tokens_helper(_visitor, &_i.match_token.span)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         arms: FoldHelper::lift(_i.arms, |it| _visitor.fold_arm(it)),
     }
 }
@@ -1449,10 +1478,10 @@
     ExprMethodCall {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         receiver: Box::new(_visitor.fold_expr(*_i.receiver)),
-        dot_token: Token ! [ . ](tokens_helper(_visitor, &(_i.dot_token).0)),
+        dot_token: Token ! [ . ](tokens_helper(_visitor, &_i.dot_token.spans)),
         method: _visitor.fold_ident(_i.method),
         turbofish: (_i.turbofish).map(|it| _visitor.fold_method_turbofish(it)),
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         args: FoldHelper::lift(_i.args, |it| _visitor.fold_expr(it)),
     }
 }
@@ -1460,7 +1489,7 @@
 pub fn fold_expr_paren<V: Fold + ?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)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
     }
 }
@@ -1487,8 +1516,8 @@
 pub fn fold_expr_reference<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprReference) -> ExprReference {
     ExprReference {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        and_token: Token ! [ & ](tokens_helper(_visitor, &(_i.and_token).0)),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
+        and_token: Token ! [ & ](tokens_helper(_visitor, &_i.and_token.spans)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
     }
 }
@@ -1497,9 +1526,9 @@
 pub fn fold_expr_repeat<V: Fold + ?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)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
         len: Box::new(_visitor.fold_expr(*_i.len)),
     }
 }
@@ -1508,7 +1537,7 @@
 pub fn fold_expr_return<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprReturn) -> ExprReturn {
     ExprReturn {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        return_token: Token![return](tokens_helper(_visitor, &(_i.return_token).0)),
+        return_token: Token![return](tokens_helper(_visitor, &_i.return_token.span)),
         expr: (_i.expr).map(|it| Box::new(_visitor.fold_expr(*it))),
     }
 }
@@ -1518,9 +1547,9 @@
     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)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         fields: FoldHelper::lift(_i.fields, |it| _visitor.fold_field_value(it)),
-        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &(it).0))),
+        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &it.spans))),
         rest: (_i.rest).map(|it| Box::new(_visitor.fold_expr(*it))),
     }
 }
@@ -1530,7 +1559,16 @@
     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)),
+        question_token: Token ! [ ? ](tokens_helper(_visitor, &_i.question_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_try_block<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprTryBlock) -> ExprTryBlock {
+    ExprTryBlock {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        try_token: Token![try](tokens_helper(_visitor, &_i.try_token.span)),
+        block: _visitor.fold_block(_i.block),
     }
 }
 #[cfg(feature = "full")]
@@ -1538,7 +1576,7 @@
 pub fn fold_expr_tuple<V: Fold + ?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)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         elems: FoldHelper::lift(_i.elems, |it| _visitor.fold_expr(it)),
     }
 }
@@ -1548,7 +1586,7 @@
     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)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: Box::new(_visitor.fold_type(*_i.ty)),
     }
 }
@@ -1565,7 +1603,7 @@
 pub fn fold_expr_unsafe<V: Fold + ?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)),
+        unsafe_token: Token ! [ unsafe ](tokens_helper(_visitor, &_i.unsafe_token.span)),
         block: _visitor.fold_block(_i.block),
     }
 }
@@ -1579,7 +1617,7 @@
     ExprWhile {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         label: (_i.label).map(|it| _visitor.fold_label(it)),
-        while_token: Token ! [ while ](tokens_helper(_visitor, &(_i.while_token).0)),
+        while_token: Token ! [ while ](tokens_helper(_visitor, &_i.while_token.span)),
         cond: Box::new(_visitor.fold_expr(*_i.cond)),
         body: _visitor.fold_block(_i.body),
     }
@@ -1590,10 +1628,10 @@
     ExprWhileLet {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         label: (_i.label).map(|it| _visitor.fold_label(it)),
-        while_token: Token ! [ while ](tokens_helper(_visitor, &(_i.while_token).0)),
-        let_token: Token ! [ let ](tokens_helper(_visitor, &(_i.let_token).0)),
+        while_token: Token ! [ while ](tokens_helper(_visitor, &_i.while_token.span)),
+        let_token: Token ! [ let ](tokens_helper(_visitor, &_i.let_token.span)),
         pats: FoldHelper::lift(_i.pats, |it| _visitor.fold_pat(it)),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
         body: _visitor.fold_block(_i.body),
     }
@@ -1603,7 +1641,7 @@
 pub fn fold_expr_yield<V: Fold + ?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)),
+        yield_token: Token![yield](tokens_helper(_visitor, &_i.yield_token.span)),
         expr: (_i.expr).map(|it| Box::new(_visitor.fold_expr(*it))),
     }
 }
@@ -1613,7 +1651,7 @@
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
         ident: (_i.ident).map(|it| _visitor.fold_ident(it)),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
         ty: _visitor.fold_type(_i.ty),
     }
 }
@@ -1623,7 +1661,7 @@
     FieldPat {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         member: _visitor.fold_member(_i.member),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
         pat: Box::new(_visitor.fold_pat(*_i.pat)),
     }
 }
@@ -1633,7 +1671,7 @@
     FieldValue {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         member: _visitor.fold_member(_i.member),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
         expr: _visitor.fold_expr(_i.expr),
     }
 }
@@ -1648,14 +1686,14 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_fields_named<V: Fold + ?Sized>(_visitor: &mut V, _i: FieldsNamed) -> FieldsNamed {
     FieldsNamed {
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         named: FoldHelper::lift(_i.named, |it| _visitor.fold_field(it)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_fields_unnamed<V: Fold + ?Sized>(_visitor: &mut V, _i: FieldsUnnamed) -> FieldsUnnamed {
     FieldsUnnamed {
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         unnamed: FoldHelper::lift(_i.unnamed, |it| _visitor.fold_field(it)),
     }
 }
@@ -1680,11 +1718,11 @@
 #[cfg(feature = "full")]
 pub fn fold_fn_decl<V: Fold + ?Sized>(_visitor: &mut V, _i: FnDecl) -> FnDecl {
     FnDecl {
-        fn_token: Token ! [ fn ](tokens_helper(_visitor, &(_i.fn_token).0)),
+        fn_token: Token ! [ fn ](tokens_helper(_visitor, &_i.fn_token.span)),
         generics: _visitor.fold_generics(_i.generics),
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         inputs: FoldHelper::lift(_i.inputs, |it| _visitor.fold_fn_arg(it)),
-        variadic: (_i.variadic).map(|it| Token ! [ ... ](tokens_helper(_visitor, &(it).0))),
+        variadic: (_i.variadic).map(|it| Token ! [ ... ](tokens_helper(_visitor, &it.spans))),
         output: _visitor.fold_return_type(_i.output),
     }
 }
@@ -1698,6 +1736,9 @@
         ForeignItem::Type(_binding_0) => {
             ForeignItem::Type(_visitor.fold_foreign_item_type(_binding_0))
         }
+        ForeignItem::Macro(_binding_0) => {
+            ForeignItem::Macro(_visitor.fold_foreign_item_macro(_binding_0))
+        }
         ForeignItem::Verbatim(_binding_0) => {
             ForeignItem::Verbatim(_visitor.fold_foreign_item_verbatim(_binding_0))
         }
@@ -1713,7 +1754,18 @@
         vis: _visitor.fold_visibility(_i.vis),
         ident: _visitor.fold_ident(_i.ident),
         decl: Box::new(_visitor.fold_fn_decl(*_i.decl)),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_foreign_item_macro<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ForeignItemMacro,
+) -> ForeignItemMacro {
+    ForeignItemMacro {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        mac: _visitor.fold_macro(_i.mac),
+        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "full")]
@@ -1724,12 +1776,12 @@
     ForeignItemStatic {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        static_token: Token ! [ static ](tokens_helper(_visitor, &(_i.static_token).0)),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
+        static_token: Token ! [ static ](tokens_helper(_visitor, &_i.static_token.span)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
         ident: _visitor.fold_ident(_i.ident),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: Box::new(_visitor.fold_type(*_i.ty)),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -1740,9 +1792,9 @@
     ForeignItemType {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        type_token: Token ! [ type ](tokens_helper(_visitor, &(_i.type_token).0)),
+        type_token: Token ! [ type ](tokens_helper(_visitor, &_i.type_token.span)),
         ident: _visitor.fold_ident(_i.ident),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -1800,9 +1852,9 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_generics<V: Fold + ?Sized>(_visitor: &mut V, _i: Generics) -> Generics {
     Generics {
-        lt_token: (_i.lt_token).map(|it| Token ! [ < ](tokens_helper(_visitor, &(it).0))),
+        lt_token: (_i.lt_token).map(|it| Token ! [ < ](tokens_helper(_visitor, &it.spans))),
         params: FoldHelper::lift(_i.params, |it| _visitor.fold_generic_param(it)),
-        gt_token: (_i.gt_token).map(|it| Token ! [ > ](tokens_helper(_visitor, &(it).0))),
+        gt_token: (_i.gt_token).map(|it| Token ! [ > ](tokens_helper(_visitor, &it.spans))),
         where_clause: (_i.where_clause).map(|it| _visitor.fold_where_clause(it)),
     }
 }
@@ -1820,6 +1872,9 @@
             ImplItem::Method(_visitor.fold_impl_item_method(_binding_0))
         }
         ImplItem::Type(_binding_0) => ImplItem::Type(_visitor.fold_impl_item_type(_binding_0)),
+        ImplItem::Existential(_binding_0) => {
+            ImplItem::Existential(_visitor.fold_impl_item_existential(_binding_0))
+        }
         ImplItem::Macro(_binding_0) => ImplItem::Macro(_visitor.fold_impl_item_macro(_binding_0)),
         ImplItem::Verbatim(_binding_0) => {
             ImplItem::Verbatim(_visitor.fold_impl_item_verbatim(_binding_0))
@@ -1834,14 +1889,30 @@
     ImplItemConst {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &(it).0))),
-        const_token: Token ! [ const ](tokens_helper(_visitor, &(_i.const_token).0)),
+        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &it.span))),
+        const_token: Token ! [ const ](tokens_helper(_visitor, &_i.const_token.span)),
         ident: _visitor.fold_ident(_i.ident),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: _visitor.fold_type(_i.ty),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         expr: _visitor.fold_expr(_i.expr),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_impl_item_existential<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ImplItemExistential,
+) -> ImplItemExistential {
+    ImplItemExistential {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        existential_token: Token![existential](tokens_helper(_visitor, &_i.existential_token.span)),
+        type_token: Token ! [ type ](tokens_helper(_visitor, &_i.type_token.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        generics: _visitor.fold_generics(_i.generics),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
+        bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -1852,7 +1923,7 @@
     ImplItemMacro {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         mac: _visitor.fold_macro(_i.mac),
-        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &(it).0))),
+        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "full")]
@@ -1863,7 +1934,7 @@
     ImplItemMethod {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &(it).0))),
+        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &it.span))),
         sig: _visitor.fold_method_sig(_i.sig),
         block: _visitor.fold_block(_i.block),
     }
@@ -1873,13 +1944,13 @@
     ImplItemType {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &(it).0))),
-        type_token: Token ! [ type ](tokens_helper(_visitor, &(_i.type_token).0)),
+        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &it.span))),
+        type_token: Token ! [ type ](tokens_helper(_visitor, &_i.type_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         generics: _visitor.fold_generics(_i.generics),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         ty: _visitor.fold_type(_i.ty),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -1911,10 +1982,16 @@
             Item::ForeignMod(_visitor.fold_item_foreign_mod(_binding_0))
         }
         Item::Type(_binding_0) => Item::Type(_visitor.fold_item_type(_binding_0)),
+        Item::Existential(_binding_0) => {
+            Item::Existential(_visitor.fold_item_existential(_binding_0))
+        }
         Item::Struct(_binding_0) => Item::Struct(_visitor.fold_item_struct(_binding_0)),
         Item::Enum(_binding_0) => Item::Enum(_visitor.fold_item_enum(_binding_0)),
         Item::Union(_binding_0) => Item::Union(_visitor.fold_item_union(_binding_0)),
         Item::Trait(_binding_0) => Item::Trait(_visitor.fold_item_trait(_binding_0)),
+        Item::TraitAlias(_binding_0) => {
+            Item::TraitAlias(_visitor.fold_item_trait_alias(_binding_0))
+        }
         Item::Impl(_binding_0) => Item::Impl(_visitor.fold_item_impl(_binding_0)),
         Item::Macro(_binding_0) => Item::Macro(_visitor.fold_item_macro(_binding_0)),
         Item::Macro2(_binding_0) => Item::Macro2(_visitor.fold_item_macro2(_binding_0)),
@@ -1926,13 +2003,13 @@
     ItemConst {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        const_token: Token ! [ const ](tokens_helper(_visitor, &(_i.const_token).0)),
+        const_token: Token ! [ const ](tokens_helper(_visitor, &_i.const_token.span)),
         ident: _visitor.fold_ident(_i.ident),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: Box::new(_visitor.fold_type(*_i.ty)),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -1940,14 +2017,31 @@
     ItemEnum {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        enum_token: Token ! [ enum ](tokens_helper(_visitor, &(_i.enum_token).0)),
+        enum_token: Token ! [ enum ](tokens_helper(_visitor, &_i.enum_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         generics: _visitor.fold_generics(_i.generics),
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         variants: FoldHelper::lift(_i.variants, |it| _visitor.fold_variant(it)),
     }
 }
 #[cfg(feature = "full")]
+pub fn fold_item_existential<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ItemExistential,
+) -> ItemExistential {
+    ItemExistential {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        vis: _visitor.fold_visibility(_i.vis),
+        existential_token: Token![existential](tokens_helper(_visitor, &_i.existential_token.span)),
+        type_token: Token ! [ type ](tokens_helper(_visitor, &_i.type_token.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        generics: _visitor.fold_generics(_i.generics),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
+        bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
 pub fn fold_item_extern_crate<V: Fold + ?Sized>(
     _visitor: &mut V,
     _i: ItemExternCrate,
@@ -1955,16 +2049,16 @@
     ItemExternCrate {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        extern_token: Token![extern](tokens_helper(_visitor, &(_i.extern_token).0)),
-        crate_token: Token![crate](tokens_helper(_visitor, &(_i.crate_token).0)),
+        extern_token: Token![extern](tokens_helper(_visitor, &_i.extern_token.span)),
+        crate_token: Token![crate](tokens_helper(_visitor, &_i.crate_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         rename: (_i.rename).map(|it| {
             (
-                Token ! [ as ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ as ](tokens_helper(_visitor, &(it).0.span)),
                 _visitor.fold_ident((it).1),
             )
         }),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -1972,8 +2066,9 @@
     ItemFn {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        constness: (_i.constness).map(|it| Token ! [ const ](tokens_helper(_visitor, &(it).0))),
-        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &(it).0))),
+        constness: (_i.constness).map(|it| Token ! [ const ](tokens_helper(_visitor, &it.span))),
+        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &it.span))),
+        asyncness: (_i.asyncness).map(|it| Token![async](tokens_helper(_visitor, &it.span))),
         abi: (_i.abi).map(|it| _visitor.fold_abi(it)),
         ident: _visitor.fold_ident(_i.ident),
         decl: Box::new(_visitor.fold_fn_decl(*_i.decl)),
@@ -1988,7 +2083,7 @@
     ItemForeignMod {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         abi: _visitor.fold_abi(_i.abi),
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         items: FoldHelper::lift(_i.items, |it| _visitor.fold_foreign_item(it)),
     }
 }
@@ -1996,19 +2091,19 @@
 pub fn fold_item_impl<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemImpl) -> ItemImpl {
     ItemImpl {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &(it).0))),
-        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &(it).0))),
-        impl_token: Token![impl ](tokens_helper(_visitor, &(_i.impl_token).0)),
+        defaultness: (_i.defaultness).map(|it| Token![default](tokens_helper(_visitor, &it.span))),
+        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &it.span))),
+        impl_token: Token![impl ](tokens_helper(_visitor, &_i.impl_token.span)),
         generics: _visitor.fold_generics(_i.generics),
         trait_: (_i.trait_).map(|it| {
             (
-                ((it).0).map(|it| Token![!](tokens_helper(_visitor, &(it).0))),
+                ((it).0).map(|it| Token![!](tokens_helper(_visitor, &it.spans))),
                 _visitor.fold_path((it).1),
-                Token ! [ for ](tokens_helper(_visitor, &((it).2).0)),
+                Token ! [ for ](tokens_helper(_visitor, &(it).2.span)),
             )
         }),
         self_ty: Box::new(_visitor.fold_type(*_i.self_ty)),
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         items: FoldHelper::lift(_i.items, |it| _visitor.fold_impl_item(it)),
     }
 }
@@ -2018,7 +2113,7 @@
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         ident: (_i.ident).map(|it| _visitor.fold_ident(it)),
         mac: _visitor.fold_macro(_i.mac),
-        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &(it).0))),
+        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "full")]
@@ -2026,11 +2121,11 @@
     ItemMacro2 {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        macro_token: Token ! [ macro ](tokens_helper(_visitor, &(_i.macro_token).0)),
+        macro_token: Token ! [ macro ](tokens_helper(_visitor, &_i.macro_token.span)),
         ident: _visitor.fold_ident(_i.ident),
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         args: _i.args,
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         body: _i.body,
     }
 }
@@ -2039,15 +2134,15 @@
     ItemMod {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        mod_token: Token ! [ mod ](tokens_helper(_visitor, &(_i.mod_token).0)),
+        mod_token: Token ! [ mod ](tokens_helper(_visitor, &_i.mod_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         content: (_i.content).map(|it| {
             (
-                Brace(tokens_helper(_visitor, &((it).0).0)),
+                Brace(tokens_helper(_visitor, &(it).0.span)),
                 FoldHelper::lift((it).1, |it| _visitor.fold_item(it)),
             )
         }),
-        semi: (_i.semi).map(|it| Token ! [ ; ](tokens_helper(_visitor, &(it).0))),
+        semi: (_i.semi).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "full")]
@@ -2055,14 +2150,14 @@
     ItemStatic {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        static_token: Token ! [ static ](tokens_helper(_visitor, &(_i.static_token).0)),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
+        static_token: Token ! [ static ](tokens_helper(_visitor, &_i.static_token.span)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
         ident: _visitor.fold_ident(_i.ident),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: Box::new(_visitor.fold_type(*_i.ty)),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         expr: Box::new(_visitor.fold_expr(*_i.expr)),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -2070,11 +2165,11 @@
     ItemStruct {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        struct_token: Token ! [ struct ](tokens_helper(_visitor, &(_i.struct_token).0)),
+        struct_token: Token ! [ struct ](tokens_helper(_visitor, &_i.struct_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         generics: _visitor.fold_generics(_i.generics),
         fields: _visitor.fold_fields(_i.fields),
-        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &(it).0))),
+        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "full")]
@@ -2082,28 +2177,44 @@
     ItemTrait {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &(it).0))),
-        auto_token: (_i.auto_token).map(|it| Token![auto](tokens_helper(_visitor, &(it).0))),
-        trait_token: Token ! [ trait ](tokens_helper(_visitor, &(_i.trait_token).0)),
+        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &it.span))),
+        auto_token: (_i.auto_token).map(|it| Token![auto](tokens_helper(_visitor, &it.span))),
+        trait_token: Token ! [ trait ](tokens_helper(_visitor, &_i.trait_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         generics: _visitor.fold_generics(_i.generics),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
         supertraits: FoldHelper::lift(_i.supertraits, |it| _visitor.fold_type_param_bound(it)),
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         items: FoldHelper::lift(_i.items, |it| _visitor.fold_trait_item(it)),
     }
 }
 #[cfg(feature = "full")]
+pub fn fold_item_trait_alias<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ItemTraitAlias,
+) -> ItemTraitAlias {
+    ItemTraitAlias {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        vis: _visitor.fold_visibility(_i.vis),
+        trait_token: Token ! [ trait ](tokens_helper(_visitor, &_i.trait_token.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        generics: _visitor.fold_generics(_i.generics),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
+        bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
 pub fn fold_item_type<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemType) -> ItemType {
     ItemType {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        type_token: Token ! [ type ](tokens_helper(_visitor, &(_i.type_token).0)),
+        type_token: Token ! [ type ](tokens_helper(_visitor, &_i.type_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         generics: _visitor.fold_generics(_i.generics),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         ty: Box::new(_visitor.fold_type(*_i.ty)),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -2111,7 +2222,7 @@
     ItemUnion {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        union_token: Token![union](tokens_helper(_visitor, &(_i.union_token).0)),
+        union_token: Token![union](tokens_helper(_visitor, &_i.union_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         generics: _visitor.fold_generics(_i.generics),
         fields: _visitor.fold_fields_named(_i.fields),
@@ -2122,11 +2233,11 @@
     ItemUse {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         vis: _visitor.fold_visibility(_i.vis),
-        use_token: Token ! [ use ](tokens_helper(_visitor, &(_i.use_token).0)),
+        use_token: Token ! [ use ](tokens_helper(_visitor, &_i.use_token.span)),
         leading_colon: (_i.leading_colon)
-            .map(|it| Token ! [ :: ](tokens_helper(_visitor, &(it).0))),
+            .map(|it| Token ! [ :: ](tokens_helper(_visitor, &it.spans))),
         tree: _visitor.fold_use_tree(_i.tree),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -2138,13 +2249,12 @@
 pub fn fold_label<V: Fold + ?Sized>(_visitor: &mut V, _i: Label) -> Label {
     Label {
         name: _visitor.fold_lifetime(_i.name),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
     }
 }
-#[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_lifetime<V: Fold + ?Sized>(_visitor: &mut V, _i: Lifetime) -> Lifetime {
     Lifetime {
-        apostrophe: _i.apostrophe,
+        apostrophe: _visitor.fold_span(_i.apostrophe),
         ident: _visitor.fold_ident(_i.ident),
     }
 }
@@ -2153,7 +2263,7 @@
     LifetimeDef {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         lifetime: _visitor.fold_lifetime(_i.lifetime),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
         bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_lifetime(it)),
     }
 }
@@ -2186,28 +2296,28 @@
 pub fn fold_local<V: Fold + ?Sized>(_visitor: &mut V, _i: Local) -> Local {
     Local {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        let_token: Token ! [ let ](tokens_helper(_visitor, &(_i.let_token).0)),
+        let_token: Token ! [ let ](tokens_helper(_visitor, &_i.let_token.span)),
         pats: FoldHelper::lift(_i.pats, |it| _visitor.fold_pat(it)),
         ty: (_i.ty).map(|it| {
             (
-                Token ! [ : ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ : ](tokens_helper(_visitor, &(it).0.spans)),
                 Box::new(_visitor.fold_type(*(it).1)),
             )
         }),
         init: (_i.init).map(|it| {
             (
-                Token ! [ = ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ = ](tokens_helper(_visitor, &(it).0.spans)),
                 Box::new(_visitor.fold_expr(*(it).1)),
             )
         }),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_macro<V: Fold + ?Sized>(_visitor: &mut V, _i: Macro) -> Macro {
     Macro {
         path: _visitor.fold_path(_i.path),
-        bang_token: Token![!](tokens_helper(_visitor, &(_i.bang_token).0)),
+        bang_token: Token![!](tokens_helper(_visitor, &_i.bang_token.spans)),
         delimiter: _visitor.fold_macro_delimiter(_i.delimiter),
         tts: _i.tts,
     }
@@ -2219,13 +2329,13 @@
 ) -> MacroDelimiter {
     match _i {
         MacroDelimiter::Paren(_binding_0) => {
-            MacroDelimiter::Paren(Paren(tokens_helper(_visitor, &(_binding_0).0)))
+            MacroDelimiter::Paren(Paren(tokens_helper(_visitor, &_binding_0.span)))
         }
         MacroDelimiter::Brace(_binding_0) => {
-            MacroDelimiter::Brace(Brace(tokens_helper(_visitor, &(_binding_0).0)))
+            MacroDelimiter::Brace(Brace(tokens_helper(_visitor, &_binding_0.span)))
         }
         MacroDelimiter::Bracket(_binding_0) => {
-            MacroDelimiter::Bracket(Bracket(tokens_helper(_visitor, &(_binding_0).0)))
+            MacroDelimiter::Bracket(Bracket(tokens_helper(_visitor, &_binding_0.span)))
         }
     }
 }
@@ -2248,7 +2358,7 @@
 pub fn fold_meta_list<V: Fold + ?Sized>(_visitor: &mut V, _i: MetaList) -> MetaList {
     MetaList {
         ident: _visitor.fold_ident(_i.ident),
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         nested: FoldHelper::lift(_i.nested, |it| _visitor.fold_nested_meta(it)),
     }
 }
@@ -2259,15 +2369,16 @@
 ) -> MetaNameValue {
     MetaNameValue {
         ident: _visitor.fold_ident(_i.ident),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         lit: _visitor.fold_lit(_i.lit),
     }
 }
 #[cfg(feature = "full")]
 pub fn fold_method_sig<V: Fold + ?Sized>(_visitor: &mut V, _i: MethodSig) -> MethodSig {
     MethodSig {
-        constness: (_i.constness).map(|it| Token ! [ const ](tokens_helper(_visitor, &(it).0))),
-        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &(it).0))),
+        constness: (_i.constness).map(|it| Token ! [ const ](tokens_helper(_visitor, &it.span))),
+        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &it.span))),
+        asyncness: (_i.asyncness).map(|it| Token![async](tokens_helper(_visitor, &it.span))),
         abi: (_i.abi).map(|it| _visitor.fold_abi(it)),
         ident: _visitor.fold_ident(_i.ident),
         decl: _visitor.fold_fn_decl(_i.decl),
@@ -2280,10 +2391,10 @@
     _i: MethodTurbofish,
 ) -> MethodTurbofish {
     MethodTurbofish {
-        colon2_token: Token ! [ :: ](tokens_helper(_visitor, &(_i.colon2_token).0)),
-        lt_token: Token ! [ < ](tokens_helper(_visitor, &(_i.lt_token).0)),
+        colon2_token: Token ! [ :: ](tokens_helper(_visitor, &_i.colon2_token.spans)),
+        lt_token: Token ! [ < ](tokens_helper(_visitor, &_i.lt_token.spans)),
         args: FoldHelper::lift(_i.args, |it| _visitor.fold_generic_method_argument(it)),
-        gt_token: Token ! [ > ](tokens_helper(_visitor, &(_i.gt_token).0)),
+        gt_token: Token ! [ > ](tokens_helper(_visitor, &_i.gt_token.spans)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2299,7 +2410,7 @@
     _i: ParenthesizedGenericArguments,
 ) -> ParenthesizedGenericArguments {
     ParenthesizedGenericArguments {
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         inputs: FoldHelper::lift(_i.inputs, |it| _visitor.fold_type(it)),
         output: _visitor.fold_return_type(_i.output),
     }
@@ -2329,7 +2440,7 @@
 #[cfg(feature = "full")]
 pub fn fold_pat_box<V: Fold + ?Sized>(_visitor: &mut V, _i: PatBox) -> PatBox {
     PatBox {
-        box_token: Token ! [ box ](tokens_helper(_visitor, &(_i.box_token).0)),
+        box_token: Token ! [ box ](tokens_helper(_visitor, &_i.box_token.span)),
         pat: Box::new(_visitor.fold_pat(*_i.pat)),
     }
 }
@@ -2337,12 +2448,12 @@
 #[cfg(feature = "full")]
 pub fn fold_pat_ident<V: Fold + ?Sized>(_visitor: &mut V, _i: PatIdent) -> PatIdent {
     PatIdent {
-        by_ref: (_i.by_ref).map(|it| Token ! [ ref ](tokens_helper(_visitor, &(it).0))),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
+        by_ref: (_i.by_ref).map(|it| Token ! [ ref ](tokens_helper(_visitor, &it.span))),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
         ident: _visitor.fold_ident(_i.ident),
         subpat: (_i.subpat).map(|it| {
             (
-                Token ! [ @ ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ @ ](tokens_helper(_visitor, &(it).0.spans)),
                 Box::new(_visitor.fold_pat(*(it).1)),
             )
         }),
@@ -2383,8 +2494,8 @@
 #[cfg(feature = "full")]
 pub fn fold_pat_ref<V: Fold + ?Sized>(_visitor: &mut V, _i: PatRef) -> PatRef {
     PatRef {
-        and_token: Token ! [ & ](tokens_helper(_visitor, &(_i.and_token).0)),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
+        and_token: Token ! [ & ](tokens_helper(_visitor, &_i.and_token.spans)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
         pat: Box::new(_visitor.fold_pat(*_i.pat)),
     }
 }
@@ -2392,11 +2503,11 @@
 #[cfg(feature = "full")]
 pub fn fold_pat_slice<V: Fold + ?Sized>(_visitor: &mut V, _i: PatSlice) -> PatSlice {
     PatSlice {
-        bracket_token: Bracket(tokens_helper(_visitor, &(_i.bracket_token).0)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
         front: FoldHelper::lift(_i.front, |it| _visitor.fold_pat(it)),
         middle: (_i.middle).map(|it| Box::new(_visitor.fold_pat(*it))),
-        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &(it).0))),
-        comma_token: (_i.comma_token).map(|it| Token ! [ , ](tokens_helper(_visitor, &(it).0))),
+        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &it.spans))),
+        comma_token: (_i.comma_token).map(|it| Token ! [ , ](tokens_helper(_visitor, &it.spans))),
         back: FoldHelper::lift(_i.back, |it| _visitor.fold_pat(it)),
     }
 }
@@ -2405,19 +2516,19 @@
 pub fn fold_pat_struct<V: Fold + ?Sized>(_visitor: &mut V, _i: PatStruct) -> PatStruct {
     PatStruct {
         path: _visitor.fold_path(_i.path),
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         fields: FoldHelper::lift(_i.fields, |it| _visitor.fold_field_pat(it)),
-        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &(it).0))),
+        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn fold_pat_tuple<V: Fold + ?Sized>(_visitor: &mut V, _i: PatTuple) -> PatTuple {
     PatTuple {
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         front: FoldHelper::lift(_i.front, |it| _visitor.fold_pat(it)),
-        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &(it).0))),
-        comma_token: (_i.comma_token).map(|it| Token ! [ , ](tokens_helper(_visitor, &(it).0))),
+        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &it.spans))),
+        comma_token: (_i.comma_token).map(|it| Token ! [ , ](tokens_helper(_visitor, &it.spans))),
         back: FoldHelper::lift(_i.back, |it| _visitor.fold_pat(it)),
     }
 }
@@ -2441,14 +2552,14 @@
 #[cfg(feature = "full")]
 pub fn fold_pat_wild<V: Fold + ?Sized>(_visitor: &mut V, _i: PatWild) -> PatWild {
     PatWild {
-        underscore_token: Token![_](tokens_helper(_visitor, &(_i.underscore_token).0)),
+        underscore_token: Token![_](tokens_helper(_visitor, &_i.underscore_token.spans)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_path<V: Fold + ?Sized>(_visitor: &mut V, _i: Path) -> Path {
     Path {
         leading_colon: (_i.leading_colon)
-            .map(|it| Token ! [ :: ](tokens_helper(_visitor, &(it).0))),
+            .map(|it| Token ! [ :: ](tokens_helper(_visitor, &it.spans))),
         segments: FoldHelper::lift(_i.segments, |it| _visitor.fold_path_segment(it)),
     }
 }
@@ -2475,7 +2586,7 @@
 pub fn fold_predicate_eq<V: Fold + ?Sized>(_visitor: &mut V, _i: PredicateEq) -> PredicateEq {
     PredicateEq {
         lhs_ty: _visitor.fold_type(_i.lhs_ty),
-        eq_token: Token ! [ = ](tokens_helper(_visitor, &(_i.eq_token).0)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
         rhs_ty: _visitor.fold_type(_i.rhs_ty),
     }
 }
@@ -2486,7 +2597,7 @@
 ) -> PredicateLifetime {
     PredicateLifetime {
         lifetime: _visitor.fold_lifetime(_i.lifetime),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_lifetime(it)),
     }
 }
@@ -2495,18 +2606,18 @@
     PredicateType {
         lifetimes: (_i.lifetimes).map(|it| _visitor.fold_bound_lifetimes(it)),
         bounded_ty: _visitor.fold_type(_i.bounded_ty),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_qself<V: Fold + ?Sized>(_visitor: &mut V, _i: QSelf) -> QSelf {
     QSelf {
-        lt_token: Token ! [ < ](tokens_helper(_visitor, &(_i.lt_token).0)),
+        lt_token: Token ! [ < ](tokens_helper(_visitor, &_i.lt_token.spans)),
         ty: Box::new(_visitor.fold_type(*_i.ty)),
         position: _i.position,
-        as_token: (_i.as_token).map(|it| Token ! [ as ](tokens_helper(_visitor, &(it).0))),
-        gt_token: Token ! [ > ](tokens_helper(_visitor, &(_i.gt_token).0)),
+        as_token: (_i.as_token).map(|it| Token ! [ as ](tokens_helper(_visitor, &it.span))),
+        gt_token: Token ! [ > ](tokens_helper(_visitor, &_i.gt_token.spans)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2514,10 +2625,10 @@
 pub fn fold_range_limits<V: Fold + ?Sized>(_visitor: &mut V, _i: RangeLimits) -> RangeLimits {
     match _i {
         RangeLimits::HalfOpen(_binding_0) => {
-            RangeLimits::HalfOpen(Token![..](tokens_helper(_visitor, &(_binding_0).0)))
+            RangeLimits::HalfOpen(Token![..](tokens_helper(_visitor, &_binding_0.spans)))
         }
         RangeLimits::Closed(_binding_0) => {
-            RangeLimits::Closed(Token ! [ ..= ](tokens_helper(_visitor, &(_binding_0).0)))
+            RangeLimits::Closed(Token ! [ ..= ](tokens_helper(_visitor, &_binding_0.spans)))
         }
     }
 }
@@ -2526,7 +2637,7 @@
     match _i {
         ReturnType::Default => ReturnType::Default,
         ReturnType::Type(_binding_0, _binding_1) => ReturnType::Type(
-            Token ! [ -> ](tokens_helper(_visitor, &(_binding_0).0)),
+            Token ! [ -> ](tokens_helper(_visitor, &_binding_0.spans)),
             Box::new(_visitor.fold_type(*_binding_1)),
         ),
     }
@@ -2543,14 +2654,14 @@
         Stmt::Expr(_binding_0) => Stmt::Expr(_visitor.fold_expr(_binding_0)),
         Stmt::Semi(_binding_0, _binding_1) => Stmt::Semi(
             _visitor.fold_expr(_binding_0),
-            Token ! [ ; ](tokens_helper(_visitor, &(_binding_1).0)),
+            Token ! [ ; ](tokens_helper(_visitor, &_binding_1.spans)),
         ),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_trait_bound<V: Fold + ?Sized>(_visitor: &mut V, _i: TraitBound) -> TraitBound {
     TraitBound {
-        paren_token: (_i.paren_token).map(|it| Paren(tokens_helper(_visitor, &(it).0))),
+        paren_token: (_i.paren_token).map(|it| Paren(tokens_helper(_visitor, &it.span))),
         modifier: _visitor.fold_trait_bound_modifier(_i.modifier),
         lifetimes: (_i.lifetimes).map(|it| _visitor.fold_bound_lifetimes(it)),
         path: _visitor.fold_path(_i.path),
@@ -2564,7 +2675,7 @@
     match _i {
         TraitBoundModifier::None => TraitBoundModifier::None,
         TraitBoundModifier::Maybe(_binding_0) => {
-            TraitBoundModifier::Maybe(Token ! [ ? ](tokens_helper(_visitor, &(_binding_0).0)))
+            TraitBoundModifier::Maybe(Token ! [ ? ](tokens_helper(_visitor, &_binding_0.spans)))
         }
     }
 }
@@ -2593,17 +2704,17 @@
 ) -> TraitItemConst {
     TraitItemConst {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        const_token: Token ! [ const ](tokens_helper(_visitor, &(_i.const_token).0)),
+        const_token: Token ! [ const ](tokens_helper(_visitor, &_i.const_token.span)),
         ident: _visitor.fold_ident(_i.ident),
-        colon_token: Token ! [ : ](tokens_helper(_visitor, &(_i.colon_token).0)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
         ty: _visitor.fold_type(_i.ty),
         default: (_i.default).map(|it| {
             (
-                Token ! [ = ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ = ](tokens_helper(_visitor, &(it).0.spans)),
                 _visitor.fold_expr((it).1),
             )
         }),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -2614,7 +2725,7 @@
     TraitItemMacro {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         mac: _visitor.fold_macro(_i.mac),
-        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &(it).0))),
+        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "full")]
@@ -2626,7 +2737,7 @@
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         sig: _visitor.fold_method_sig(_i.sig),
         default: (_i.default).map(|it| _visitor.fold_block(it)),
-        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &(it).0))),
+        semi_token: (_i.semi_token).map(|it| Token ! [ ; ](tokens_helper(_visitor, &it.spans))),
     }
 }
 #[cfg(feature = "full")]
@@ -2636,18 +2747,18 @@
 ) -> TraitItemType {
     TraitItemType {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
-        type_token: Token ! [ type ](tokens_helper(_visitor, &(_i.type_token).0)),
+        type_token: Token ! [ type ](tokens_helper(_visitor, &_i.type_token.span)),
         ident: _visitor.fold_ident(_i.ident),
         generics: _visitor.fold_generics(_i.generics),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
         bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
         default: (_i.default).map(|it| {
             (
-                Token ! [ = ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ = ](tokens_helper(_visitor, &(it).0.spans)),
                 _visitor.fold_type((it).1),
             )
         }),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
     }
 }
 #[cfg(feature = "full")]
@@ -2682,29 +2793,29 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_array<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeArray) -> TypeArray {
     TypeArray {
-        bracket_token: Bracket(tokens_helper(_visitor, &(_i.bracket_token).0)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
         elem: Box::new(_visitor.fold_type(*_i.elem)),
-        semi_token: Token ! [ ; ](tokens_helper(_visitor, &(_i.semi_token).0)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
         len: _visitor.fold_expr(_i.len),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_bare_fn<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeBareFn) -> TypeBareFn {
     TypeBareFn {
-        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &(it).0))),
-        abi: (_i.abi).map(|it| _visitor.fold_abi(it)),
-        fn_token: Token ! [ fn ](tokens_helper(_visitor, &(_i.fn_token).0)),
         lifetimes: (_i.lifetimes).map(|it| _visitor.fold_bound_lifetimes(it)),
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        unsafety: (_i.unsafety).map(|it| Token ! [ unsafe ](tokens_helper(_visitor, &it.span))),
+        abi: (_i.abi).map(|it| _visitor.fold_abi(it)),
+        fn_token: Token ! [ fn ](tokens_helper(_visitor, &_i.fn_token.span)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         inputs: FoldHelper::lift(_i.inputs, |it| _visitor.fold_bare_fn_arg(it)),
-        variadic: (_i.variadic).map(|it| Token ! [ ... ](tokens_helper(_visitor, &(it).0))),
+        variadic: (_i.variadic).map(|it| Token ! [ ... ](tokens_helper(_visitor, &it.spans))),
         output: _visitor.fold_return_type(_i.output),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_group<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeGroup) -> TypeGroup {
     TypeGroup {
-        group_token: Group(tokens_helper(_visitor, &(_i.group_token).0)),
+        group_token: Group(tokens_helper(_visitor, &_i.group_token.span)),
         elem: Box::new(_visitor.fold_type(*_i.elem)),
     }
 }
@@ -2714,14 +2825,14 @@
     _i: TypeImplTrait,
 ) -> TypeImplTrait {
     TypeImplTrait {
-        impl_token: Token![impl ](tokens_helper(_visitor, &(_i.impl_token).0)),
+        impl_token: Token![impl ](tokens_helper(_visitor, &_i.impl_token.span)),
         bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_infer<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeInfer) -> TypeInfer {
     TypeInfer {
-        underscore_token: Token![_](tokens_helper(_visitor, &(_i.underscore_token).0)),
+        underscore_token: Token![_](tokens_helper(_visitor, &_i.underscore_token.spans)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2733,7 +2844,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_never<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeNever) -> TypeNever {
     TypeNever {
-        bang_token: Token![!](tokens_helper(_visitor, &(_i.bang_token).0)),
+        bang_token: Token![!](tokens_helper(_visitor, &_i.bang_token.spans)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2741,9 +2852,9 @@
     TypeParam {
         attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
         ident: _visitor.fold_ident(_i.ident),
-        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &(it).0))),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
         bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
-        eq_token: (_i.eq_token).map(|it| Token ! [ = ](tokens_helper(_visitor, &(it).0))),
+        eq_token: (_i.eq_token).map(|it| Token ! [ = ](tokens_helper(_visitor, &it.spans))),
         default: (_i.default).map(|it| _visitor.fold_type(it)),
     }
 }
@@ -2764,7 +2875,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_paren<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeParen) -> TypeParen {
     TypeParen {
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         elem: Box::new(_visitor.fold_type(*_i.elem)),
     }
 }
@@ -2778,25 +2889,26 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_ptr<V: Fold + ?Sized>(_visitor: &mut V, _i: TypePtr) -> TypePtr {
     TypePtr {
-        star_token: Token ! [ * ](tokens_helper(_visitor, &(_i.star_token).0)),
-        const_token: (_i.const_token).map(|it| Token ! [ const ](tokens_helper(_visitor, &(it).0))),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
+        star_token: Token ! [ * ](tokens_helper(_visitor, &_i.star_token.spans)),
+        const_token: (_i.const_token)
+            .map(|it| Token ! [ const ](tokens_helper(_visitor, &it.span))),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
         elem: Box::new(_visitor.fold_type(*_i.elem)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_reference<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeReference) -> TypeReference {
     TypeReference {
-        and_token: Token ! [ & ](tokens_helper(_visitor, &(_i.and_token).0)),
+        and_token: Token ! [ & ](tokens_helper(_visitor, &_i.and_token.spans)),
         lifetime: (_i.lifetime).map(|it| _visitor.fold_lifetime(it)),
-        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &(it).0))),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
         elem: Box::new(_visitor.fold_type(*_i.elem)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_slice<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeSlice) -> TypeSlice {
     TypeSlice {
-        bracket_token: Bracket(tokens_helper(_visitor, &(_i.bracket_token).0)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
         elem: Box::new(_visitor.fold_type(*_i.elem)),
     }
 }
@@ -2806,14 +2918,14 @@
     _i: TypeTraitObject,
 ) -> TypeTraitObject {
     TypeTraitObject {
-        dyn_token: (_i.dyn_token).map(|it| Token![dyn](tokens_helper(_visitor, &(it).0))),
+        dyn_token: (_i.dyn_token).map(|it| Token![dyn](tokens_helper(_visitor, &it.span))),
         bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_type_param_bound(it)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_type_tuple<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeTuple) -> TypeTuple {
     TypeTuple {
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
         elems: FoldHelper::lift(_i.elems, |it| _visitor.fold_type(it)),
     }
 }
@@ -2825,22 +2937,24 @@
 pub fn fold_un_op<V: Fold + ?Sized>(_visitor: &mut V, _i: UnOp) -> UnOp {
     match _i {
         UnOp::Deref(_binding_0) => {
-            UnOp::Deref(Token ! [ * ](tokens_helper(_visitor, &(_binding_0).0)))
+            UnOp::Deref(Token ! [ * ](tokens_helper(_visitor, &_binding_0.spans)))
         }
-        UnOp::Not(_binding_0) => UnOp::Not(Token![!](tokens_helper(_visitor, &(_binding_0).0))),
-        UnOp::Neg(_binding_0) => UnOp::Neg(Token ! [ - ](tokens_helper(_visitor, &(_binding_0).0))),
+        UnOp::Not(_binding_0) => UnOp::Not(Token![!](tokens_helper(_visitor, &_binding_0.spans))),
+        UnOp::Neg(_binding_0) => {
+            UnOp::Neg(Token ! [ - ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
     }
 }
 #[cfg(feature = "full")]
 pub fn fold_use_glob<V: Fold + ?Sized>(_visitor: &mut V, _i: UseGlob) -> UseGlob {
     UseGlob {
-        star_token: Token ! [ * ](tokens_helper(_visitor, &(_i.star_token).0)),
+        star_token: Token ! [ * ](tokens_helper(_visitor, &_i.star_token.spans)),
     }
 }
 #[cfg(feature = "full")]
 pub fn fold_use_group<V: Fold + ?Sized>(_visitor: &mut V, _i: UseGroup) -> UseGroup {
     UseGroup {
-        brace_token: Brace(tokens_helper(_visitor, &(_i.brace_token).0)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
         items: FoldHelper::lift(_i.items, |it| _visitor.fold_use_tree(it)),
     }
 }
@@ -2854,7 +2968,7 @@
 pub fn fold_use_path<V: Fold + ?Sized>(_visitor: &mut V, _i: UsePath) -> UsePath {
     UsePath {
         ident: _visitor.fold_ident(_i.ident),
-        colon2_token: Token ! [ :: ](tokens_helper(_visitor, &(_i.colon2_token).0)),
+        colon2_token: Token ! [ :: ](tokens_helper(_visitor, &_i.colon2_token.spans)),
         tree: Box::new(_visitor.fold_use_tree(*_i.tree)),
     }
 }
@@ -2862,7 +2976,7 @@
 pub fn fold_use_rename<V: Fold + ?Sized>(_visitor: &mut V, _i: UseRename) -> UseRename {
     UseRename {
         ident: _visitor.fold_ident(_i.ident),
-        as_token: Token ! [ as ](tokens_helper(_visitor, &(_i.as_token).0)),
+        as_token: Token ! [ as ](tokens_helper(_visitor, &_i.as_token.span)),
         rename: _visitor.fold_ident(_i.rename),
     }
 }
@@ -2884,7 +2998,7 @@
         fields: _visitor.fold_fields(_i.fields),
         discriminant: (_i.discriminant).map(|it| {
             (
-                Token ! [ = ](tokens_helper(_visitor, &((it).0).0)),
+                Token ! [ = ](tokens_helper(_visitor, &(it).0.spans)),
                 _visitor.fold_expr((it).1),
             )
         }),
@@ -2893,21 +3007,21 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_vis_crate<V: Fold + ?Sized>(_visitor: &mut V, _i: VisCrate) -> VisCrate {
     VisCrate {
-        crate_token: Token![crate](tokens_helper(_visitor, &(_i.crate_token).0)),
+        crate_token: Token![crate](tokens_helper(_visitor, &_i.crate_token.span)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_vis_public<V: Fold + ?Sized>(_visitor: &mut V, _i: VisPublic) -> VisPublic {
     VisPublic {
-        pub_token: Token ! [ pub ](tokens_helper(_visitor, &(_i.pub_token).0)),
+        pub_token: Token ! [ pub ](tokens_helper(_visitor, &_i.pub_token.span)),
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_vis_restricted<V: Fold + ?Sized>(_visitor: &mut V, _i: VisRestricted) -> VisRestricted {
     VisRestricted {
-        pub_token: Token ! [ pub ](tokens_helper(_visitor, &(_i.pub_token).0)),
-        paren_token: Paren(tokens_helper(_visitor, &(_i.paren_token).0)),
-        in_token: (_i.in_token).map(|it| Token ! [ in ](tokens_helper(_visitor, &(it).0))),
+        pub_token: Token ! [ pub ](tokens_helper(_visitor, &_i.pub_token.span)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
+        in_token: (_i.in_token).map(|it| Token ! [ in ](tokens_helper(_visitor, &it.span))),
         path: Box::new(_visitor.fold_path(*_i.path)),
     }
 }
@@ -2925,7 +3039,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn fold_where_clause<V: Fold + ?Sized>(_visitor: &mut V, _i: WhereClause) -> WhereClause {
     WhereClause {
-        where_token: Token ! [ where ](tokens_helper(_visitor, &(_i.where_token).0)),
+        where_token: Token ! [ where ](tokens_helper(_visitor, &_i.where_token.span)),
         predicates: FoldHelper::lift(_i.predicates, |it| _visitor.fold_where_predicate(it)),
     }
 }
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index d501ac6..7ef88fd 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -132,6 +132,11 @@
     fn visit_expr_assign_op(&mut self, i: &'ast ExprAssignOp) {
         visit_expr_assign_op(self, i)
     }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_async(&mut self, i: &'ast ExprAsync) {
+        visit_expr_async(self, i)
+    }
     #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_expr_binary(&mut self, i: &'ast ExprBinary) {
         visit_expr_binary(self, i)
@@ -161,11 +166,6 @@
     }
     #[cfg(feature = "full")]
     #[cfg(any(feature = "full", feature = "derive"))]
-    fn visit_expr_catch(&mut self, i: &'ast ExprCatch) {
-        visit_expr_catch(self, i)
-    }
-    #[cfg(feature = "full")]
-    #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_expr_closure(&mut self, i: &'ast ExprClosure) {
         visit_expr_closure(self, i)
     }
@@ -271,6 +271,11 @@
     }
     #[cfg(feature = "full")]
     #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_try_block(&mut self, i: &'ast ExprTryBlock) {
+        visit_expr_try_block(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_expr_tuple(&mut self, i: &'ast ExprTuple) {
         visit_expr_tuple(self, i)
     }
@@ -354,6 +359,10 @@
         visit_foreign_item_fn(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_foreign_item_macro(&mut self, i: &'ast ForeignItemMacro) {
+        visit_foreign_item_macro(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_foreign_item_static(&mut self, i: &'ast ForeignItemStatic) {
         visit_foreign_item_static(self, i)
     }
@@ -394,6 +403,10 @@
         visit_impl_item_const(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_impl_item_existential(&mut self, i: &'ast ImplItemExistential) {
+        visit_impl_item_existential(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_impl_item_macro(&mut self, i: &'ast ImplItemMacro) {
         visit_impl_item_macro(self, i)
     }
@@ -426,6 +439,10 @@
         visit_item_enum(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_item_existential(&mut self, i: &'ast ItemExistential) {
+        visit_item_existential(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_item_extern_crate(&mut self, i: &'ast ItemExternCrate) {
         visit_item_extern_crate(self, i)
     }
@@ -466,6 +483,10 @@
         visit_item_trait(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_item_trait_alias(&mut self, i: &'ast ItemTraitAlias) {
+        visit_item_trait_alias(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_item_type(&mut self, i: &'ast ItemType) {
         visit_item_type(self, i)
     }
@@ -486,7 +507,6 @@
     fn visit_label(&mut self, i: &'ast Label) {
         visit_label(self, i)
     }
-    #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_lifetime(&mut self, i: &'ast Lifetime) {
         visit_lifetime(self, i)
     }
@@ -854,7 +874,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_abi<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Abi) {
-    tokens_helper(_visitor, &(_i.extern_token).0);
+    tokens_helper(_visitor, &_i.extern_token.span);
     if let Some(ref it) = _i.name {
         _visitor.visit_lit_str(it)
     };
@@ -865,38 +885,38 @@
     _i: &'ast AngleBracketedGenericArguments,
 ) {
     if let Some(ref it) = _i.colon2_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
-    tokens_helper(_visitor, &(_i.lt_token).0);
+    tokens_helper(_visitor, &_i.lt_token.spans);
     for el in Punctuated::pairs(&_i.args) {
         let it = el.value();
         _visitor.visit_generic_argument(it)
     }
-    tokens_helper(_visitor, &(_i.gt_token).0);
+    tokens_helper(_visitor, &_i.gt_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_arg_captured<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ArgCaptured) {
     _visitor.visit_pat(&_i.pat);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&_i.ty);
 }
 #[cfg(feature = "full")]
 pub fn visit_arg_self<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ArgSelf) {
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.self_token).0);
+    tokens_helper(_visitor, &_i.self_token.span);
 }
 #[cfg(feature = "full")]
 pub fn visit_arg_self_ref<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ArgSelfRef) {
-    tokens_helper(_visitor, &(_i.and_token).0);
+    tokens_helper(_visitor, &_i.and_token.spans);
     if let Some(ref it) = _i.lifetime {
         _visitor.visit_lifetime(it)
     };
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.self_token).0);
+    tokens_helper(_visitor, &_i.self_token.span);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
@@ -905,20 +925,20 @@
         _visitor.visit_attribute(it)
     }
     if let Some(ref it) = _i.leading_vert {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.pats) {
         let it = el.value();
         _visitor.visit_pat(it)
     }
     if let Some(ref it) = _i.guard {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.span);
         _visitor.visit_expr(&*(it).1);
     };
-    tokens_helper(_visitor, &(_i.fat_arrow_token).0);
+    tokens_helper(_visitor, &_i.fat_arrow_token.spans);
     _visitor.visit_expr(&*_i.body);
     if let Some(ref it) = _i.comma {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -926,24 +946,23 @@
     match *_i {
         AttrStyle::Outer => {}
         AttrStyle::Inner(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_attribute<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Attribute) {
-    tokens_helper(_visitor, &(_i.pound_token).0);
+    tokens_helper(_visitor, &_i.pound_token.spans);
     _visitor.visit_attr_style(&_i.style);
-    tokens_helper(_visitor, &(_i.bracket_token).0);
+    tokens_helper(_visitor, &_i.bracket_token.span);
     _visitor.visit_path(&_i.path);
     skip!(_i.tts);
-    skip!(_i.is_sugared_doc);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_bare_fn_arg<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast BareFnArg) {
     if let Some(ref it) = _i.name {
         _visitor.visit_bare_fn_arg_name(&(it).0);
-        tokens_helper(_visitor, &((it).1).0);
+        tokens_helper(_visitor, &(it).1.spans);
     };
     _visitor.visit_type(&_i.ty);
 }
@@ -957,7 +976,7 @@
             _visitor.visit_ident(_binding_0);
         }
         BareFnArgName::Wild(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
     }
 }
@@ -965,101 +984,101 @@
 pub fn visit_bin_op<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast BinOp) {
     match *_i {
         BinOp::Add(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Sub(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Mul(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Div(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Rem(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::And(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Or(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::BitXor(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::BitAnd(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::BitOr(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Shl(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Shr(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Eq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Lt(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Le(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Ne(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Ge(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::Gt(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::AddEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::SubEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::MulEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::DivEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::RemEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::BitXorEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::BitAndEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::BitOrEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::ShlEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         BinOp::ShrEq(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_binding<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Binding) {
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_type(&_i.ty);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_block<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Block) {
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for it in &_i.stmts {
         _visitor.visit_stmt(it)
     }
@@ -1069,25 +1088,25 @@
     _visitor: &mut V,
     _i: &'ast BoundLifetimes,
 ) {
-    tokens_helper(_visitor, &(_i.for_token).0);
-    tokens_helper(_visitor, &(_i.lt_token).0);
+    tokens_helper(_visitor, &_i.for_token.span);
+    tokens_helper(_visitor, &_i.lt_token.spans);
     for el in Punctuated::pairs(&_i.lifetimes) {
         let it = el.value();
         _visitor.visit_lifetime_def(it)
     }
-    tokens_helper(_visitor, &(_i.gt_token).0);
+    tokens_helper(_visitor, &_i.gt_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_const_param<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ConstParam) {
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.const_token).0);
+    tokens_helper(_visitor, &_i.const_token.span);
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&_i.ty);
     if let Some(ref it) = _i.eq_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     if let Some(ref it) = _i.default {
         _visitor.visit_expr(it)
@@ -1109,8 +1128,8 @@
 }
 #[cfg(feature = "derive")]
 pub fn visit_data_enum<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DataEnum) {
-    tokens_helper(_visitor, &(_i.enum_token).0);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.enum_token.span);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for el in Punctuated::pairs(&_i.variants) {
         let it = el.value();
         _visitor.visit_variant(it)
@@ -1118,15 +1137,15 @@
 }
 #[cfg(feature = "derive")]
 pub fn visit_data_struct<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DataStruct) {
-    tokens_helper(_visitor, &(_i.struct_token).0);
+    tokens_helper(_visitor, &_i.struct_token.span);
     _visitor.visit_fields(&_i.fields);
     if let Some(ref it) = _i.semi_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(feature = "derive")]
 pub fn visit_data_union<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DataUnion) {
-    tokens_helper(_visitor, &(_i.union_token).0);
+    tokens_helper(_visitor, &_i.union_token.span);
     _visitor.visit_fields_named(&_i.fields);
 }
 #[cfg(feature = "derive")]
@@ -1253,8 +1272,11 @@
         Expr::Try(ref _binding_0) => {
             full!(_visitor.visit_expr_try(_binding_0));
         }
-        Expr::Catch(ref _binding_0) => {
-            full!(_visitor.visit_expr_catch(_binding_0));
+        Expr::Async(ref _binding_0) => {
+            full!(_visitor.visit_expr_async(_binding_0));
+        }
+        Expr::TryBlock(ref _binding_0) => {
+            full!(_visitor.visit_expr_try_block(_binding_0));
         }
         Expr::Yield(ref _binding_0) => {
             full!(_visitor.visit_expr_yield(_binding_0));
@@ -1270,7 +1292,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.bracket_token).0);
+    tokens_helper(_visitor, &_i.bracket_token.span);
     for el in Punctuated::pairs(&_i.elems) {
         let it = el.value();
         _visitor.visit_expr(it)
@@ -1283,7 +1305,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.left);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_expr(&*_i.right);
 }
 #[cfg(feature = "full")]
@@ -1299,6 +1321,18 @@
     _visitor.visit_bin_op(&_i.op);
     _visitor.visit_expr(&*_i.right);
 }
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_async<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAsync) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.async_token.span);
+    if let Some(ref it) = _i.capture {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_block(&_i.block);
+}
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_expr_binary<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBinary) {
     for it in &_i.attrs {
@@ -1314,6 +1348,9 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
+    if let Some(ref it) = _i.label {
+        _visitor.visit_label(it)
+    };
     _visitor.visit_block(&_i.block);
 }
 #[cfg(feature = "full")]
@@ -1322,7 +1359,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.box_token).0);
+    tokens_helper(_visitor, &_i.box_token.span);
     _visitor.visit_expr(&*_i.expr);
 }
 #[cfg(feature = "full")]
@@ -1331,7 +1368,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.break_token).0);
+    tokens_helper(_visitor, &_i.break_token.span);
     if let Some(ref it) = _i.label {
         _visitor.visit_lifetime(it)
     };
@@ -1345,7 +1382,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.func);
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.args) {
         let it = el.value();
         _visitor.visit_expr(it)
@@ -1357,37 +1394,30 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.as_token).0);
+    tokens_helper(_visitor, &_i.as_token.span);
     _visitor.visit_type(&*_i.ty);
 }
 #[cfg(feature = "full")]
 #[cfg(any(feature = "full", feature = "derive"))]
-pub fn visit_expr_catch<'ast, V: Visit<'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")]
-#[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_expr_closure<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprClosure) {
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
+    if let Some(ref it) = _i.asyncness {
+        tokens_helper(_visitor, &it.span)
+    };
     if let Some(ref it) = _i.movability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.capture {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.or1_token).0);
+    tokens_helper(_visitor, &_i.or1_token.spans);
     for el in Punctuated::pairs(&_i.inputs) {
         let it = el.value();
         _visitor.visit_fn_arg(it)
     }
-    tokens_helper(_visitor, &(_i.or2_token).0);
+    tokens_helper(_visitor, &_i.or2_token.spans);
     _visitor.visit_return_type(&_i.output);
     _visitor.visit_expr(&*_i.body);
 }
@@ -1400,7 +1430,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.continue_token).0);
+    tokens_helper(_visitor, &_i.continue_token.span);
     if let Some(ref it) = _i.label {
         _visitor.visit_lifetime(it)
     };
@@ -1411,7 +1441,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.base);
-    tokens_helper(_visitor, &(_i.dot_token).0);
+    tokens_helper(_visitor, &_i.dot_token.spans);
     _visitor.visit_member(&_i.member);
 }
 #[cfg(feature = "full")]
@@ -1423,9 +1453,9 @@
     if let Some(ref it) = _i.label {
         _visitor.visit_label(it)
     };
-    tokens_helper(_visitor, &(_i.for_token).0);
+    tokens_helper(_visitor, &_i.for_token.span);
     _visitor.visit_pat(&*_i.pat);
-    tokens_helper(_visitor, &(_i.in_token).0);
+    tokens_helper(_visitor, &_i.in_token.span);
     _visitor.visit_expr(&*_i.expr);
     _visitor.visit_block(&_i.body);
 }
@@ -1435,7 +1465,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.group_token).0);
+    tokens_helper(_visitor, &_i.group_token.span);
     _visitor.visit_expr(&*_i.expr);
 }
 #[cfg(feature = "full")]
@@ -1444,11 +1474,11 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.if_token).0);
+    tokens_helper(_visitor, &_i.if_token.span);
     _visitor.visit_expr(&*_i.cond);
     _visitor.visit_block(&_i.then_branch);
     if let Some(ref it) = _i.else_branch {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.span);
         _visitor.visit_expr(&*(it).1);
     };
 }
@@ -1458,17 +1488,17 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.if_token).0);
-    tokens_helper(_visitor, &(_i.let_token).0);
+    tokens_helper(_visitor, &_i.if_token.span);
+    tokens_helper(_visitor, &_i.let_token.span);
     for el in Punctuated::pairs(&_i.pats) {
         let it = el.value();
         _visitor.visit_pat(it)
     }
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_expr(&*_i.expr);
     _visitor.visit_block(&_i.then_branch);
     if let Some(ref it) = _i.else_branch {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.span);
         _visitor.visit_expr(&*(it).1);
     };
 }
@@ -1479,7 +1509,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.place);
-    tokens_helper(_visitor, &(_i.arrow_token).0);
+    tokens_helper(_visitor, &_i.arrow_token.spans);
     _visitor.visit_expr(&*_i.value);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1488,7 +1518,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.bracket_token).0);
+    tokens_helper(_visitor, &_i.bracket_token.span);
     _visitor.visit_expr(&*_i.index);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1507,7 +1537,7 @@
     if let Some(ref it) = _i.label {
         _visitor.visit_label(it)
     };
-    tokens_helper(_visitor, &(_i.loop_token).0);
+    tokens_helper(_visitor, &_i.loop_token.span);
     _visitor.visit_block(&_i.body);
 }
 #[cfg(feature = "full")]
@@ -1524,9 +1554,9 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.match_token).0);
+    tokens_helper(_visitor, &_i.match_token.span);
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for it in &_i.arms {
         _visitor.visit_arm(it)
     }
@@ -1541,12 +1571,12 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.receiver);
-    tokens_helper(_visitor, &(_i.dot_token).0);
+    tokens_helper(_visitor, &_i.dot_token.spans);
     _visitor.visit_ident(&_i.method);
     if let Some(ref it) = _i.turbofish {
         _visitor.visit_method_turbofish(it)
     };
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.args) {
         let it = el.value();
         _visitor.visit_expr(it)
@@ -1557,7 +1587,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     _visitor.visit_expr(&*_i.expr);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1593,9 +1623,9 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.and_token).0);
+    tokens_helper(_visitor, &_i.and_token.spans);
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_expr(&*_i.expr);
 }
@@ -1605,9 +1635,9 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.bracket_token).0);
+    tokens_helper(_visitor, &_i.bracket_token.span);
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
     _visitor.visit_expr(&*_i.len);
 }
 #[cfg(feature = "full")]
@@ -1616,7 +1646,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.return_token).0);
+    tokens_helper(_visitor, &_i.return_token.span);
     if let Some(ref it) = _i.expr {
         _visitor.visit_expr(&**it)
     };
@@ -1628,13 +1658,13 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_path(&_i.path);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for el in Punctuated::pairs(&_i.fields) {
         let it = el.value();
         _visitor.visit_field_value(it)
     }
     if let Some(ref it) = _i.dot2_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     if let Some(ref it) = _i.rest {
         _visitor.visit_expr(&**it)
@@ -1647,7 +1677,19 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.question_token).0);
+    tokens_helper(_visitor, &_i.question_token.spans);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_try_block<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ExprTryBlock,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.try_token.span);
+    _visitor.visit_block(&_i.block);
 }
 #[cfg(feature = "full")]
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1655,7 +1697,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.elems) {
         let it = el.value();
         _visitor.visit_expr(it)
@@ -1668,7 +1710,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&*_i.ty);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1685,7 +1727,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.unsafe_token).0);
+    tokens_helper(_visitor, &_i.unsafe_token.span);
     _visitor.visit_block(&_i.block);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1704,7 +1746,7 @@
     if let Some(ref it) = _i.label {
         _visitor.visit_label(it)
     };
-    tokens_helper(_visitor, &(_i.while_token).0);
+    tokens_helper(_visitor, &_i.while_token.span);
     _visitor.visit_expr(&*_i.cond);
     _visitor.visit_block(&_i.body);
 }
@@ -1720,13 +1762,13 @@
     if let Some(ref it) = _i.label {
         _visitor.visit_label(it)
     };
-    tokens_helper(_visitor, &(_i.while_token).0);
-    tokens_helper(_visitor, &(_i.let_token).0);
+    tokens_helper(_visitor, &_i.while_token.span);
+    tokens_helper(_visitor, &_i.let_token.span);
     for el in Punctuated::pairs(&_i.pats) {
         let it = el.value();
         _visitor.visit_pat(it)
     }
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_expr(&*_i.expr);
     _visitor.visit_block(&_i.body);
 }
@@ -1736,7 +1778,7 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.yield_token).0);
+    tokens_helper(_visitor, &_i.yield_token.span);
     if let Some(ref it) = _i.expr {
         _visitor.visit_expr(&**it)
     };
@@ -1751,7 +1793,7 @@
         _visitor.visit_ident(it)
     };
     if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     _visitor.visit_type(&_i.ty);
 }
@@ -1763,7 +1805,7 @@
     }
     _visitor.visit_member(&_i.member);
     if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     _visitor.visit_pat(&*_i.pat);
 }
@@ -1775,7 +1817,7 @@
     }
     _visitor.visit_member(&_i.member);
     if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     _visitor.visit_expr(&_i.expr);
 }
@@ -1793,7 +1835,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_fields_named<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast FieldsNamed) {
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for el in Punctuated::pairs(&_i.named) {
         let it = el.value();
         _visitor.visit_field(it)
@@ -1804,7 +1846,7 @@
     _visitor: &mut V,
     _i: &'ast FieldsUnnamed,
 ) {
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.unnamed) {
         let it = el.value();
         _visitor.visit_field(it)
@@ -1842,15 +1884,15 @@
 }
 #[cfg(feature = "full")]
 pub fn visit_fn_decl<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast FnDecl) {
-    tokens_helper(_visitor, &(_i.fn_token).0);
+    tokens_helper(_visitor, &_i.fn_token.span);
     _visitor.visit_generics(&_i.generics);
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.inputs) {
         let it = el.value();
         _visitor.visit_fn_arg(it)
     }
     if let Some(ref it) = _i.variadic {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     _visitor.visit_return_type(&_i.output);
 }
@@ -1866,6 +1908,9 @@
         ForeignItem::Type(ref _binding_0) => {
             _visitor.visit_foreign_item_type(_binding_0);
         }
+        ForeignItem::Macro(ref _binding_0) => {
+            _visitor.visit_foreign_item_macro(_binding_0);
+        }
         ForeignItem::Verbatim(ref _binding_0) => {
             _visitor.visit_foreign_item_verbatim(_binding_0);
         }
@@ -1882,7 +1927,20 @@
     _visitor.visit_visibility(&_i.vis);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_fn_decl(&*_i.decl);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_macro<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ForeignItemMacro,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_macro(&_i.mac);
+    if let Some(ref it) = _i.semi_token {
+        tokens_helper(_visitor, &it.spans)
+    };
 }
 #[cfg(feature = "full")]
 pub fn visit_foreign_item_static<'ast, V: Visit<'ast> + ?Sized>(
@@ -1893,14 +1951,14 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.static_token).0);
+    tokens_helper(_visitor, &_i.static_token.span);
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&*_i.ty);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_foreign_item_type<'ast, V: Visit<'ast> + ?Sized>(
@@ -1911,9 +1969,9 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.type_token).0);
+    tokens_helper(_visitor, &_i.type_token.span);
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_foreign_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
@@ -1977,14 +2035,14 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_generics<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Generics) {
     if let Some(ref it) = _i.lt_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.params) {
         let it = el.value();
         _visitor.visit_generic_param(it)
     }
     if let Some(ref it) = _i.gt_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     if let Some(ref it) = _i.where_clause {
         _visitor.visit_where_clause(it)
@@ -2003,6 +2061,9 @@
         ImplItem::Type(ref _binding_0) => {
             _visitor.visit_impl_item_type(_binding_0);
         }
+        ImplItem::Existential(ref _binding_0) => {
+            _visitor.visit_impl_item_existential(_binding_0);
+        }
         ImplItem::Macro(ref _binding_0) => {
             _visitor.visit_impl_item_macro(_binding_0);
         }
@@ -2021,15 +2082,36 @@
     }
     _visitor.visit_visibility(&_i.vis);
     if let Some(ref it) = _i.defaultness {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.const_token).0);
+    tokens_helper(_visitor, &_i.const_token.span);
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&_i.ty);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_expr(&_i.expr);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_existential<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ImplItemExistential,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.existential_token.span);
+    tokens_helper(_visitor, &_i.type_token.span);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    if let Some(ref it) = _i.colon_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    for el in Punctuated::pairs(&_i.bounds) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_impl_item_macro<'ast, V: Visit<'ast> + ?Sized>(
@@ -2041,7 +2123,7 @@
     }
     _visitor.visit_macro(&_i.mac);
     if let Some(ref it) = _i.semi_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2054,7 +2136,7 @@
     }
     _visitor.visit_visibility(&_i.vis);
     if let Some(ref it) = _i.defaultness {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_method_sig(&_i.sig);
     _visitor.visit_block(&_i.block);
@@ -2069,14 +2151,14 @@
     }
     _visitor.visit_visibility(&_i.vis);
     if let Some(ref it) = _i.defaultness {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.type_token).0);
+    tokens_helper(_visitor, &_i.type_token.span);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_generics(&_i.generics);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_type(&_i.ty);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_impl_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
@@ -2117,6 +2199,9 @@
         Item::Type(ref _binding_0) => {
             _visitor.visit_item_type(_binding_0);
         }
+        Item::Existential(ref _binding_0) => {
+            _visitor.visit_item_existential(_binding_0);
+        }
         Item::Struct(ref _binding_0) => {
             _visitor.visit_item_struct(_binding_0);
         }
@@ -2129,6 +2214,9 @@
         Item::Trait(ref _binding_0) => {
             _visitor.visit_item_trait(_binding_0);
         }
+        Item::TraitAlias(ref _binding_0) => {
+            _visitor.visit_item_trait_alias(_binding_0);
+        }
         Item::Impl(ref _binding_0) => {
             _visitor.visit_item_impl(_binding_0);
         }
@@ -2149,13 +2237,13 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.const_token).0);
+    tokens_helper(_visitor, &_i.const_token.span);
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&*_i.ty);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_enum<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemEnum) {
@@ -2163,16 +2251,38 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.enum_token).0);
+    tokens_helper(_visitor, &_i.enum_token.span);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_generics(&_i.generics);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for el in Punctuated::pairs(&_i.variants) {
         let it = el.value();
         _visitor.visit_variant(it)
     }
 }
 #[cfg(feature = "full")]
+pub fn visit_item_existential<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ItemExistential,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.existential_token.span);
+    tokens_helper(_visitor, &_i.type_token.span);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    if let Some(ref it) = _i.colon_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    for el in Punctuated::pairs(&_i.bounds) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
 pub fn visit_item_extern_crate<'ast, V: Visit<'ast> + ?Sized>(
     _visitor: &mut V,
     _i: &'ast ItemExternCrate,
@@ -2181,14 +2291,14 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.extern_token).0);
-    tokens_helper(_visitor, &(_i.crate_token).0);
+    tokens_helper(_visitor, &_i.extern_token.span);
+    tokens_helper(_visitor, &_i.crate_token.span);
     _visitor.visit_ident(&_i.ident);
     if let Some(ref it) = _i.rename {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.span);
         _visitor.visit_ident(&(it).1);
     };
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_fn<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemFn) {
@@ -2197,10 +2307,13 @@
     }
     _visitor.visit_visibility(&_i.vis);
     if let Some(ref it) = _i.constness {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.unsafety {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
+    };
+    if let Some(ref it) = _i.asyncness {
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.abi {
         _visitor.visit_abi(it)
@@ -2218,7 +2331,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_abi(&_i.abi);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for it in &_i.items {
         _visitor.visit_foreign_item(it)
     }
@@ -2229,22 +2342,22 @@
         _visitor.visit_attribute(it)
     }
     if let Some(ref it) = _i.defaultness {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.unsafety {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.impl_token).0);
+    tokens_helper(_visitor, &_i.impl_token.span);
     _visitor.visit_generics(&_i.generics);
     if let Some(ref it) = _i.trait_ {
         if let Some(ref it) = (it).0 {
-            tokens_helper(_visitor, &(it).0)
+            tokens_helper(_visitor, &it.spans)
         };
         _visitor.visit_path(&(it).1);
-        tokens_helper(_visitor, &((it).2).0);
+        tokens_helper(_visitor, &(it).2.span);
     };
     _visitor.visit_type(&*_i.self_ty);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for it in &_i.items {
         _visitor.visit_impl_item(it)
     }
@@ -2259,7 +2372,7 @@
     };
     _visitor.visit_macro(&_i.mac);
     if let Some(ref it) = _i.semi_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2268,11 +2381,11 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.macro_token).0);
+    tokens_helper(_visitor, &_i.macro_token.span);
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     skip!(_i.args);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     skip!(_i.body);
 }
 #[cfg(feature = "full")]
@@ -2281,16 +2394,16 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.mod_token).0);
+    tokens_helper(_visitor, &_i.mod_token.span);
     _visitor.visit_ident(&_i.ident);
     if let Some(ref it) = _i.content {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.span);
         for it in &(it).1 {
             _visitor.visit_item(it)
         }
     };
     if let Some(ref it) = _i.semi {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2299,16 +2412,16 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.static_token).0);
+    tokens_helper(_visitor, &_i.static_token.span);
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&*_i.ty);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_expr(&*_i.expr);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_struct<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemStruct) {
@@ -2316,12 +2429,12 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.struct_token).0);
+    tokens_helper(_visitor, &_i.struct_token.span);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_generics(&_i.generics);
     _visitor.visit_fields(&_i.fields);
     if let Some(ref it) = _i.semi_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2331,38 +2444,57 @@
     }
     _visitor.visit_visibility(&_i.vis);
     if let Some(ref it) = _i.unsafety {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.auto_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.trait_token).0);
+    tokens_helper(_visitor, &_i.trait_token.span);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_generics(&_i.generics);
     if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.supertraits) {
         let it = el.value();
         _visitor.visit_type_param_bound(it)
     }
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for it in &_i.items {
         _visitor.visit_trait_item(it)
     }
 }
 #[cfg(feature = "full")]
+pub fn visit_item_trait_alias<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ItemTraitAlias,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.trait_token.span);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    tokens_helper(_visitor, &_i.eq_token.spans);
+    for el in Punctuated::pairs(&_i.bounds) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
 pub fn visit_item_type<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemType) {
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.type_token).0);
+    tokens_helper(_visitor, &_i.type_token.span);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_generics(&_i.generics);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_type(&*_i.ty);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_union<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemUnion) {
@@ -2370,7 +2502,7 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.union_token).0);
+    tokens_helper(_visitor, &_i.union_token.span);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_generics(&_i.generics);
     _visitor.visit_fields_named(&_i.fields);
@@ -2381,12 +2513,12 @@
         _visitor.visit_attribute(it)
     }
     _visitor.visit_visibility(&_i.vis);
-    tokens_helper(_visitor, &(_i.use_token).0);
+    tokens_helper(_visitor, &_i.use_token.span);
     if let Some(ref it) = _i.leading_colon {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     _visitor.visit_use_tree(&_i.tree);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
@@ -2399,11 +2531,10 @@
 #[cfg(feature = "full")]
 pub fn visit_label<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Label) {
     _visitor.visit_lifetime(&_i.name);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
 }
-#[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_lifetime<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Lifetime) {
-    skip!(_i.apostrophe);
+    _visitor.visit_span(&_i.apostrophe);
     _visitor.visit_ident(&_i.ident);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2413,7 +2544,7 @@
     }
     _visitor.visit_lifetime(&_i.lifetime);
     if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.bounds) {
         let it = el.value();
@@ -2488,25 +2619,25 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.let_token).0);
+    tokens_helper(_visitor, &_i.let_token.span);
     for el in Punctuated::pairs(&_i.pats) {
         let it = el.value();
         _visitor.visit_pat(it)
     }
     if let Some(ref it) = _i.ty {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.spans);
         _visitor.visit_type(&*(it).1);
     };
     if let Some(ref it) = _i.init {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.spans);
         _visitor.visit_expr(&*(it).1);
     };
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_macro<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Macro) {
     _visitor.visit_path(&_i.path);
-    tokens_helper(_visitor, &(_i.bang_token).0);
+    tokens_helper(_visitor, &_i.bang_token.spans);
     _visitor.visit_macro_delimiter(&_i.delimiter);
     skip!(_i.tts);
 }
@@ -2517,13 +2648,13 @@
 ) {
     match *_i {
         MacroDelimiter::Paren(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.span);
         }
         MacroDelimiter::Brace(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.span);
         }
         MacroDelimiter::Bracket(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.span);
         }
     }
 }
@@ -2555,7 +2686,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_meta_list<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast MetaList) {
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.nested) {
         let it = el.value();
         _visitor.visit_nested_meta(it)
@@ -2567,16 +2698,19 @@
     _i: &'ast MetaNameValue,
 ) {
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_lit(&_i.lit);
 }
 #[cfg(feature = "full")]
 pub fn visit_method_sig<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast MethodSig) {
     if let Some(ref it) = _i.constness {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.unsafety {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
+    };
+    if let Some(ref it) = _i.asyncness {
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.abi {
         _visitor.visit_abi(it)
@@ -2590,13 +2724,13 @@
     _visitor: &mut V,
     _i: &'ast MethodTurbofish,
 ) {
-    tokens_helper(_visitor, &(_i.colon2_token).0);
-    tokens_helper(_visitor, &(_i.lt_token).0);
+    tokens_helper(_visitor, &_i.colon2_token.spans);
+    tokens_helper(_visitor, &_i.lt_token.spans);
     for el in Punctuated::pairs(&_i.args) {
         let it = el.value();
         _visitor.visit_generic_method_argument(it)
     }
-    tokens_helper(_visitor, &(_i.gt_token).0);
+    tokens_helper(_visitor, &_i.gt_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_nested_meta<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast NestedMeta) {
@@ -2614,7 +2748,7 @@
     _visitor: &mut V,
     _i: &'ast ParenthesizedGenericArguments,
 ) {
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.inputs) {
         let it = el.value();
         _visitor.visit_type(it)
@@ -2669,21 +2803,21 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_box<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatBox) {
-    tokens_helper(_visitor, &(_i.box_token).0);
+    tokens_helper(_visitor, &_i.box_token.span);
     _visitor.visit_pat(&*_i.pat);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_ident<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatIdent) {
     if let Some(ref it) = _i.by_ref {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_ident(&_i.ident);
     if let Some(ref it) = _i.subpat {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.spans);
         _visitor.visit_pat(&*(it).1);
     };
 }
@@ -2715,16 +2849,16 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_ref<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatRef) {
-    tokens_helper(_visitor, &(_i.and_token).0);
+    tokens_helper(_visitor, &_i.and_token.spans);
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_pat(&*_i.pat);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_slice<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatSlice) {
-    tokens_helper(_visitor, &(_i.bracket_token).0);
+    tokens_helper(_visitor, &_i.bracket_token.span);
     for el in Punctuated::pairs(&_i.front) {
         let it = el.value();
         _visitor.visit_pat(it)
@@ -2733,10 +2867,10 @@
         _visitor.visit_pat(&**it)
     };
     if let Some(ref it) = _i.dot2_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     if let Some(ref it) = _i.comma_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.back) {
         let it = el.value();
@@ -2747,28 +2881,28 @@
 #[cfg(feature = "full")]
 pub fn visit_pat_struct<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatStruct) {
     _visitor.visit_path(&_i.path);
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for el in Punctuated::pairs(&_i.fields) {
         let it = el.value();
         _visitor.visit_field_pat(it)
     }
     if let Some(ref it) = _i.dot2_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_tuple<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatTuple) {
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.front) {
         let it = el.value();
         _visitor.visit_pat(it)
     }
     if let Some(ref it) = _i.dot2_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     if let Some(ref it) = _i.comma_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.back) {
         let it = el.value();
@@ -2792,12 +2926,12 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_wild<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatWild) {
-    tokens_helper(_visitor, &(_i.underscore_token).0);
+    tokens_helper(_visitor, &_i.underscore_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_path<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Path) {
     if let Some(ref it) = _i.leading_colon {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.segments) {
         let it = el.value();
@@ -2827,7 +2961,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_predicate_eq<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PredicateEq) {
     _visitor.visit_type(&_i.lhs_ty);
-    tokens_helper(_visitor, &(_i.eq_token).0);
+    tokens_helper(_visitor, &_i.eq_token.spans);
     _visitor.visit_type(&_i.rhs_ty);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2836,9 +2970,7 @@
     _i: &'ast PredicateLifetime,
 ) {
     _visitor.visit_lifetime(&_i.lifetime);
-    if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
-    };
+    tokens_helper(_visitor, &_i.colon_token.spans);
     for el in Punctuated::pairs(&_i.bounds) {
         let it = el.value();
         _visitor.visit_lifetime(it)
@@ -2853,7 +2985,7 @@
         _visitor.visit_bound_lifetimes(it)
     };
     _visitor.visit_type(&_i.bounded_ty);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     for el in Punctuated::pairs(&_i.bounds) {
         let it = el.value();
         _visitor.visit_type_param_bound(it)
@@ -2861,23 +2993,23 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_qself<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast QSelf) {
-    tokens_helper(_visitor, &(_i.lt_token).0);
+    tokens_helper(_visitor, &_i.lt_token.spans);
     _visitor.visit_type(&*_i.ty);
     skip!(_i.position);
     if let Some(ref it) = _i.as_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
-    tokens_helper(_visitor, &(_i.gt_token).0);
+    tokens_helper(_visitor, &_i.gt_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_range_limits<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast RangeLimits) {
     match *_i {
         RangeLimits::HalfOpen(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         RangeLimits::Closed(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
     }
 }
@@ -2886,7 +3018,7 @@
     match *_i {
         ReturnType::Default => {}
         ReturnType::Type(ref _binding_0, ref _binding_1) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
             _visitor.visit_type(&**_binding_1);
         }
     }
@@ -2907,14 +3039,14 @@
         }
         Stmt::Semi(ref _binding_0, ref _binding_1) => {
             _visitor.visit_expr(_binding_0);
-            tokens_helper(_visitor, &(_binding_1).0);
+            tokens_helper(_visitor, &_binding_1.spans);
         }
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_trait_bound<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TraitBound) {
     if let Some(ref it) = _i.paren_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_trait_bound_modifier(&_i.modifier);
     if let Some(ref it) = _i.lifetimes {
@@ -2930,7 +3062,7 @@
     match *_i {
         TraitBoundModifier::None => {}
         TraitBoundModifier::Maybe(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
     }
 }
@@ -2962,15 +3094,15 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.const_token).0);
+    tokens_helper(_visitor, &_i.const_token.span);
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.colon_token).0);
+    tokens_helper(_visitor, &_i.colon_token.spans);
     _visitor.visit_type(&_i.ty);
     if let Some(ref it) = _i.default {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.spans);
         _visitor.visit_expr(&(it).1);
     };
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_trait_item_macro<'ast, V: Visit<'ast> + ?Sized>(
@@ -2982,7 +3114,7 @@
     }
     _visitor.visit_macro(&_i.mac);
     if let Some(ref it) = _i.semi_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2998,7 +3130,7 @@
         _visitor.visit_block(it)
     };
     if let Some(ref it) = _i.semi_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -3009,21 +3141,21 @@
     for it in &_i.attrs {
         _visitor.visit_attribute(it)
     }
-    tokens_helper(_visitor, &(_i.type_token).0);
+    tokens_helper(_visitor, &_i.type_token.span);
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_generics(&_i.generics);
     if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.bounds) {
         let it = el.value();
         _visitor.visit_type_param_bound(it)
     }
     if let Some(ref it) = _i.default {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.spans);
         _visitor.visit_type(&(it).1);
     };
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_trait_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
@@ -3084,36 +3216,36 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_array<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeArray) {
-    tokens_helper(_visitor, &(_i.bracket_token).0);
+    tokens_helper(_visitor, &_i.bracket_token.span);
     _visitor.visit_type(&*_i.elem);
-    tokens_helper(_visitor, &(_i.semi_token).0);
+    tokens_helper(_visitor, &_i.semi_token.spans);
     _visitor.visit_expr(&_i.len);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_bare_fn<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeBareFn) {
+    if let Some(ref it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes(it)
+    };
     if let Some(ref it) = _i.unsafety {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.abi {
         _visitor.visit_abi(it)
     };
-    tokens_helper(_visitor, &(_i.fn_token).0);
-    if let Some(ref it) = _i.lifetimes {
-        _visitor.visit_bound_lifetimes(it)
-    };
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.fn_token.span);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.inputs) {
         let it = el.value();
         _visitor.visit_bare_fn_arg(it)
     }
     if let Some(ref it) = _i.variadic {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     _visitor.visit_return_type(&_i.output);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_group<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeGroup) {
-    tokens_helper(_visitor, &(_i.group_token).0);
+    tokens_helper(_visitor, &_i.group_token.span);
     _visitor.visit_type(&*_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -3121,7 +3253,7 @@
     _visitor: &mut V,
     _i: &'ast TypeImplTrait,
 ) {
-    tokens_helper(_visitor, &(_i.impl_token).0);
+    tokens_helper(_visitor, &_i.impl_token.span);
     for el in Punctuated::pairs(&_i.bounds) {
         let it = el.value();
         _visitor.visit_type_param_bound(it)
@@ -3129,7 +3261,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_infer<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeInfer) {
-    tokens_helper(_visitor, &(_i.underscore_token).0);
+    tokens_helper(_visitor, &_i.underscore_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_macro<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeMacro) {
@@ -3137,7 +3269,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_never<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeNever) {
-    tokens_helper(_visitor, &(_i.bang_token).0);
+    tokens_helper(_visitor, &_i.bang_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_param<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeParam) {
@@ -3146,14 +3278,14 @@
     }
     _visitor.visit_ident(&_i.ident);
     if let Some(ref it) = _i.colon_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     for el in Punctuated::pairs(&_i.bounds) {
         let it = el.value();
         _visitor.visit_type_param_bound(it)
     }
     if let Some(ref it) = _i.eq_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.spans)
     };
     if let Some(ref it) = _i.default {
         _visitor.visit_type(it)
@@ -3175,7 +3307,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_paren<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeParen) {
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     _visitor.visit_type(&*_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -3187,12 +3319,12 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_ptr<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypePtr) {
-    tokens_helper(_visitor, &(_i.star_token).0);
+    tokens_helper(_visitor, &_i.star_token.spans);
     if let Some(ref it) = _i.const_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_type(&*_i.elem);
 }
@@ -3201,18 +3333,18 @@
     _visitor: &mut V,
     _i: &'ast TypeReference,
 ) {
-    tokens_helper(_visitor, &(_i.and_token).0);
+    tokens_helper(_visitor, &_i.and_token.spans);
     if let Some(ref it) = _i.lifetime {
         _visitor.visit_lifetime(it)
     };
     if let Some(ref it) = _i.mutability {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_type(&*_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_slice<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeSlice) {
-    tokens_helper(_visitor, &(_i.bracket_token).0);
+    tokens_helper(_visitor, &_i.bracket_token.span);
     _visitor.visit_type(&*_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -3221,7 +3353,7 @@
     _i: &'ast TypeTraitObject,
 ) {
     if let Some(ref it) = _i.dyn_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     for el in Punctuated::pairs(&_i.bounds) {
         let it = el.value();
@@ -3230,7 +3362,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_tuple<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeTuple) {
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.paren_token.span);
     for el in Punctuated::pairs(&_i.elems) {
         let it = el.value();
         _visitor.visit_type(it)
@@ -3247,23 +3379,23 @@
 pub fn visit_un_op<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast UnOp) {
     match *_i {
         UnOp::Deref(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         UnOp::Not(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
         UnOp::Neg(ref _binding_0) => {
-            tokens_helper(_visitor, &(_binding_0).0);
+            tokens_helper(_visitor, &_binding_0.spans);
         }
     }
 }
 #[cfg(feature = "full")]
 pub fn visit_use_glob<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast UseGlob) {
-    tokens_helper(_visitor, &(_i.star_token).0);
+    tokens_helper(_visitor, &_i.star_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_use_group<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast UseGroup) {
-    tokens_helper(_visitor, &(_i.brace_token).0);
+    tokens_helper(_visitor, &_i.brace_token.span);
     for el in Punctuated::pairs(&_i.items) {
         let it = el.value();
         _visitor.visit_use_tree(it)
@@ -3276,13 +3408,13 @@
 #[cfg(feature = "full")]
 pub fn visit_use_path<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast UsePath) {
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.colon2_token).0);
+    tokens_helper(_visitor, &_i.colon2_token.spans);
     _visitor.visit_use_tree(&*_i.tree);
 }
 #[cfg(feature = "full")]
 pub fn visit_use_rename<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast UseRename) {
     _visitor.visit_ident(&_i.ident);
-    tokens_helper(_visitor, &(_i.as_token).0);
+    tokens_helper(_visitor, &_i.as_token.span);
     _visitor.visit_ident(&_i.rename);
 }
 #[cfg(feature = "full")]
@@ -3313,27 +3445,27 @@
     _visitor.visit_ident(&_i.ident);
     _visitor.visit_fields(&_i.fields);
     if let Some(ref it) = _i.discriminant {
-        tokens_helper(_visitor, &((it).0).0);
+        tokens_helper(_visitor, &(it).0.spans);
         _visitor.visit_expr(&(it).1);
     };
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_vis_crate<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast VisCrate) {
-    tokens_helper(_visitor, &(_i.crate_token).0);
+    tokens_helper(_visitor, &_i.crate_token.span);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_vis_public<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast VisPublic) {
-    tokens_helper(_visitor, &(_i.pub_token).0);
+    tokens_helper(_visitor, &_i.pub_token.span);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_vis_restricted<'ast, V: Visit<'ast> + ?Sized>(
     _visitor: &mut V,
     _i: &'ast VisRestricted,
 ) {
-    tokens_helper(_visitor, &(_i.pub_token).0);
-    tokens_helper(_visitor, &(_i.paren_token).0);
+    tokens_helper(_visitor, &_i.pub_token.span);
+    tokens_helper(_visitor, &_i.paren_token.span);
     if let Some(ref it) = _i.in_token {
-        tokens_helper(_visitor, &(it).0)
+        tokens_helper(_visitor, &it.span)
     };
     _visitor.visit_path(&*_i.path);
 }
@@ -3354,7 +3486,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_where_clause<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast WhereClause) {
-    tokens_helper(_visitor, &(_i.where_token).0);
+    tokens_helper(_visitor, &_i.where_token.span);
     for el in Punctuated::pairs(&_i.predicates) {
         let it = el.value();
         _visitor.visit_where_predicate(it)
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index 14a7970..0795daf 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -136,6 +136,11 @@
     fn visit_expr_assign_op_mut(&mut self, i: &mut ExprAssignOp) {
         visit_expr_assign_op_mut(self, i)
     }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_async_mut(&mut self, i: &mut ExprAsync) {
+        visit_expr_async_mut(self, i)
+    }
     #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_expr_binary_mut(&mut self, i: &mut ExprBinary) {
         visit_expr_binary_mut(self, i)
@@ -165,11 +170,6 @@
     }
     #[cfg(feature = "full")]
     #[cfg(any(feature = "full", feature = "derive"))]
-    fn visit_expr_catch_mut(&mut self, i: &mut ExprCatch) {
-        visit_expr_catch_mut(self, i)
-    }
-    #[cfg(feature = "full")]
-    #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_expr_closure_mut(&mut self, i: &mut ExprClosure) {
         visit_expr_closure_mut(self, i)
     }
@@ -275,6 +275,11 @@
     }
     #[cfg(feature = "full")]
     #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_try_block_mut(&mut self, i: &mut ExprTryBlock) {
+        visit_expr_try_block_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_expr_tuple_mut(&mut self, i: &mut ExprTuple) {
         visit_expr_tuple_mut(self, i)
     }
@@ -358,6 +363,10 @@
         visit_foreign_item_fn_mut(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_foreign_item_macro_mut(&mut self, i: &mut ForeignItemMacro) {
+        visit_foreign_item_macro_mut(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_foreign_item_static_mut(&mut self, i: &mut ForeignItemStatic) {
         visit_foreign_item_static_mut(self, i)
     }
@@ -398,6 +407,10 @@
         visit_impl_item_const_mut(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_impl_item_existential_mut(&mut self, i: &mut ImplItemExistential) {
+        visit_impl_item_existential_mut(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_impl_item_macro_mut(&mut self, i: &mut ImplItemMacro) {
         visit_impl_item_macro_mut(self, i)
     }
@@ -430,6 +443,10 @@
         visit_item_enum_mut(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_item_existential_mut(&mut self, i: &mut ItemExistential) {
+        visit_item_existential_mut(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_item_extern_crate_mut(&mut self, i: &mut ItemExternCrate) {
         visit_item_extern_crate_mut(self, i)
     }
@@ -470,6 +487,10 @@
         visit_item_trait_mut(self, i)
     }
     #[cfg(feature = "full")]
+    fn visit_item_trait_alias_mut(&mut self, i: &mut ItemTraitAlias) {
+        visit_item_trait_alias_mut(self, i)
+    }
+    #[cfg(feature = "full")]
     fn visit_item_type_mut(&mut self, i: &mut ItemType) {
         visit_item_type_mut(self, i)
     }
@@ -490,7 +511,6 @@
     fn visit_label_mut(&mut self, i: &mut Label) {
         visit_label_mut(self, i)
     }
-    #[cfg(any(feature = "full", feature = "derive"))]
     fn visit_lifetime_mut(&mut self, i: &mut Lifetime) {
         visit_lifetime_mut(self, i)
     }
@@ -858,7 +878,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_abi_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Abi) {
-    tokens_helper(_visitor, &mut (_i.extern_token).0);
+    tokens_helper(_visitor, &mut _i.extern_token.span);
     if let Some(ref mut it) = _i.name {
         _visitor.visit_lit_str_mut(it)
     };
@@ -869,38 +889,38 @@
     _i: &mut AngleBracketedGenericArguments,
 ) {
     if let Some(ref mut it) = _i.colon2_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
-    tokens_helper(_visitor, &mut (_i.lt_token).0);
+    tokens_helper(_visitor, &mut _i.lt_token.spans);
     for mut el in Punctuated::pairs_mut(&mut _i.args) {
         let it = el.value_mut();
         _visitor.visit_generic_argument_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.gt_token).0);
+    tokens_helper(_visitor, &mut _i.gt_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_arg_captured_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ArgCaptured) {
     _visitor.visit_pat_mut(&mut _i.pat);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut _i.ty);
 }
 #[cfg(feature = "full")]
 pub fn visit_arg_self_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ArgSelf) {
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.self_token).0);
+    tokens_helper(_visitor, &mut _i.self_token.span);
 }
 #[cfg(feature = "full")]
 pub fn visit_arg_self_ref_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ArgSelfRef) {
-    tokens_helper(_visitor, &mut (_i.and_token).0);
+    tokens_helper(_visitor, &mut _i.and_token.spans);
     if let Some(ref mut it) = _i.lifetime {
         _visitor.visit_lifetime_mut(it)
     };
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.self_token).0);
+    tokens_helper(_visitor, &mut _i.self_token.span);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
@@ -909,20 +929,20 @@
         _visitor.visit_attribute_mut(it)
     }
     if let Some(ref mut it) = _i.leading_vert {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.pats) {
         let it = el.value_mut();
         _visitor.visit_pat_mut(it)
     }
     if let Some(ref mut it) = _i.guard {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.span);
         _visitor.visit_expr_mut(&mut *(it).1);
     };
-    tokens_helper(_visitor, &mut (_i.fat_arrow_token).0);
+    tokens_helper(_visitor, &mut _i.fat_arrow_token.spans);
     _visitor.visit_expr_mut(&mut *_i.body);
     if let Some(ref mut it) = _i.comma {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -930,24 +950,23 @@
     match *_i {
         AttrStyle::Outer => {}
         AttrStyle::Inner(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_attribute_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Attribute) {
-    tokens_helper(_visitor, &mut (_i.pound_token).0);
+    tokens_helper(_visitor, &mut _i.pound_token.spans);
     _visitor.visit_attr_style_mut(&mut _i.style);
-    tokens_helper(_visitor, &mut (_i.bracket_token).0);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
     _visitor.visit_path_mut(&mut _i.path);
     skip!(_i.tts);
-    skip!(_i.is_sugared_doc);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_bare_fn_arg_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut BareFnArg) {
     if let Some(ref mut it) = _i.name {
         _visitor.visit_bare_fn_arg_name_mut(&mut (it).0);
-        tokens_helper(_visitor, &mut ((it).1).0);
+        tokens_helper(_visitor, &mut (it).1.spans);
     };
     _visitor.visit_type_mut(&mut _i.ty);
 }
@@ -958,7 +977,7 @@
             _visitor.visit_ident_mut(_binding_0);
         }
         BareFnArgName::Wild(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
     }
 }
@@ -966,126 +985,126 @@
 pub fn visit_bin_op_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut BinOp) {
     match *_i {
         BinOp::Add(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Sub(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Mul(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Div(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Rem(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::And(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Or(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::BitXor(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::BitAnd(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::BitOr(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Shl(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Shr(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Eq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Lt(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Le(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Ne(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Ge(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::Gt(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::AddEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::SubEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::MulEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::DivEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::RemEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::BitXorEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::BitAndEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::BitOrEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::ShlEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         BinOp::ShrEq(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_binding_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Binding) {
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_type_mut(&mut _i.ty);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_block_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Block) {
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for it in &mut _i.stmts {
         _visitor.visit_stmt_mut(it)
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_bound_lifetimes_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut BoundLifetimes) {
-    tokens_helper(_visitor, &mut (_i.for_token).0);
-    tokens_helper(_visitor, &mut (_i.lt_token).0);
+    tokens_helper(_visitor, &mut _i.for_token.span);
+    tokens_helper(_visitor, &mut _i.lt_token.spans);
     for mut el in Punctuated::pairs_mut(&mut _i.lifetimes) {
         let it = el.value_mut();
         _visitor.visit_lifetime_def_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.gt_token).0);
+    tokens_helper(_visitor, &mut _i.gt_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_const_param_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ConstParam) {
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.const_token).0);
+    tokens_helper(_visitor, &mut _i.const_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut _i.ty);
     if let Some(ref mut it) = _i.eq_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     if let Some(ref mut it) = _i.default {
         _visitor.visit_expr_mut(it)
@@ -1107,8 +1126,8 @@
 }
 #[cfg(feature = "derive")]
 pub fn visit_data_enum_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut DataEnum) {
-    tokens_helper(_visitor, &mut (_i.enum_token).0);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.enum_token.span);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.variants) {
         let it = el.value_mut();
         _visitor.visit_variant_mut(it)
@@ -1116,15 +1135,15 @@
 }
 #[cfg(feature = "derive")]
 pub fn visit_data_struct_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut DataStruct) {
-    tokens_helper(_visitor, &mut (_i.struct_token).0);
+    tokens_helper(_visitor, &mut _i.struct_token.span);
     _visitor.visit_fields_mut(&mut _i.fields);
     if let Some(ref mut it) = _i.semi_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(feature = "derive")]
 pub fn visit_data_union_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut DataUnion) {
-    tokens_helper(_visitor, &mut (_i.union_token).0);
+    tokens_helper(_visitor, &mut _i.union_token.span);
     _visitor.visit_fields_named_mut(&mut _i.fields);
 }
 #[cfg(feature = "derive")]
@@ -1251,8 +1270,11 @@
         Expr::Try(ref mut _binding_0) => {
             full!(_visitor.visit_expr_try_mut(_binding_0));
         }
-        Expr::Catch(ref mut _binding_0) => {
-            full!(_visitor.visit_expr_catch_mut(_binding_0));
+        Expr::Async(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_async_mut(_binding_0));
+        }
+        Expr::TryBlock(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_try_block_mut(_binding_0));
         }
         Expr::Yield(ref mut _binding_0) => {
             full!(_visitor.visit_expr_yield_mut(_binding_0));
@@ -1268,7 +1290,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.bracket_token).0);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.elems) {
         let it = el.value_mut();
         _visitor.visit_expr_mut(it)
@@ -1281,7 +1303,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.left);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_expr_mut(&mut *_i.right);
 }
 #[cfg(feature = "full")]
@@ -1294,6 +1316,18 @@
     _visitor.visit_bin_op_mut(&mut _i.op);
     _visitor.visit_expr_mut(&mut *_i.right);
 }
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_async_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAsync) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.async_token.span);
+    if let Some(ref mut it) = _i.capture {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    _visitor.visit_block_mut(&mut _i.block);
+}
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_expr_binary_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBinary) {
     for it in &mut _i.attrs {
@@ -1309,6 +1343,9 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
+    if let Some(ref mut it) = _i.label {
+        _visitor.visit_label_mut(it)
+    };
     _visitor.visit_block_mut(&mut _i.block);
 }
 #[cfg(feature = "full")]
@@ -1317,7 +1354,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.box_token).0);
+    tokens_helper(_visitor, &mut _i.box_token.span);
     _visitor.visit_expr_mut(&mut *_i.expr);
 }
 #[cfg(feature = "full")]
@@ -1326,7 +1363,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.break_token).0);
+    tokens_helper(_visitor, &mut _i.break_token.span);
     if let Some(ref mut it) = _i.label {
         _visitor.visit_lifetime_mut(it)
     };
@@ -1340,7 +1377,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.func);
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.args) {
         let it = el.value_mut();
         _visitor.visit_expr_mut(it)
@@ -1352,37 +1389,30 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.as_token).0);
+    tokens_helper(_visitor, &mut _i.as_token.span);
     _visitor.visit_type_mut(&mut *_i.ty);
 }
 #[cfg(feature = "full")]
 #[cfg(any(feature = "full", feature = "derive"))]
-pub fn visit_expr_catch_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCatch) {
-    for it in &mut _i.attrs {
-        _visitor.visit_attribute_mut(it)
-    }
-    tokens_helper(_visitor, &mut (_i.do_token).0);
-    tokens_helper(_visitor, &mut (_i.catch_token).0);
-    _visitor.visit_block_mut(&mut _i.block);
-}
-#[cfg(feature = "full")]
-#[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_expr_closure_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprClosure) {
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
+    if let Some(ref mut it) = _i.asyncness {
+        tokens_helper(_visitor, &mut it.span)
+    };
     if let Some(ref mut it) = _i.movability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.capture {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.or1_token).0);
+    tokens_helper(_visitor, &mut _i.or1_token.spans);
     for mut el in Punctuated::pairs_mut(&mut _i.inputs) {
         let it = el.value_mut();
         _visitor.visit_fn_arg_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.or2_token).0);
+    tokens_helper(_visitor, &mut _i.or2_token.spans);
     _visitor.visit_return_type_mut(&mut _i.output);
     _visitor.visit_expr_mut(&mut *_i.body);
 }
@@ -1392,7 +1422,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.continue_token).0);
+    tokens_helper(_visitor, &mut _i.continue_token.span);
     if let Some(ref mut it) = _i.label {
         _visitor.visit_lifetime_mut(it)
     };
@@ -1403,7 +1433,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.base);
-    tokens_helper(_visitor, &mut (_i.dot_token).0);
+    tokens_helper(_visitor, &mut _i.dot_token.spans);
     _visitor.visit_member_mut(&mut _i.member);
 }
 #[cfg(feature = "full")]
@@ -1415,9 +1445,9 @@
     if let Some(ref mut it) = _i.label {
         _visitor.visit_label_mut(it)
     };
-    tokens_helper(_visitor, &mut (_i.for_token).0);
+    tokens_helper(_visitor, &mut _i.for_token.span);
     _visitor.visit_pat_mut(&mut *_i.pat);
-    tokens_helper(_visitor, &mut (_i.in_token).0);
+    tokens_helper(_visitor, &mut _i.in_token.span);
     _visitor.visit_expr_mut(&mut *_i.expr);
     _visitor.visit_block_mut(&mut _i.body);
 }
@@ -1427,7 +1457,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.group_token).0);
+    tokens_helper(_visitor, &mut _i.group_token.span);
     _visitor.visit_expr_mut(&mut *_i.expr);
 }
 #[cfg(feature = "full")]
@@ -1436,11 +1466,11 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.if_token).0);
+    tokens_helper(_visitor, &mut _i.if_token.span);
     _visitor.visit_expr_mut(&mut *_i.cond);
     _visitor.visit_block_mut(&mut _i.then_branch);
     if let Some(ref mut it) = _i.else_branch {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.span);
         _visitor.visit_expr_mut(&mut *(it).1);
     };
 }
@@ -1450,17 +1480,17 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.if_token).0);
-    tokens_helper(_visitor, &mut (_i.let_token).0);
+    tokens_helper(_visitor, &mut _i.if_token.span);
+    tokens_helper(_visitor, &mut _i.let_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.pats) {
         let it = el.value_mut();
         _visitor.visit_pat_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_expr_mut(&mut *_i.expr);
     _visitor.visit_block_mut(&mut _i.then_branch);
     if let Some(ref mut it) = _i.else_branch {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.span);
         _visitor.visit_expr_mut(&mut *(it).1);
     };
 }
@@ -1471,7 +1501,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.place);
-    tokens_helper(_visitor, &mut (_i.arrow_token).0);
+    tokens_helper(_visitor, &mut _i.arrow_token.spans);
     _visitor.visit_expr_mut(&mut *_i.value);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1480,7 +1510,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.bracket_token).0);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
     _visitor.visit_expr_mut(&mut *_i.index);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1499,7 +1529,7 @@
     if let Some(ref mut it) = _i.label {
         _visitor.visit_label_mut(it)
     };
-    tokens_helper(_visitor, &mut (_i.loop_token).0);
+    tokens_helper(_visitor, &mut _i.loop_token.span);
     _visitor.visit_block_mut(&mut _i.body);
 }
 #[cfg(feature = "full")]
@@ -1516,9 +1546,9 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.match_token).0);
+    tokens_helper(_visitor, &mut _i.match_token.span);
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for it in &mut _i.arms {
         _visitor.visit_arm_mut(it)
     }
@@ -1530,12 +1560,12 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.receiver);
-    tokens_helper(_visitor, &mut (_i.dot_token).0);
+    tokens_helper(_visitor, &mut _i.dot_token.spans);
     _visitor.visit_ident_mut(&mut _i.method);
     if let Some(ref mut it) = _i.turbofish {
         _visitor.visit_method_turbofish_mut(it)
     };
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.args) {
         let it = el.value_mut();
         _visitor.visit_expr_mut(it)
@@ -1546,7 +1576,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     _visitor.visit_expr_mut(&mut *_i.expr);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1579,9 +1609,9 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.and_token).0);
+    tokens_helper(_visitor, &mut _i.and_token.spans);
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_expr_mut(&mut *_i.expr);
 }
@@ -1591,9 +1621,9 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.bracket_token).0);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
     _visitor.visit_expr_mut(&mut *_i.len);
 }
 #[cfg(feature = "full")]
@@ -1602,7 +1632,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.return_token).0);
+    tokens_helper(_visitor, &mut _i.return_token.span);
     if let Some(ref mut it) = _i.expr {
         _visitor.visit_expr_mut(&mut **it)
     };
@@ -1614,13 +1644,13 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_path_mut(&mut _i.path);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.fields) {
         let it = el.value_mut();
         _visitor.visit_field_value_mut(it)
     }
     if let Some(ref mut it) = _i.dot2_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     if let Some(ref mut it) = _i.rest {
         _visitor.visit_expr_mut(&mut **it)
@@ -1633,7 +1663,16 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.question_token).0);
+    tokens_helper(_visitor, &mut _i.question_token.spans);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_try_block_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprTryBlock) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.try_token.span);
+    _visitor.visit_block_mut(&mut _i.block);
 }
 #[cfg(feature = "full")]
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1641,7 +1680,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.elems) {
         let it = el.value_mut();
         _visitor.visit_expr_mut(it)
@@ -1654,7 +1693,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut *_i.ty);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1671,7 +1710,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.unsafe_token).0);
+    tokens_helper(_visitor, &mut _i.unsafe_token.span);
     _visitor.visit_block_mut(&mut _i.block);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -1687,7 +1726,7 @@
     if let Some(ref mut it) = _i.label {
         _visitor.visit_label_mut(it)
     };
-    tokens_helper(_visitor, &mut (_i.while_token).0);
+    tokens_helper(_visitor, &mut _i.while_token.span);
     _visitor.visit_expr_mut(&mut *_i.cond);
     _visitor.visit_block_mut(&mut _i.body);
 }
@@ -1700,13 +1739,13 @@
     if let Some(ref mut it) = _i.label {
         _visitor.visit_label_mut(it)
     };
-    tokens_helper(_visitor, &mut (_i.while_token).0);
-    tokens_helper(_visitor, &mut (_i.let_token).0);
+    tokens_helper(_visitor, &mut _i.while_token.span);
+    tokens_helper(_visitor, &mut _i.let_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.pats) {
         let it = el.value_mut();
         _visitor.visit_pat_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_expr_mut(&mut *_i.expr);
     _visitor.visit_block_mut(&mut _i.body);
 }
@@ -1716,7 +1755,7 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.yield_token).0);
+    tokens_helper(_visitor, &mut _i.yield_token.span);
     if let Some(ref mut it) = _i.expr {
         _visitor.visit_expr_mut(&mut **it)
     };
@@ -1731,7 +1770,7 @@
         _visitor.visit_ident_mut(it)
     };
     if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     _visitor.visit_type_mut(&mut _i.ty);
 }
@@ -1743,7 +1782,7 @@
     }
     _visitor.visit_member_mut(&mut _i.member);
     if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     _visitor.visit_pat_mut(&mut *_i.pat);
 }
@@ -1755,7 +1794,7 @@
     }
     _visitor.visit_member_mut(&mut _i.member);
     if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     _visitor.visit_expr_mut(&mut _i.expr);
 }
@@ -1773,7 +1812,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_fields_named_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut FieldsNamed) {
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.named) {
         let it = el.value_mut();
         _visitor.visit_field_mut(it)
@@ -1781,7 +1820,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_fields_unnamed_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut FieldsUnnamed) {
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.unnamed) {
         let it = el.value_mut();
         _visitor.visit_field_mut(it)
@@ -1819,15 +1858,15 @@
 }
 #[cfg(feature = "full")]
 pub fn visit_fn_decl_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut FnDecl) {
-    tokens_helper(_visitor, &mut (_i.fn_token).0);
+    tokens_helper(_visitor, &mut _i.fn_token.span);
     _visitor.visit_generics_mut(&mut _i.generics);
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.inputs) {
         let it = el.value_mut();
         _visitor.visit_fn_arg_mut(it)
     }
     if let Some(ref mut it) = _i.variadic {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     _visitor.visit_return_type_mut(&mut _i.output);
 }
@@ -1843,6 +1882,9 @@
         ForeignItem::Type(ref mut _binding_0) => {
             _visitor.visit_foreign_item_type_mut(_binding_0);
         }
+        ForeignItem::Macro(ref mut _binding_0) => {
+            _visitor.visit_foreign_item_macro_mut(_binding_0);
+        }
         ForeignItem::Verbatim(ref mut _binding_0) => {
             _visitor.visit_foreign_item_verbatim_mut(_binding_0);
         }
@@ -1856,7 +1898,20 @@
     _visitor.visit_visibility_mut(&mut _i.vis);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_fn_decl_mut(&mut *_i.decl);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_macro_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut ForeignItemMacro,
+) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_macro_mut(&mut _i.mac);
+    if let Some(ref mut it) = _i.semi_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
 }
 #[cfg(feature = "full")]
 pub fn visit_foreign_item_static_mut<V: VisitMut + ?Sized>(
@@ -1867,14 +1922,14 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.static_token).0);
+    tokens_helper(_visitor, &mut _i.static_token.span);
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut *_i.ty);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_foreign_item_type_mut<V: VisitMut + ?Sized>(
@@ -1885,9 +1940,9 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.type_token).0);
+    tokens_helper(_visitor, &mut _i.type_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_foreign_item_verbatim_mut<V: VisitMut + ?Sized>(
@@ -1948,14 +2003,14 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_generics_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Generics) {
     if let Some(ref mut it) = _i.lt_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.params) {
         let it = el.value_mut();
         _visitor.visit_generic_param_mut(it)
     }
     if let Some(ref mut it) = _i.gt_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     if let Some(ref mut it) = _i.where_clause {
         _visitor.visit_where_clause_mut(it)
@@ -1974,6 +2029,9 @@
         ImplItem::Type(ref mut _binding_0) => {
             _visitor.visit_impl_item_type_mut(_binding_0);
         }
+        ImplItem::Existential(ref mut _binding_0) => {
+            _visitor.visit_impl_item_existential_mut(_binding_0);
+        }
         ImplItem::Macro(ref mut _binding_0) => {
             _visitor.visit_impl_item_macro_mut(_binding_0);
         }
@@ -1989,15 +2047,36 @@
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
     if let Some(ref mut it) = _i.defaultness {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.const_token).0);
+    tokens_helper(_visitor, &mut _i.const_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut _i.ty);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_expr_mut(&mut _i.expr);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_existential_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut ImplItemExistential,
+) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.existential_token.span);
+    tokens_helper(_visitor, &mut _i.type_token.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_generics_mut(&mut _i.generics);
+    if let Some(ref mut it) = _i.colon_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
+        let it = el.value_mut();
+        _visitor.visit_type_param_bound_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_impl_item_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ImplItemMacro) {
@@ -2006,7 +2085,7 @@
     }
     _visitor.visit_macro_mut(&mut _i.mac);
     if let Some(ref mut it) = _i.semi_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2016,7 +2095,7 @@
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
     if let Some(ref mut it) = _i.defaultness {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_method_sig_mut(&mut _i.sig);
     _visitor.visit_block_mut(&mut _i.block);
@@ -2028,14 +2107,14 @@
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
     if let Some(ref mut it) = _i.defaultness {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.type_token).0);
+    tokens_helper(_visitor, &mut _i.type_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_generics_mut(&mut _i.generics);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_type_mut(&mut _i.ty);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_impl_item_verbatim_mut<V: VisitMut + ?Sized>(
@@ -2076,6 +2155,9 @@
         Item::Type(ref mut _binding_0) => {
             _visitor.visit_item_type_mut(_binding_0);
         }
+        Item::Existential(ref mut _binding_0) => {
+            _visitor.visit_item_existential_mut(_binding_0);
+        }
         Item::Struct(ref mut _binding_0) => {
             _visitor.visit_item_struct_mut(_binding_0);
         }
@@ -2088,6 +2170,9 @@
         Item::Trait(ref mut _binding_0) => {
             _visitor.visit_item_trait_mut(_binding_0);
         }
+        Item::TraitAlias(ref mut _binding_0) => {
+            _visitor.visit_item_trait_alias_mut(_binding_0);
+        }
         Item::Impl(ref mut _binding_0) => {
             _visitor.visit_item_impl_mut(_binding_0);
         }
@@ -2108,13 +2193,13 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.const_token).0);
+    tokens_helper(_visitor, &mut _i.const_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut *_i.ty);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_enum_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemEnum) {
@@ -2122,16 +2207,38 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.enum_token).0);
+    tokens_helper(_visitor, &mut _i.enum_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_generics_mut(&mut _i.generics);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.variants) {
         let it = el.value_mut();
         _visitor.visit_variant_mut(it)
     }
 }
 #[cfg(feature = "full")]
+pub fn visit_item_existential_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut ItemExistential,
+) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    tokens_helper(_visitor, &mut _i.existential_token.span);
+    tokens_helper(_visitor, &mut _i.type_token.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_generics_mut(&mut _i.generics);
+    if let Some(ref mut it) = _i.colon_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
+        let it = el.value_mut();
+        _visitor.visit_type_param_bound_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
 pub fn visit_item_extern_crate_mut<V: VisitMut + ?Sized>(
     _visitor: &mut V,
     _i: &mut ItemExternCrate,
@@ -2140,14 +2247,14 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.extern_token).0);
-    tokens_helper(_visitor, &mut (_i.crate_token).0);
+    tokens_helper(_visitor, &mut _i.extern_token.span);
+    tokens_helper(_visitor, &mut _i.crate_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     if let Some(ref mut it) = _i.rename {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.span);
         _visitor.visit_ident_mut(&mut (it).1);
     };
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_fn_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemFn) {
@@ -2156,10 +2263,13 @@
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
     if let Some(ref mut it) = _i.constness {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.unsafety {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
+    };
+    if let Some(ref mut it) = _i.asyncness {
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.abi {
         _visitor.visit_abi_mut(it)
@@ -2174,7 +2284,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_abi_mut(&mut _i.abi);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for it in &mut _i.items {
         _visitor.visit_foreign_item_mut(it)
     }
@@ -2185,22 +2295,22 @@
         _visitor.visit_attribute_mut(it)
     }
     if let Some(ref mut it) = _i.defaultness {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.unsafety {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.impl_token).0);
+    tokens_helper(_visitor, &mut _i.impl_token.span);
     _visitor.visit_generics_mut(&mut _i.generics);
     if let Some(ref mut it) = _i.trait_ {
         if let Some(ref mut it) = (it).0 {
-            tokens_helper(_visitor, &mut (it).0)
+            tokens_helper(_visitor, &mut it.spans)
         };
         _visitor.visit_path_mut(&mut (it).1);
-        tokens_helper(_visitor, &mut ((it).2).0);
+        tokens_helper(_visitor, &mut (it).2.span);
     };
     _visitor.visit_type_mut(&mut *_i.self_ty);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for it in &mut _i.items {
         _visitor.visit_impl_item_mut(it)
     }
@@ -2215,7 +2325,7 @@
     };
     _visitor.visit_macro_mut(&mut _i.mac);
     if let Some(ref mut it) = _i.semi_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2224,11 +2334,11 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.macro_token).0);
+    tokens_helper(_visitor, &mut _i.macro_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     skip!(_i.args);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     skip!(_i.body);
 }
 #[cfg(feature = "full")]
@@ -2237,16 +2347,16 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.mod_token).0);
+    tokens_helper(_visitor, &mut _i.mod_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     if let Some(ref mut it) = _i.content {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.span);
         for it in &mut (it).1 {
             _visitor.visit_item_mut(it)
         }
     };
     if let Some(ref mut it) = _i.semi {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2255,16 +2365,16 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.static_token).0);
+    tokens_helper(_visitor, &mut _i.static_token.span);
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut *_i.ty);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_expr_mut(&mut *_i.expr);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_struct_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemStruct) {
@@ -2272,12 +2382,12 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.struct_token).0);
+    tokens_helper(_visitor, &mut _i.struct_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_generics_mut(&mut _i.generics);
     _visitor.visit_fields_mut(&mut _i.fields);
     if let Some(ref mut it) = _i.semi_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2287,38 +2397,54 @@
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
     if let Some(ref mut it) = _i.unsafety {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.auto_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.trait_token).0);
+    tokens_helper(_visitor, &mut _i.trait_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_generics_mut(&mut _i.generics);
     if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.supertraits) {
         let it = el.value_mut();
         _visitor.visit_type_param_bound_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for it in &mut _i.items {
         _visitor.visit_trait_item_mut(it)
     }
 }
 #[cfg(feature = "full")]
+pub fn visit_item_trait_alias_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemTraitAlias) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    tokens_helper(_visitor, &mut _i.trait_token.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_generics_mut(&mut _i.generics);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
+    for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
+        let it = el.value_mut();
+        _visitor.visit_type_param_bound_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
 pub fn visit_item_type_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemType) {
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.type_token).0);
+    tokens_helper(_visitor, &mut _i.type_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_generics_mut(&mut _i.generics);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_type_mut(&mut *_i.ty);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_union_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemUnion) {
@@ -2326,7 +2452,7 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.union_token).0);
+    tokens_helper(_visitor, &mut _i.union_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_generics_mut(&mut _i.generics);
     _visitor.visit_fields_named_mut(&mut _i.fields);
@@ -2337,12 +2463,12 @@
         _visitor.visit_attribute_mut(it)
     }
     _visitor.visit_visibility_mut(&mut _i.vis);
-    tokens_helper(_visitor, &mut (_i.use_token).0);
+    tokens_helper(_visitor, &mut _i.use_token.span);
     if let Some(ref mut it) = _i.leading_colon {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     _visitor.visit_use_tree_mut(&mut _i.tree);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_item_verbatim_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemVerbatim) {
@@ -2352,11 +2478,10 @@
 #[cfg(feature = "full")]
 pub fn visit_label_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Label) {
     _visitor.visit_lifetime_mut(&mut _i.name);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
 }
-#[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_lifetime_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Lifetime) {
-    skip!(_i.apostrophe);
+    _visitor.visit_span_mut(&mut _i.apostrophe);
     _visitor.visit_ident_mut(&mut _i.ident);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2366,7 +2491,7 @@
     }
     _visitor.visit_lifetime_mut(&mut _i.lifetime);
     if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
         let it = el.value_mut();
@@ -2441,25 +2566,25 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.let_token).0);
+    tokens_helper(_visitor, &mut _i.let_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.pats) {
         let it = el.value_mut();
         _visitor.visit_pat_mut(it)
     }
     if let Some(ref mut it) = _i.ty {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.spans);
         _visitor.visit_type_mut(&mut *(it).1);
     };
     if let Some(ref mut it) = _i.init {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.spans);
         _visitor.visit_expr_mut(&mut *(it).1);
     };
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Macro) {
     _visitor.visit_path_mut(&mut _i.path);
-    tokens_helper(_visitor, &mut (_i.bang_token).0);
+    tokens_helper(_visitor, &mut _i.bang_token.spans);
     _visitor.visit_macro_delimiter_mut(&mut _i.delimiter);
     skip!(_i.tts);
 }
@@ -2467,13 +2592,13 @@
 pub fn visit_macro_delimiter_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut MacroDelimiter) {
     match *_i {
         MacroDelimiter::Paren(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.span);
         }
         MacroDelimiter::Brace(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.span);
         }
         MacroDelimiter::Bracket(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.span);
         }
     }
 }
@@ -2505,7 +2630,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_meta_list_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut MetaList) {
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.nested) {
         let it = el.value_mut();
         _visitor.visit_nested_meta_mut(it)
@@ -2514,16 +2639,19 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_meta_name_value_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut MetaNameValue) {
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_lit_mut(&mut _i.lit);
 }
 #[cfg(feature = "full")]
 pub fn visit_method_sig_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut MethodSig) {
     if let Some(ref mut it) = _i.constness {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.unsafety {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
+    };
+    if let Some(ref mut it) = _i.asyncness {
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.abi {
         _visitor.visit_abi_mut(it)
@@ -2537,13 +2665,13 @@
     _visitor: &mut V,
     _i: &mut MethodTurbofish,
 ) {
-    tokens_helper(_visitor, &mut (_i.colon2_token).0);
-    tokens_helper(_visitor, &mut (_i.lt_token).0);
+    tokens_helper(_visitor, &mut _i.colon2_token.spans);
+    tokens_helper(_visitor, &mut _i.lt_token.spans);
     for mut el in Punctuated::pairs_mut(&mut _i.args) {
         let it = el.value_mut();
         _visitor.visit_generic_method_argument_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.gt_token).0);
+    tokens_helper(_visitor, &mut _i.gt_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_nested_meta_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut NestedMeta) {
@@ -2561,7 +2689,7 @@
     _visitor: &mut V,
     _i: &mut ParenthesizedGenericArguments,
 ) {
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.inputs) {
         let it = el.value_mut();
         _visitor.visit_type_mut(it)
@@ -2616,21 +2744,21 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_box_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatBox) {
-    tokens_helper(_visitor, &mut (_i.box_token).0);
+    tokens_helper(_visitor, &mut _i.box_token.span);
     _visitor.visit_pat_mut(&mut *_i.pat);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_ident_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatIdent) {
     if let Some(ref mut it) = _i.by_ref {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_ident_mut(&mut _i.ident);
     if let Some(ref mut it) = _i.subpat {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.spans);
         _visitor.visit_pat_mut(&mut *(it).1);
     };
 }
@@ -2662,16 +2790,16 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_ref_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatRef) {
-    tokens_helper(_visitor, &mut (_i.and_token).0);
+    tokens_helper(_visitor, &mut _i.and_token.spans);
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_pat_mut(&mut *_i.pat);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_slice_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatSlice) {
-    tokens_helper(_visitor, &mut (_i.bracket_token).0);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.front) {
         let it = el.value_mut();
         _visitor.visit_pat_mut(it)
@@ -2680,10 +2808,10 @@
         _visitor.visit_pat_mut(&mut **it)
     };
     if let Some(ref mut it) = _i.dot2_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     if let Some(ref mut it) = _i.comma_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.back) {
         let it = el.value_mut();
@@ -2694,28 +2822,28 @@
 #[cfg(feature = "full")]
 pub fn visit_pat_struct_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatStruct) {
     _visitor.visit_path_mut(&mut _i.path);
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.fields) {
         let it = el.value_mut();
         _visitor.visit_field_pat_mut(it)
     }
     if let Some(ref mut it) = _i.dot2_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_tuple_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatTuple) {
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.front) {
         let it = el.value_mut();
         _visitor.visit_pat_mut(it)
     }
     if let Some(ref mut it) = _i.dot2_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     if let Some(ref mut it) = _i.comma_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.back) {
         let it = el.value_mut();
@@ -2736,12 +2864,12 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_pat_wild_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatWild) {
-    tokens_helper(_visitor, &mut (_i.underscore_token).0);
+    tokens_helper(_visitor, &mut _i.underscore_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_path_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Path) {
     if let Some(ref mut it) = _i.leading_colon {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.segments) {
         let it = el.value_mut();
@@ -2768,7 +2896,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_predicate_eq_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PredicateEq) {
     _visitor.visit_type_mut(&mut _i.lhs_ty);
-    tokens_helper(_visitor, &mut (_i.eq_token).0);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
     _visitor.visit_type_mut(&mut _i.rhs_ty);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -2777,9 +2905,7 @@
     _i: &mut PredicateLifetime,
 ) {
     _visitor.visit_lifetime_mut(&mut _i.lifetime);
-    if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
-    };
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
         let it = el.value_mut();
         _visitor.visit_lifetime_mut(it)
@@ -2791,7 +2917,7 @@
         _visitor.visit_bound_lifetimes_mut(it)
     };
     _visitor.visit_type_mut(&mut _i.bounded_ty);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
         let it = el.value_mut();
         _visitor.visit_type_param_bound_mut(it)
@@ -2799,23 +2925,23 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_qself_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut QSelf) {
-    tokens_helper(_visitor, &mut (_i.lt_token).0);
+    tokens_helper(_visitor, &mut _i.lt_token.spans);
     _visitor.visit_type_mut(&mut *_i.ty);
     skip!(_i.position);
     if let Some(ref mut it) = _i.as_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
-    tokens_helper(_visitor, &mut (_i.gt_token).0);
+    tokens_helper(_visitor, &mut _i.gt_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 #[cfg(feature = "full")]
 pub fn visit_range_limits_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut RangeLimits) {
     match *_i {
         RangeLimits::HalfOpen(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         RangeLimits::Closed(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
     }
 }
@@ -2824,7 +2950,7 @@
     match *_i {
         ReturnType::Default => {}
         ReturnType::Type(ref mut _binding_0, ref mut _binding_1) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
             _visitor.visit_type_mut(&mut **_binding_1);
         }
     }
@@ -2845,14 +2971,14 @@
         }
         Stmt::Semi(ref mut _binding_0, ref mut _binding_1) => {
             _visitor.visit_expr_mut(_binding_0);
-            tokens_helper(_visitor, &mut (_binding_1).0);
+            tokens_helper(_visitor, &mut _binding_1.spans);
         }
     }
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_trait_bound_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TraitBound) {
     if let Some(ref mut it) = _i.paren_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_trait_bound_modifier_mut(&mut _i.modifier);
     if let Some(ref mut it) = _i.lifetimes {
@@ -2868,7 +2994,7 @@
     match *_i {
         TraitBoundModifier::None => {}
         TraitBoundModifier::Maybe(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
     }
 }
@@ -2897,15 +3023,15 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.const_token).0);
+    tokens_helper(_visitor, &mut _i.const_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.colon_token).0);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
     _visitor.visit_type_mut(&mut _i.ty);
     if let Some(ref mut it) = _i.default {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.spans);
         _visitor.visit_expr_mut(&mut (it).1);
     };
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_trait_item_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TraitItemMacro) {
@@ -2914,7 +3040,7 @@
     }
     _visitor.visit_macro_mut(&mut _i.mac);
     if let Some(ref mut it) = _i.semi_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2930,7 +3056,7 @@
         _visitor.visit_block_mut(it)
     };
     if let Some(ref mut it) = _i.semi_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
 }
 #[cfg(feature = "full")]
@@ -2938,21 +3064,21 @@
     for it in &mut _i.attrs {
         _visitor.visit_attribute_mut(it)
     }
-    tokens_helper(_visitor, &mut (_i.type_token).0);
+    tokens_helper(_visitor, &mut _i.type_token.span);
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_generics_mut(&mut _i.generics);
     if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
         let it = el.value_mut();
         _visitor.visit_type_param_bound_mut(it)
     }
     if let Some(ref mut it) = _i.default {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.spans);
         _visitor.visit_type_mut(&mut (it).1);
     };
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_trait_item_verbatim_mut<V: VisitMut + ?Sized>(
@@ -3013,41 +3139,41 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_array_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeArray) {
-    tokens_helper(_visitor, &mut (_i.bracket_token).0);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
     _visitor.visit_type_mut(&mut *_i.elem);
-    tokens_helper(_visitor, &mut (_i.semi_token).0);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
     _visitor.visit_expr_mut(&mut _i.len);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_bare_fn_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeBareFn) {
+    if let Some(ref mut it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes_mut(it)
+    };
     if let Some(ref mut it) = _i.unsafety {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.abi {
         _visitor.visit_abi_mut(it)
     };
-    tokens_helper(_visitor, &mut (_i.fn_token).0);
-    if let Some(ref mut it) = _i.lifetimes {
-        _visitor.visit_bound_lifetimes_mut(it)
-    };
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.fn_token.span);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.inputs) {
         let it = el.value_mut();
         _visitor.visit_bare_fn_arg_mut(it)
     }
     if let Some(ref mut it) = _i.variadic {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     _visitor.visit_return_type_mut(&mut _i.output);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_group_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeGroup) {
-    tokens_helper(_visitor, &mut (_i.group_token).0);
+    tokens_helper(_visitor, &mut _i.group_token.span);
     _visitor.visit_type_mut(&mut *_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_impl_trait_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeImplTrait) {
-    tokens_helper(_visitor, &mut (_i.impl_token).0);
+    tokens_helper(_visitor, &mut _i.impl_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
         let it = el.value_mut();
         _visitor.visit_type_param_bound_mut(it)
@@ -3055,7 +3181,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_infer_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeInfer) {
-    tokens_helper(_visitor, &mut (_i.underscore_token).0);
+    tokens_helper(_visitor, &mut _i.underscore_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeMacro) {
@@ -3063,7 +3189,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_never_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeNever) {
-    tokens_helper(_visitor, &mut (_i.bang_token).0);
+    tokens_helper(_visitor, &mut _i.bang_token.spans);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_param_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeParam) {
@@ -3072,14 +3198,14 @@
     }
     _visitor.visit_ident_mut(&mut _i.ident);
     if let Some(ref mut it) = _i.colon_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
         let it = el.value_mut();
         _visitor.visit_type_param_bound_mut(it)
     }
     if let Some(ref mut it) = _i.eq_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.spans)
     };
     if let Some(ref mut it) = _i.default {
         _visitor.visit_type_mut(it)
@@ -3098,7 +3224,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_paren_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeParen) {
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     _visitor.visit_type_mut(&mut *_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -3110,29 +3236,29 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_ptr_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypePtr) {
-    tokens_helper(_visitor, &mut (_i.star_token).0);
+    tokens_helper(_visitor, &mut _i.star_token.spans);
     if let Some(ref mut it) = _i.const_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_type_mut(&mut *_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_reference_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeReference) {
-    tokens_helper(_visitor, &mut (_i.and_token).0);
+    tokens_helper(_visitor, &mut _i.and_token.spans);
     if let Some(ref mut it) = _i.lifetime {
         _visitor.visit_lifetime_mut(it)
     };
     if let Some(ref mut it) = _i.mutability {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_type_mut(&mut *_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_slice_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeSlice) {
-    tokens_helper(_visitor, &mut (_i.bracket_token).0);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
     _visitor.visit_type_mut(&mut *_i.elem);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -3141,7 +3267,7 @@
     _i: &mut TypeTraitObject,
 ) {
     if let Some(ref mut it) = _i.dyn_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
         let it = el.value_mut();
@@ -3150,7 +3276,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_type_tuple_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeTuple) {
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.elems) {
         let it = el.value_mut();
         _visitor.visit_type_mut(it)
@@ -3164,23 +3290,23 @@
 pub fn visit_un_op_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut UnOp) {
     match *_i {
         UnOp::Deref(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         UnOp::Not(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
         UnOp::Neg(ref mut _binding_0) => {
-            tokens_helper(_visitor, &mut (_binding_0).0);
+            tokens_helper(_visitor, &mut _binding_0.spans);
         }
     }
 }
 #[cfg(feature = "full")]
 pub fn visit_use_glob_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut UseGlob) {
-    tokens_helper(_visitor, &mut (_i.star_token).0);
+    tokens_helper(_visitor, &mut _i.star_token.spans);
 }
 #[cfg(feature = "full")]
 pub fn visit_use_group_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut UseGroup) {
-    tokens_helper(_visitor, &mut (_i.brace_token).0);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.items) {
         let it = el.value_mut();
         _visitor.visit_use_tree_mut(it)
@@ -3193,13 +3319,13 @@
 #[cfg(feature = "full")]
 pub fn visit_use_path_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut UsePath) {
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.colon2_token).0);
+    tokens_helper(_visitor, &mut _i.colon2_token.spans);
     _visitor.visit_use_tree_mut(&mut *_i.tree);
 }
 #[cfg(feature = "full")]
 pub fn visit_use_rename_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut UseRename) {
     _visitor.visit_ident_mut(&mut _i.ident);
-    tokens_helper(_visitor, &mut (_i.as_token).0);
+    tokens_helper(_visitor, &mut _i.as_token.span);
     _visitor.visit_ident_mut(&mut _i.rename);
 }
 #[cfg(feature = "full")]
@@ -3230,24 +3356,24 @@
     _visitor.visit_ident_mut(&mut _i.ident);
     _visitor.visit_fields_mut(&mut _i.fields);
     if let Some(ref mut it) = _i.discriminant {
-        tokens_helper(_visitor, &mut ((it).0).0);
+        tokens_helper(_visitor, &mut (it).0.spans);
         _visitor.visit_expr_mut(&mut (it).1);
     };
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_vis_crate_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut VisCrate) {
-    tokens_helper(_visitor, &mut (_i.crate_token).0);
+    tokens_helper(_visitor, &mut _i.crate_token.span);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_vis_public_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut VisPublic) {
-    tokens_helper(_visitor, &mut (_i.pub_token).0);
+    tokens_helper(_visitor, &mut _i.pub_token.span);
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_vis_restricted_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut VisRestricted) {
-    tokens_helper(_visitor, &mut (_i.pub_token).0);
-    tokens_helper(_visitor, &mut (_i.paren_token).0);
+    tokens_helper(_visitor, &mut _i.pub_token.span);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
     if let Some(ref mut it) = _i.in_token {
-        tokens_helper(_visitor, &mut (it).0)
+        tokens_helper(_visitor, &mut it.span)
     };
     _visitor.visit_path_mut(&mut *_i.path);
 }
@@ -3268,7 +3394,7 @@
 }
 #[cfg(any(feature = "full", feature = "derive"))]
 pub fn visit_where_clause_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut WhereClause) {
-    tokens_helper(_visitor, &mut (_i.where_token).0);
+    tokens_helper(_visitor, &mut _i.where_token.span);
     for mut el in Punctuated::pairs_mut(&mut _i.predicates) {
         let it = el.value_mut();
         _visitor.visit_where_predicate_mut(it)
diff --git a/src/generics.rs b/src/generics.rs
index d1f4fa2..07ea86b 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -166,7 +166,6 @@
     type Item = &'a TypeParam;
 
     fn next(&mut self) -> Option<Self::Item> {
-        // FIXME: Remove this when ? on Option is stable
         let next = match self.0.next() {
             Some(item) => item,
             None => return None,
@@ -185,7 +184,6 @@
     type Item = &'a mut TypeParam;
 
     fn next(&mut self) -> Option<Self::Item> {
-        // FIXME: Remove this when ? on Option is stable
         let next = match self.0.next() {
             Some(item) => item,
             None => return None,
@@ -204,7 +202,6 @@
     type Item = &'a LifetimeDef;
 
     fn next(&mut self) -> Option<Self::Item> {
-        // FIXME: Remove this when ? on Option is stable
         let next = match self.0.next() {
             Some(item) => item,
             None => return None,
@@ -223,7 +220,6 @@
     type Item = &'a mut LifetimeDef;
 
     fn next(&mut self) -> Option<Self::Item> {
-        // FIXME: Remove this when ? on Option is stable
         let next = match self.0.next() {
             Some(item) => item,
             None => return None,
@@ -242,7 +238,6 @@
     type Item = &'a ConstParam;
 
     fn next(&mut self) -> Option<Self::Item> {
-        // FIXME: Remove this when ? on Option is stable
         let next = match self.0.next() {
             Some(item) => item,
             None => return None,
@@ -261,7 +256,6 @@
     type Item = &'a mut ConstParam;
 
     fn next(&mut self) -> Option<Self::Item> {
-        // FIXME: Remove this when ? on Option is stable
         let next = match self.0.next() {
             Some(item) => item,
             None => return None,
@@ -309,19 +303,22 @@
     /// ```
     /// # extern crate proc_macro2;
     /// # extern crate syn;
-    /// # #[macro_use]
     /// # extern crate quote;
+    /// #
     /// # use proc_macro2::{Span, Ident};
+    /// # use quote::quote;
+    /// #
     /// # fn main() {
-    /// # let generics: syn::Generics = Default::default();
-    /// # let name = Ident::new("MyType", Span::call_site());
+    /// #     let generics: syn::Generics = Default::default();
+    /// #     let name = Ident::new("MyType", Span::call_site());
+    /// #
     /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
     /// quote! {
     ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
     ///         // ...
     ///     }
     /// }
-    /// # ;
+    /// #     ;
     /// # }
     /// ```
     ///
@@ -468,7 +465,7 @@
         /// `"full"` feature.*
         pub Lifetime(PredicateLifetime {
             pub lifetime: Lifetime,
-            pub colon_token: Option<Token![:]>,
+            pub colon_token: Token![:],
             pub bounds: Punctuated<Lifetime, Token![+]>,
         }),
 
@@ -488,263 +485,380 @@
 pub mod parsing {
     use super::*;
 
-    use punctuated::Pair;
-    use synom::Synom;
+    use parse::{Parse, ParseStream, Result};
 
-    impl Synom for Generics {
-        named!(parse -> Self, map!(
-            alt!(
-                do_parse!(
-                    lt: punct!(<) >>
-                    lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
-                    ty_params: cond!(
-                        lifetimes.empty_or_trailing(),
-                        Punctuated::<TypeParam, Token![,]>::parse_terminated
-                    ) >>
-                    gt: punct!(>) >>
-                    (lifetimes, ty_params, Some(lt), Some(gt))
-                )
-                |
-                epsilon!() => { |_| (Punctuated::new(), None, None, None) }
-            ),
-            |(lifetimes, ty_params, lt, gt)| Generics {
-                lt_token: lt,
-                params: lifetimes.into_pairs()
-                    .map(Pair::into_tuple)
-                    .map(|(life, comma)| Pair::new(GenericParam::Lifetime(life), comma))
-                    .chain(ty_params.unwrap_or_default()
-                        .into_pairs()
-                        .map(Pair::into_tuple)
-                        .map(|(ty, comma)| Pair::new(GenericParam::Type(ty), comma)))
-                    .collect(),
-                gt_token: gt,
-                where_clause: None,
+    impl Parse for Generics {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let mut params = Punctuated::new();
+
+            if !input.peek(Token![<]) {
+                return Ok(Generics {
+                    lt_token: None,
+                    params: params,
+                    gt_token: None,
+                    where_clause: None,
+                });
             }
-        ));
 
-        fn description() -> Option<&'static str> {
-            Some("generic parameters in declaration")
-        }
-    }
+            let lt_token: Token![<] = input.parse()?;
 
-    impl Synom for GenericParam {
-        named!(parse -> Self, alt!(
-            syn!(TypeParam) => { GenericParam::Type }
-            |
-            syn!(LifetimeDef) => { GenericParam::Lifetime }
-            |
-            syn!(ConstParam) => { GenericParam::Const }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("generic parameter")
-        }
-    }
-
-    impl Synom for LifetimeDef {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            life: syn!(Lifetime) >>
-            colon: option!(punct!(:)) >>
-            bounds: cond!(
-                colon.is_some(),
-                Punctuated::parse_separated_nonempty
-            ) >>
-            (LifetimeDef {
-                attrs: attrs,
-                lifetime: life,
-                bounds: bounds.unwrap_or_default(),
-                colon_token: colon,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("lifetime definition")
-        }
-    }
-
-    impl Synom for BoundLifetimes {
-        named!(parse -> Self, do_parse!(
-            for_: keyword!(for) >>
-            lt: punct!(<) >>
-            lifetimes: call!(Punctuated::parse_terminated) >>
-            gt: punct!(>) >>
-            (BoundLifetimes {
-                for_token: for_,
-                lt_token: lt,
-                gt_token: gt,
-                lifetimes: lifetimes,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("bound lifetimes")
-        }
-    }
-
-    impl Synom for TypeParam {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            id: syn!(Ident) >>
-            colon: option!(punct!(:)) >>
-            bounds: cond!(
-                colon.is_some(),
-                Punctuated::parse_separated_nonempty
-            ) >>
-            default: option!(do_parse!(
-                eq: punct!(=) >>
-                ty: syn!(Type) >>
-                (eq, ty)
-            )) >>
-            (TypeParam {
-                attrs: attrs,
-                ident: id,
-                bounds: bounds.unwrap_or_default(),
-                colon_token: colon,
-                eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
-                default: default.map(|d| d.1),
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("type parameter")
-        }
-    }
-
-    impl Synom for TypeParamBound {
-        named!(parse -> Self, alt!(
-            syn!(Lifetime) => { TypeParamBound::Lifetime }
-            |
-            syn!(TraitBound) => { TypeParamBound::Trait }
-            |
-            parens!(syn!(TraitBound)) => {|(parens, mut bound)| {
-                bound.paren_token = Some(parens);
-                TypeParamBound::Trait(bound)
-            }}
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("type parameter bound")
-        }
-    }
-
-    impl Synom for TraitBound {
-        named!(parse -> Self, do_parse!(
-            modifier: syn!(TraitBoundModifier) >>
-            lifetimes: option!(syn!(BoundLifetimes)) >>
-            mut path: syn!(Path) >>
-            parenthesized: option!(cond_reduce!(
-                path.segments.last().unwrap().value().arguments.is_empty(),
-                syn!(ParenthesizedGenericArguments)
-            )) >>
-            ({
-                if let Some(parenthesized) = parenthesized {
-                    let parenthesized = PathArguments::Parenthesized(parenthesized);
-                    path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
+            let mut has_type_param = false;
+            loop {
+                if input.peek(Token![>]) {
+                    break;
                 }
-                TraitBound {
-                    paren_token: None,
-                    modifier: modifier,
-                    lifetimes: lifetimes,
-                    path: path,
+
+                let attrs = input.call(Attribute::parse_outer)?;
+                let lookahead = input.lookahead1();
+                if !has_type_param && lookahead.peek(Lifetime) {
+                    params.push_value(GenericParam::Lifetime(LifetimeDef {
+                        attrs: attrs,
+                        ..input.parse()?
+                    }));
+                } else if lookahead.peek(Ident) {
+                    has_type_param = true;
+                    params.push_value(GenericParam::Type(TypeParam {
+                        attrs: attrs,
+                        ..input.parse()?
+                    }));
+                } else {
+                    return Err(lookahead.error());
                 }
+
+                if input.peek(Token![>]) {
+                    break;
+                }
+                let punct = input.parse()?;
+                params.push_punct(punct);
+            }
+
+            let gt_token: Token![>] = input.parse()?;
+
+            Ok(Generics {
+                lt_token: Some(lt_token),
+                params: params,
+                gt_token: Some(gt_token),
+                where_clause: None,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("trait bound")
         }
     }
 
-    impl Synom for TraitBoundModifier {
-        named!(parse -> Self, alt!(
-            punct!(?) => { TraitBoundModifier::Maybe }
-            |
-            epsilon!() => { |_| TraitBoundModifier::None }
-        ));
+    impl Parse for GenericParam {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
 
-        fn description() -> Option<&'static str> {
-            Some("trait bound modifier")
-        }
-    }
-
-    impl Synom for ConstParam {
-        named!(parse -> Self, do_parse!(
-            attrs: many0!(Attribute::parse_outer) >>
-            const_: keyword!(const) >>
-            ident: syn!(Ident) >>
-            colon: punct!(:) >>
-            ty: syn!(Type) >>
-            eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
-            ({
-                let (eq_token, default) = match eq_def {
-                    Some((eq_token, default)) => (Some(eq_token), Some(default)),
-                    None => (None, None),
-                };
-                ConstParam {
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Ident) {
+                Ok(GenericParam::Type(TypeParam {
                     attrs: attrs,
-                    const_token: const_,
-                    ident: ident,
-                    colon_token: colon,
-                    ty: ty,
-                    eq_token: eq_token,
-                    default: default,
-                }
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("generic `const` parameter")
+                    ..input.parse()?
+                }))
+            } else if lookahead.peek(Lifetime) {
+                Ok(GenericParam::Lifetime(LifetimeDef {
+                    attrs: attrs,
+                    ..input.parse()?
+                }))
+            } else if lookahead.peek(Token![const]) {
+                Ok(GenericParam::Const(ConstParam {
+                    attrs: attrs,
+                    ..input.parse()?
+                }))
+            } else {
+                Err(lookahead.error())
+            }
         }
     }
 
-    impl Synom for WhereClause {
-        named!(parse -> Self, do_parse!(
-            where_: keyword!(where) >>
-            predicates: call!(Punctuated::parse_terminated) >>
-            (WhereClause {
-                predicates: predicates,
-                where_token: where_,
+    impl Parse for LifetimeDef {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let has_colon;
+            Ok(LifetimeDef {
+                attrs: input.call(Attribute::parse_outer)?,
+                lifetime: input.parse()?,
+                colon_token: {
+                    if input.peek(Token![:]) {
+                        has_colon = true;
+                        Some(input.parse()?)
+                    } else {
+                        has_colon = false;
+                        None
+                    }
+                },
+                bounds: {
+                    let mut bounds = Punctuated::new();
+                    if has_colon {
+                        loop {
+                            if input.peek(Token![,]) || input.peek(Token![>]) {
+                                break;
+                            }
+                            let value = input.parse()?;
+                            bounds.push_value(value);
+                            if !input.peek(Token![+]) {
+                                break;
+                            }
+                            let punct = input.parse()?;
+                            bounds.push_punct(punct);
+                        }
+                    }
+                    bounds
+                },
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("where clause")
         }
     }
 
-    impl Synom for WherePredicate {
-        named!(parse -> Self, alt!(
-            do_parse!(
-                ident: syn!(Lifetime) >>
-                colon: option!(punct!(:)) >>
-                bounds: cond!(
-                    colon.is_some(),
-                    Punctuated::parse_separated
-                ) >>
-                (WherePredicate::Lifetime(PredicateLifetime {
-                    lifetime: ident,
-                    bounds: bounds.unwrap_or_default(),
-                    colon_token: colon,
-                }))
-            )
-            |
-            do_parse!(
-                lifetimes: option!(syn!(BoundLifetimes)) >>
-                bounded_ty: syn!(Type) >>
-                colon: punct!(:) >>
-                bounds: call!(Punctuated::parse_separated_nonempty) >>
-                (WherePredicate::Type(PredicateType {
-                    lifetimes: lifetimes,
-                    bounded_ty: bounded_ty,
-                    bounds: bounds,
-                    colon_token: colon,
-                }))
-            )
-        ));
+    impl Parse for BoundLifetimes {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(BoundLifetimes {
+                for_token: input.parse()?,
+                lt_token: input.parse()?,
+                lifetimes: {
+                    let mut lifetimes = Punctuated::new();
+                    while !input.peek(Token![>]) {
+                        lifetimes.push_value(input.parse()?);
+                        if input.peek(Token![>]) {
+                            break;
+                        }
+                        lifetimes.push_punct(input.parse()?);
+                    }
+                    lifetimes
+                },
+                gt_token: input.parse()?,
+            })
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("predicate in where clause")
+    impl Parse for Option<BoundLifetimes> {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![for]) {
+                input.parse().map(Some)
+            } else {
+                Ok(None)
+            }
+        }
+    }
+
+    impl Parse for TypeParam {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let has_colon;
+            let has_default;
+            Ok(TypeParam {
+                attrs: input.call(Attribute::parse_outer)?,
+                ident: input.parse()?,
+                colon_token: {
+                    if input.peek(Token![:]) {
+                        has_colon = true;
+                        Some(input.parse()?)
+                    } else {
+                        has_colon = false;
+                        None
+                    }
+                },
+                bounds: {
+                    let mut bounds = Punctuated::new();
+                    if has_colon {
+                        loop {
+                            if input.peek(Token![,]) || input.peek(Token![>]) {
+                                break;
+                            }
+                            let value = input.parse()?;
+                            bounds.push_value(value);
+                            if !input.peek(Token![+]) {
+                                break;
+                            }
+                            let punct = input.parse()?;
+                            bounds.push_punct(punct);
+                        }
+                    }
+                    bounds
+                },
+                eq_token: {
+                    if input.peek(Token![=]) {
+                        has_default = true;
+                        Some(input.parse()?)
+                    } else {
+                        has_default = false;
+                        None
+                    }
+                },
+                default: {
+                    if has_default {
+                        Some(input.parse()?)
+                    } else {
+                        None
+                    }
+                },
+            })
+        }
+    }
+
+    impl Parse for TypeParamBound {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Lifetime) {
+                return input.parse().map(TypeParamBound::Lifetime);
+            }
+
+            if input.peek(token::Paren) {
+                let content;
+                let paren_token = parenthesized!(content in input);
+                let mut bound: TraitBound = content.parse()?;
+                bound.paren_token = Some(paren_token);
+                return Ok(TypeParamBound::Trait(bound));
+            }
+
+            input.parse().map(TypeParamBound::Trait)
+        }
+    }
+
+    impl Parse for TraitBound {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let modifier: TraitBoundModifier = input.parse()?;
+            let lifetimes: Option<BoundLifetimes> = input.parse()?;
+
+            let mut path: Path = input.parse()?;
+            if path.segments.last().unwrap().value().arguments.is_empty()
+                && input.peek(token::Paren)
+            {
+                let parenthesized = PathArguments::Parenthesized(input.parse()?);
+                path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
+            }
+
+            Ok(TraitBound {
+                paren_token: None,
+                modifier: modifier,
+                lifetimes: lifetimes,
+                path: path,
+            })
+        }
+    }
+
+    impl Parse for TraitBoundModifier {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![?]) {
+                input.parse().map(TraitBoundModifier::Maybe)
+            } else {
+                Ok(TraitBoundModifier::None)
+            }
+        }
+    }
+
+    impl Parse for ConstParam {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let mut default = None;
+            Ok(ConstParam {
+                attrs: input.call(Attribute::parse_outer)?,
+                const_token: input.parse()?,
+                ident: input.parse()?,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+                eq_token: {
+                    if input.peek(Token![=]) {
+                        let eq_token = input.parse()?;
+                        default = Some(input.parse::<Expr>()?);
+                        Some(eq_token)
+                    } else {
+                        None
+                    }
+                },
+                default: default,
+            })
+        }
+    }
+
+    impl Parse for WhereClause {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(WhereClause {
+                where_token: input.parse()?,
+                predicates: {
+                    let mut predicates = Punctuated::new();
+                    loop {
+                        if input.peek(token::Brace)
+                            || input.peek(Token![,])
+                            || input.peek(Token![;])
+                            || input.peek(Token![:]) && !input.peek(Token![::])
+                            || input.peek(Token![=])
+                        {
+                            break;
+                        }
+                        let value = input.parse()?;
+                        predicates.push_value(value);
+                        if !input.peek(Token![,]) {
+                            break;
+                        }
+                        let punct = input.parse()?;
+                        predicates.push_punct(punct);
+                    }
+                    predicates
+                },
+            })
+        }
+    }
+
+    impl Parse for Option<WhereClause> {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![where]) {
+                input.parse().map(Some)
+            } else {
+                Ok(None)
+            }
+        }
+    }
+
+    impl Parse for WherePredicate {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Lifetime) && input.peek2(Token![:]) {
+                Ok(WherePredicate::Lifetime(PredicateLifetime {
+                    lifetime: input.parse()?,
+                    colon_token: input.parse()?,
+                    bounds: {
+                        let mut bounds = Punctuated::new();
+                        loop {
+                            if input.peek(token::Brace)
+                                || input.peek(Token![,])
+                                || input.peek(Token![;])
+                                || input.peek(Token![:])
+                                || input.peek(Token![=])
+                            {
+                                break;
+                            }
+                            let value = input.parse()?;
+                            bounds.push_value(value);
+                            if !input.peek(Token![+]) {
+                                break;
+                            }
+                            let punct = input.parse()?;
+                            bounds.push_punct(punct);
+                        }
+                        bounds
+                    },
+                }))
+            } else {
+                Ok(WherePredicate::Type(PredicateType {
+                    lifetimes: input.parse()?,
+                    bounded_ty: input.parse()?,
+                    colon_token: input.parse()?,
+                    bounds: {
+                        let mut bounds = Punctuated::new();
+                        loop {
+                            if input.peek(token::Brace)
+                                || input.peek(Token![,])
+                                || input.peek(Token![;])
+                                || input.peek(Token![:]) && !input.peek(Token![::])
+                                || input.peek(Token![=])
+                            {
+                                break;
+                            }
+                            let value = input.parse()?;
+                            bounds.push_value(value);
+                            if !input.peek(Token![+]) {
+                                break;
+                            }
+                            let punct = input.parse()?;
+                            bounds.push_punct(punct);
+                        }
+                        bounds
+                    },
+                }))
+            }
         }
     }
 }
@@ -752,10 +866,13 @@
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
-    use attr::FilterAttrs;
+
     use proc_macro2::TokenStream;
     use quote::{ToTokens, TokenStreamExt};
 
+    use attr::FilterAttrs;
+    use print::TokensOrDefault;
+
     impl ToTokens for Generics {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             if self.params.is_empty() {
@@ -998,10 +1115,8 @@
     impl ToTokens for PredicateLifetime {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             self.lifetime.to_tokens(tokens);
-            if !self.bounds.is_empty() {
-                TokensOrDefault(&self.colon_token).to_tokens(tokens);
-                self.bounds.to_tokens(tokens);
-            }
+            self.colon_token.to_tokens(tokens);
+            self.bounds.to_tokens(tokens);
         }
     }
 
diff --git a/src/group.rs b/src/group.rs
new file mode 100644
index 0000000..b2e4659
--- /dev/null
+++ b/src/group.rs
@@ -0,0 +1,289 @@
+use proc_macro2::{Delimiter, Span};
+
+use error::Result;
+use parse::{ParseBuffer, ParseStream};
+use private;
+use token;
+
+// Not public API.
+#[doc(hidden)]
+pub struct Parens<'a> {
+    pub token: token::Paren,
+    pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[doc(hidden)]
+pub struct Braces<'a> {
+    pub token: token::Brace,
+    pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[doc(hidden)]
+pub struct Brackets<'a> {
+    pub token: token::Bracket,
+    pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[cfg(any(feature = "full", feature = "derive"))]
+#[doc(hidden)]
+pub struct Group<'a> {
+    pub token: token::Group,
+    pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse_parens(input: ParseStream) -> Result<Parens> {
+    parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
+        token: token::Paren(span),
+        content: content,
+    })
+}
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse_braces(input: ParseStream) -> Result<Braces> {
+    parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
+        token: token::Brace(span),
+        content: content,
+    })
+}
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse_brackets(input: ParseStream) -> Result<Brackets> {
+    parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
+        token: token::Bracket(span),
+        content: content,
+    })
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+impl private {
+    pub fn parse_group(input: ParseStream) -> Result<Group> {
+        parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
+            token: token::Group(span),
+            content: content,
+        })
+    }
+}
+
+fn parse_delimited(input: ParseStream, delimiter: Delimiter) -> Result<(Span, ParseBuffer)> {
+    input.step(|cursor| {
+        if let Some((content, span, rest)) = cursor.group(delimiter) {
+            let unexpected = private::get_unexpected(input);
+            let nested = private::advance_step_cursor(cursor, content);
+            let content = private::new_parse_buffer(span, nested, unexpected);
+            Ok(((span, content), rest))
+        } else {
+            let message = match delimiter {
+                Delimiter::Parenthesis => "expected parentheses",
+                Delimiter::Brace => "expected curly braces",
+                Delimiter::Bracket => "expected square brackets",
+                Delimiter::None => "expected invisible group",
+            };
+            Err(cursor.error(message))
+        }
+    })
+}
+
+/// Parse a set of parentheses and expose their content to subsequent parsers.
+///
+/// # Example
+///
+/// ```rust
+/// # extern crate quote;
+/// # extern crate syn;
+/// #
+/// # use quote::quote;
+/// #
+/// use syn::{parenthesized, token, Ident, Token, Type};
+/// use syn::parse::{Parse, ParseStream, Result};
+/// use syn::punctuated::Punctuated;
+///
+/// // Parse a simplified tuple struct syntax like:
+/// //
+/// //     struct S(A, B);
+/// struct TupleStruct {
+///     struct_token: Token![struct],
+///     ident: Ident,
+///     paren_token: token::Paren,
+///     fields: Punctuated<Type, Token![,]>,
+///     semi_token: Token![;],
+/// }
+///
+/// impl Parse for TupleStruct {
+///     fn parse(input: ParseStream) -> Result<Self> {
+///         let content;
+///         Ok(TupleStruct {
+///             struct_token: input.parse()?,
+///             ident: input.parse()?,
+///             paren_token: parenthesized!(content in input),
+///             fields: content.parse_terminated(Type::parse)?,
+///             semi_token: input.parse()?,
+///         })
+///     }
+/// }
+/// #
+/// # fn main() {
+/// #     let input = quote! {
+/// #         struct S(A, B);
+/// #     };
+/// #     syn::parse2::<TupleStruct>(input).unwrap();
+/// # }
+/// ```
+#[macro_export]
+macro_rules! parenthesized {
+    ($content:ident in $cursor:expr) => {
+        match $crate::group::parse_parens(&$cursor) {
+            $crate::export::Ok(parens) => {
+                $content = parens.content;
+                parens.token
+            }
+            $crate::export::Err(error) => {
+                return $crate::export::Err(error);
+            }
+        }
+    };
+}
+
+/// Parse a set of curly braces and expose their content to subsequent parsers.
+///
+/// # Example
+///
+/// ```rust
+/// # extern crate quote;
+/// # extern crate syn;
+/// #
+/// # use quote::quote;
+/// #
+/// use syn::{braced, token, Ident, Token, Type};
+/// use syn::parse::{Parse, ParseStream, Result};
+/// use syn::punctuated::Punctuated;
+///
+/// // Parse a simplified struct syntax like:
+/// //
+/// //     struct S {
+/// //         a: A,
+/// //         b: B,
+/// //     }
+/// struct Struct {
+///     struct_token: Token![struct],
+///     ident: Ident,
+///     brace_token: token::Brace,
+///     fields: Punctuated<Field, Token![,]>,
+/// }
+///
+/// struct Field {
+///     name: Ident,
+///     colon_token: Token![:],
+///     ty: Type,
+/// }
+///
+/// impl Parse for Struct {
+///     fn parse(input: ParseStream) -> Result<Self> {
+///         let content;
+///         Ok(Struct {
+///             struct_token: input.parse()?,
+///             ident: input.parse()?,
+///             brace_token: braced!(content in input),
+///             fields: content.parse_terminated(Field::parse)?,
+///         })
+///     }
+/// }
+///
+/// impl Parse for Field {
+///     fn parse(input: ParseStream) -> Result<Self> {
+///         Ok(Field {
+///             name: input.parse()?,
+///             colon_token: input.parse()?,
+///             ty: input.parse()?,
+///         })
+///     }
+/// }
+/// #
+/// # fn main() {
+/// #     let input = quote! {
+/// #         struct S {
+/// #             a: A,
+/// #             b: B,
+/// #         }
+/// #     };
+/// #     syn::parse2::<Struct>(input).unwrap();
+/// # }
+/// ```
+#[macro_export]
+macro_rules! braced {
+    ($content:ident in $cursor:expr) => {
+        match $crate::group::parse_braces(&$cursor) {
+            $crate::export::Ok(braces) => {
+                $content = braces.content;
+                braces.token
+            }
+            $crate::export::Err(error) => {
+                return $crate::export::Err(error);
+            }
+        }
+    };
+}
+
+/// Parse a set of square brackets and expose their content to subsequent
+/// parsers.
+///
+/// # Example
+///
+/// ```rust
+/// # extern crate proc_macro2;
+/// # extern crate quote;
+/// # extern crate syn;
+/// #
+/// # use quote::quote;
+/// #
+/// use proc_macro2::TokenStream;
+/// use syn::{bracketed, token, Token};
+/// use syn::parse::{Parse, ParseStream, Result};
+///
+/// // Parse an outer attribute like:
+/// //
+/// //     #[repr(C, packed)]
+/// struct OuterAttribute {
+///     pound_token: Token![#],
+///     bracket_token: token::Bracket,
+///     content: TokenStream,
+/// }
+///
+/// impl Parse for OuterAttribute {
+///     fn parse(input: ParseStream) -> Result<Self> {
+///         let content;
+///         Ok(OuterAttribute {
+///             pound_token: input.parse()?,
+///             bracket_token: bracketed!(content in input),
+///             content: content.parse()?,
+///         })
+///     }
+/// }
+/// #
+/// # fn main() {
+/// #     let input = quote! {
+/// #         #[repr(C, packed)]
+/// #     };
+/// #     syn::parse2::<OuterAttribute>(input).unwrap();
+/// # }
+/// ```
+#[macro_export]
+macro_rules! bracketed {
+    ($content:ident in $cursor:expr) => {
+        match $crate::group::parse_brackets(&$cursor) {
+            $crate::export::Ok(brackets) => {
+                $content = brackets.content;
+                brackets.token
+            }
+            $crate::export::Err(error) => {
+                return $crate::export::Err(error);
+            }
+        }
+    };
+}
diff --git a/src/ident.rs b/src/ident.rs
new file mode 100644
index 0000000..368b0c3
--- /dev/null
+++ b/src/ident.rs
@@ -0,0 +1,37 @@
+#[cfg(feature = "parsing")]
+use lookahead;
+#[cfg(feature = "parsing")]
+use parse::{Parse, ParseStream, Result};
+
+pub use proc_macro2::Ident;
+
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+#[allow(non_snake_case)]
+pub fn Ident(marker: lookahead::TokenMarker) -> Ident {
+    match marker {}
+}
+
+#[cfg(feature = "parsing")]
+impl Parse for Ident {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| {
+            if let Some((ident, rest)) = cursor.ident() {
+                match ident.to_string().as_str() {
+                    "_"
+                    // Based on https://doc.rust-lang.org/grammar.html#keywords
+                    // and https://github.com/rust-lang/rfcs/blob/master/text/2421-unreservations-2018.md
+                    | "abstract" | "as" | "become" | "box" | "break" | "const"
+                    | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
+                    | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
+                    | "mod" | "move" | "mut" | "override" | "priv" | "proc" | "pub"
+                    | "ref" | "return" | "Self" | "self" | "static" | "struct"
+                    | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
+                    | "virtual" | "where" | "while" | "yield" => {}
+                    _ => return Ok((ident, rest)),
+                }
+            }
+            Err(cursor.error("expected identifier"))
+        })
+    }
+}
diff --git a/src/item.rs b/src/item.rs
index 7e49a4a..c31bb9c 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -93,6 +93,7 @@
             pub vis: Visibility,
             pub constness: Option<Token![const]>,
             pub unsafety: Option<Token![unsafe]>,
+            pub asyncness: Option<Token![async]>,
             pub abi: Option<Abi>,
             pub ident: Ident,
             pub decl: Box<FnDecl>,
@@ -135,6 +136,21 @@
             pub semi_token: Token![;],
         }),
 
+        /// An existential type: `existential type Iter: Iterator<Item = u8>`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Existential(ItemExistential {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub existential_token: Token![existential],
+            pub type_token: Token![type],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub colon_token: Option<Token![:]>,
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+            pub semi_token: Token![;],
+        }),
+
         /// A struct definition: `struct Foo<A> { x: A }`.
         ///
         /// *This type is available if Syn is built with the `"full"` feature.*
@@ -190,6 +206,20 @@
             pub items: Vec<TraitItem>,
         }),
 
+        /// A trait alias: `pub trait SharableIterator = Iterator + Sync`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub TraitAlias(ItemTraitAlias {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub trait_token: Token![trait],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub eq_token: Token![=],
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+            pub semi_token: Token![;],
+        }),
+
         /// An impl block providing trait or associated items: `impl<A> Trait
         /// for Data<A> { ... }`.
         ///
@@ -429,6 +459,15 @@
             pub semi_token: Token![;],
         }),
 
+        /// A macro invocation within an extern block.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Macro(ForeignItemMacro {
+            pub attrs: Vec<Attribute>,
+            pub mac: Macro,
+            pub semi_token: Option<Token![;]>,
+        }),
+
         /// Tokens in an `extern` block not interpreted by Syn.
         ///
         /// *This type is available if Syn is built with the `"full"` feature.*
@@ -597,6 +636,20 @@
             pub semi_token: Token![;],
         }),
 
+        /// An existential type within an impl block.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Existential(ImplItemExistential {
+            pub attrs: Vec<Attribute>,
+            pub existential_token: Token![existential],
+            pub type_token: Token![type],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub colon_token: Option<Token![:]>,
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+            pub semi_token: Token![;],
+        }),
+
         /// A macro invocation within an impl block.
         ///
         /// *This type is available if Syn is built with the `"full"` feature.*
@@ -643,6 +696,7 @@
     pub struct MethodSig {
         pub constness: Option<Token![const]>,
         pub unsafety: Option<Token![unsafe]>,
+        pub asyncness: Option<Token![async]>,
         pub abi: Option<Abi>,
         pub ident: Ident,
         pub decl: FnDecl,
@@ -714,681 +768,861 @@
 pub mod parsing {
     use super::*;
 
-    use synom::Synom;
+    use ext::IdentExt;
+    use parse::{Parse, ParseStream, Result};
 
-    impl_synom!(Item "item" alt!(
-        syn!(ItemExternCrate) => { Item::ExternCrate }
-        |
-        syn!(ItemUse) => { Item::Use }
-        |
-        syn!(ItemStatic) => { Item::Static }
-        |
-        syn!(ItemConst) => { Item::Const }
-        |
-        syn!(ItemFn) => { Item::Fn }
-        |
-        call!(unstable_async_fn) => { Item::Verbatim }
-        |
-        syn!(ItemMod) => { Item::Mod }
-        |
-        syn!(ItemForeignMod) => { Item::ForeignMod }
-        |
-        syn!(ItemType) => { Item::Type }
-        |
-        call!(unstable_existential_type) => { Item::Verbatim }
-        |
-        syn!(ItemStruct) => { Item::Struct }
-        |
-        syn!(ItemEnum) => { Item::Enum }
-        |
-        syn!(ItemUnion) => { Item::Union }
-        |
-        syn!(ItemTrait) => { Item::Trait }
-        |
-        syn!(ItemImpl) => { Item::Impl }
-        |
-        syn!(ItemMacro) => { Item::Macro }
-        |
-        syn!(ItemMacro2) => { Item::Macro2 }
-    ));
+    impl Parse for Item {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let ahead = input.fork();
+            ahead.call(Attribute::parse_outer)?;
+            let vis: Visibility = ahead.parse()?;
 
-    impl_synom!(ItemMacro "macro item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        what: call!(Path::parse_mod_style) >>
-        bang: punct!(!) >>
-        ident: option!(syn!(Ident)) >>
-        body: call!(tt::delimited) >>
-        semi: cond!(!is_brace(&body.0), punct!(;)) >>
-        (ItemMacro {
-            attrs: attrs,
-            ident: ident,
-            mac: Macro {
-                path: what,
-                bang_token: bang,
-                delimiter: body.0,
-                tts: body.1,
-            },
-            semi_token: semi,
-        })
-    ));
-
-    // TODO: figure out the actual grammar; is body required to be braced?
-    impl_synom!(ItemMacro2 "macro2 item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        macro_: keyword!(macro) >>
-        ident: syn!(Ident) >>
-        args: call!(tt::parenthesized) >>
-        body: call!(tt::braced) >>
-        (ItemMacro2 {
-            attrs: attrs,
-            vis: vis,
-            macro_token: macro_,
-            ident: ident,
-            paren_token: args.0,
-            args: args.1,
-            brace_token: body.0,
-            body: body.1,
-        })
-    ));
-
-    impl_synom!(ItemExternCrate "extern crate item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        extern_: keyword!(extern) >>
-        crate_: keyword!(crate) >>
-        ident: syn!(Ident) >>
-        rename: option!(tuple!(keyword!(as), syn!(Ident))) >>
-        semi: punct!(;) >>
-        (ItemExternCrate {
-            attrs: attrs,
-            vis: vis,
-            extern_token: extern_,
-            crate_token: crate_,
-            ident: ident,
-            rename: rename,
-            semi_token: semi,
-        })
-    ));
-
-    impl_synom!(ItemUse "use item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        use_: keyword!(use) >>
-        leading_colon: option!(punct!(::)) >>
-        tree: syn!(UseTree) >>
-        semi: punct!(;) >>
-        (ItemUse {
-            attrs: attrs,
-            vis: vis,
-            use_token: use_,
-            leading_colon: leading_colon,
-            tree: tree,
-            semi_token: semi,
-        })
-    ));
-
-    named!(use_element -> Ident, alt!(
-        syn!(Ident)
-        |
-        keyword!(self) => { Into::into }
-        |
-        keyword!(super) => { Into::into }
-        |
-        keyword!(crate) => { Into::into }
-        |
-        keyword!(extern) => { Into::into }
-    ));
-
-    impl_synom!(UseTree "use tree" alt!(
-        syn!(UseRename) => { UseTree::Rename }
-        |
-        syn!(UsePath) => { UseTree::Path }
-        |
-        syn!(UseName) => { UseTree::Name }
-        |
-        syn!(UseGlob) => { UseTree::Glob }
-        |
-        syn!(UseGroup) => { UseTree::Group }
-    ));
-
-    impl_synom!(UsePath "use path" do_parse!(
-        ident: call!(use_element) >>
-        colon2_token: punct!(::) >>
-        tree: syn!(UseTree) >>
-        (UsePath {
-            ident: ident,
-            colon2_token: colon2_token,
-            tree: Box::new(tree),
-        })
-    ));
-
-    impl_synom!(UseName "use name" do_parse!(
-        ident: call!(use_element) >>
-        (UseName {
-            ident: ident,
-        })
-    ));
-
-    impl_synom!(UseRename "use rename" do_parse!(
-        ident: call!(use_element) >>
-        as_token: keyword!(as) >>
-        rename: syn!(Ident) >>
-        (UseRename {
-            ident: ident,
-            as_token: as_token,
-            rename: rename,
-        })
-    ));
-
-    impl_synom!(UseGlob "use glob" do_parse!(
-        star: punct!(*) >>
-        (UseGlob {
-            star_token: star,
-        })
-    ));
-
-    impl_synom!(UseGroup "use group" do_parse!(
-        list: braces!(Punctuated::parse_terminated) >>
-        (UseGroup {
-            brace_token: list.0,
-            items: list.1,
-        })
-    ));
-
-    impl_synom!(ItemStatic "static item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        static_: keyword!(static) >>
-        mutability: option!(keyword!(mut)) >>
-        ident: syn!(Ident) >>
-        colon: punct!(:) >>
-        ty: syn!(Type) >>
-        eq: punct!(=) >>
-        value: syn!(Expr) >>
-        semi: punct!(;) >>
-        (ItemStatic {
-            attrs: attrs,
-            vis: vis,
-            static_token: static_,
-            mutability: mutability,
-            ident: ident,
-            colon_token: colon,
-            ty: Box::new(ty),
-            eq_token: eq,
-            expr: Box::new(value),
-            semi_token: semi,
-        })
-    ));
-
-    impl_synom!(ItemConst "const item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        const_: keyword!(const) >>
-        ident: syn!(Ident) >>
-        colon: punct!(:) >>
-        ty: syn!(Type) >>
-        eq: punct!(=) >>
-        value: syn!(Expr) >>
-        semi: punct!(;) >>
-        (ItemConst {
-            attrs: attrs,
-            vis: vis,
-            const_token: const_,
-            ident: ident,
-            colon_token: colon,
-            ty: Box::new(ty),
-            eq_token: eq,
-            expr: Box::new(value),
-            semi_token: semi,
-        })
-    ));
-
-    impl_synom!(ItemFn "fn item" do_parse!(
-        outer_attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        constness: option!(keyword!(const)) >>
-        unsafety: option!(keyword!(unsafe)) >>
-        abi: option!(syn!(Abi)) >>
-        fn_: keyword!(fn) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        inputs: parens!(Punctuated::parse_terminated) >>
-        ret: syn!(ReturnType) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        inner_attrs_stmts: braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            call!(Block::parse_within),
-        )) >>
-        (ItemFn {
-            attrs: {
-                let mut attrs = outer_attrs;
-                attrs.extend((inner_attrs_stmts.1).0);
-                attrs
-            },
-            vis: vis,
-            constness: constness,
-            unsafety: unsafety,
-            abi: abi,
-            decl: Box::new(FnDecl {
-                fn_token: fn_,
-                paren_token: inputs.0,
-                inputs: inputs.1,
-                output: ret,
-                variadic: None,
-                generics: Generics {
-                    where_clause: where_clause,
-                    ..generics
-                },
-            }),
-            ident: ident,
-            block: Box::new(Block {
-                brace_token: inner_attrs_stmts.0,
-                stmts: (inner_attrs_stmts.1).1,
-            }),
-        })
-    ));
-
-    named!(unstable_async_fn -> ItemVerbatim, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        many0!(Attribute::parse_outer) >>
-        syn!(Visibility) >>
-        option!(keyword!(const)) >>
-        option!(keyword!(unsafe)) >>
-        keyword!(async) >>
-        option!(syn!(Abi)) >>
-        keyword!(fn) >>
-        syn!(Ident) >>
-        syn!(Generics) >>
-        parens!(Punctuated::<FnArg, Token![,]>::parse_terminated) >>
-        syn!(ReturnType) >>
-        option!(syn!(WhereClause)) >>
-        braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            call!(Block::parse_within),
-        )) >>
-        end: call!(verbatim::grab_cursor) >>
-        (ItemVerbatim {
-            tts: verbatim::token_range(begin..end),
-        })
-    ));
-
-    impl Synom for FnArg {
-        named!(parse -> Self, alt!(
-            do_parse!(
-                and: punct!(&) >>
-                lt: option!(syn!(Lifetime)) >>
-                mutability: option!(keyword!(mut)) >>
-                self_: keyword!(self) >>
-                not!(punct!(:)) >>
-                (ArgSelfRef {
-                    lifetime: lt,
-                    mutability: mutability,
-                    and_token: and,
-                    self_token: self_,
-                }.into())
-            )
-            |
-            do_parse!(
-                mutability: option!(keyword!(mut)) >>
-                self_: keyword!(self) >>
-                not!(punct!(:)) >>
-                (ArgSelf {
-                    mutability: mutability,
-                    self_token: self_,
-                }.into())
-            )
-            |
-            do_parse!(
-                pat: syn!(Pat) >>
-                colon: punct!(:) >>
-                ty: syn!(Type) >>
-                (ArgCaptured {
-                    pat: pat,
-                    ty: ty,
-                    colon_token: colon,
-                }.into())
-            )
-            |
-            syn!(Type) => { FnArg::Ignored }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("function argument")
+            let lookahead = ahead.lookahead1();
+            if lookahead.peek(Token![extern]) {
+                ahead.parse::<Token![extern]>()?;
+                let lookahead = ahead.lookahead1();
+                if lookahead.peek(Token![crate]) {
+                    input.parse().map(Item::ExternCrate)
+                } else if lookahead.peek(Token![fn]) {
+                    input.parse().map(Item::Fn)
+                } else if lookahead.peek(token::Brace) {
+                    input.parse().map(Item::ForeignMod)
+                } else if lookahead.peek(LitStr) {
+                    ahead.parse::<LitStr>()?;
+                    let lookahead = ahead.lookahead1();
+                    if lookahead.peek(token::Brace) {
+                        input.parse().map(Item::ForeignMod)
+                    } else if lookahead.peek(Token![fn]) {
+                        input.parse().map(Item::Fn)
+                    } else {
+                        Err(lookahead.error())
+                    }
+                } else {
+                    Err(lookahead.error())
+                }
+            } else if lookahead.peek(Token![use]) {
+                input.parse().map(Item::Use)
+            } else if lookahead.peek(Token![static]) {
+                input.parse().map(Item::Static)
+            } else if lookahead.peek(Token![const]) {
+                ahead.parse::<Token![const]>()?;
+                let lookahead = ahead.lookahead1();
+                if lookahead.peek(Ident) {
+                    input.parse().map(Item::Const)
+                } else if lookahead.peek(Token![unsafe])
+                    || lookahead.peek(Token![async])
+                    || lookahead.peek(Token![extern])
+                    || lookahead.peek(Token![fn])
+                {
+                    input.parse().map(Item::Fn)
+                } else {
+                    Err(lookahead.error())
+                }
+            } else if lookahead.peek(Token![unsafe]) {
+                ahead.parse::<Token![unsafe]>()?;
+                let lookahead = ahead.lookahead1();
+                if lookahead.peek(Token![trait])
+                    || lookahead.peek(Token![auto]) && ahead.peek2(Token![trait])
+                {
+                    input.parse().map(Item::Trait)
+                } else if lookahead.peek(Token![impl ]) {
+                    input.parse().map(Item::Impl)
+                } else if lookahead.peek(Token![async])
+                    || lookahead.peek(Token![extern])
+                    || lookahead.peek(Token![fn])
+                {
+                    input.parse().map(Item::Fn)
+                } else {
+                    Err(lookahead.error())
+                }
+            } else if lookahead.peek(Token![async]) || lookahead.peek(Token![fn]) {
+                input.parse().map(Item::Fn)
+            } else if lookahead.peek(Token![mod]) {
+                input.parse().map(Item::Mod)
+            } else if lookahead.peek(Token![type]) {
+                input.parse().map(Item::Type)
+            } else if lookahead.peek(Token![existential]) {
+                input.parse().map(Item::Existential)
+            } else if lookahead.peek(Token![struct]) {
+                input.parse().map(Item::Struct)
+            } else if lookahead.peek(Token![enum]) {
+                input.parse().map(Item::Enum)
+            } else if lookahead.peek(Token![union]) && ahead.peek2(Ident) {
+                input.parse().map(Item::Union)
+            } else if lookahead.peek(Token![trait])
+                || lookahead.peek(Token![auto]) && ahead.peek2(Token![trait])
+            {
+                input.parse().map(Item::Trait)
+            } else if lookahead.peek(Token![impl ])
+                || lookahead.peek(Token![default]) && !ahead.peek2(Token![!])
+            {
+                input.parse().map(Item::Impl)
+            } else if lookahead.peek(Token![macro]) {
+                input.parse().map(Item::Macro2)
+            } else if vis.is_inherited()
+                && (lookahead.peek(Ident)
+                    || lookahead.peek(Token![self])
+                    || lookahead.peek(Token![super])
+                    || lookahead.peek(Token![extern])
+                    || lookahead.peek(Token![crate])
+                    || lookahead.peek(Token![::]))
+            {
+                input.parse().map(Item::Macro)
+            } else {
+                Err(lookahead.error())
+            }
         }
     }
 
-    impl_synom!(ItemMod "mod item" do_parse!(
-        outer_attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        mod_: keyword!(mod) >>
-        ident: syn!(Ident) >>
-        content_semi: alt!(
-            punct!(;) => {|semi| (
-                Vec::new(),
-                None,
-                Some(semi),
-            )}
-            |
-            braces!(
-                tuple!(
-                    many0!(Attribute::parse_inner),
-                    many0!(Item::parse),
-                )
-            ) => {|(brace, (inner_attrs, items))| (
-                inner_attrs,
-                Some((brace, items)),
-                None,
-            )}
-        ) >>
-        (ItemMod {
-            attrs: {
-                let mut attrs = outer_attrs;
-                attrs.extend(content_semi.0);
-                attrs
-            },
-            vis: vis,
-            mod_token: mod_,
-            ident: ident,
-            content: content_semi.1,
-            semi: content_semi.2,
-        })
-    ));
-
-    impl_synom!(ItemForeignMod "foreign mod item" do_parse!(
-        outer_attrs: many0!(Attribute::parse_outer) >>
-        abi: syn!(Abi) >>
-        braced_content: braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            many0!(ForeignItem::parse),
-        )) >>
-        (ItemForeignMod {
-            attrs: {
-                let mut attrs = outer_attrs;
-                attrs.extend((braced_content.1).0);
-                attrs
-            },
-            abi: abi,
-            brace_token: braced_content.0,
-            items: (braced_content.1).1,
-        })
-    ));
-
-    impl_synom!(ForeignItem "foreign item" alt!(
-        syn!(ForeignItemFn) => { ForeignItem::Fn }
-        |
-        syn!(ForeignItemStatic) => { ForeignItem::Static }
-        |
-        syn!(ForeignItemType) => { ForeignItem::Type }
-        |
-        call!(foreign_item_macro) => { ForeignItem::Verbatim }
-    ));
-
-    impl_synom!(ForeignItemFn "foreign function" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        fn_: keyword!(fn) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        inputs: parens!(do_parse!(
-            args: call!(Punctuated::parse_terminated) >>
-            variadic: option!(cond_reduce!(args.empty_or_trailing(), punct!(...))) >>
-            (args, variadic)
-        )) >>
-        ret: syn!(ReturnType) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        semi: punct!(;) >>
-        ({
-            let (parens, (inputs, variadic)) = inputs;
-            ForeignItemFn {
-                ident: ident,
+    impl Parse for ItemMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let path = input.call(Path::parse_mod_style)?;
+            let bang_token: Token![!] = input.parse()?;
+            let ident: Option<Ident> = input.parse()?;
+            let (delimiter, tts) = input.call(mac::parse_delimiter)?;
+            let semi_token: Option<Token![;]> = if !delimiter.is_brace() {
+                Some(input.parse()?)
+            } else {
+                None
+            };
+            Ok(ItemMacro {
                 attrs: attrs,
-                semi_token: semi,
+                ident: ident,
+                mac: Macro {
+                    path: path,
+                    bang_token: bang_token,
+                    delimiter: delimiter,
+                    tts: tts,
+                },
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    // TODO: figure out the actual grammar; is body required to be braced?
+    impl Parse for ItemMacro2 {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let args;
+            let body;
+            Ok(ItemMacro2 {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                macro_token: input.parse()?,
+                ident: input.parse()?,
+                paren_token: parenthesized!(args in input),
+                args: args.parse()?,
+                brace_token: braced!(body in input),
+                body: body.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ItemExternCrate {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ItemExternCrate {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                extern_token: input.parse()?,
+                crate_token: input.parse()?,
+                ident: input.parse()?,
+                rename: {
+                    if input.peek(Token![as]) {
+                        let as_token: Token![as] = input.parse()?;
+                        let rename: Ident = input.parse()?;
+                        Some((as_token, rename))
+                    } else {
+                        None
+                    }
+                },
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ItemUse {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ItemUse {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                use_token: input.parse()?,
+                leading_colon: input.parse()?,
+                tree: input.call(use_tree)?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    fn use_tree(input: ParseStream) -> Result<UseTree> {
+        let lookahead = input.lookahead1();
+        if lookahead.peek(Ident)
+            || lookahead.peek(Token![self])
+            || lookahead.peek(Token![super])
+            || lookahead.peek(Token![crate])
+            || lookahead.peek(Token![extern])
+        {
+            let ident = input.call(Ident::parse_any)?;
+            if input.peek(Token![::]) {
+                Ok(UseTree::Path(UsePath {
+                    ident: ident,
+                    colon2_token: input.parse()?,
+                    tree: Box::new(input.call(use_tree)?),
+                }))
+            } else if input.peek(Token![as]) {
+                Ok(UseTree::Rename(UseRename {
+                    ident: ident,
+                    as_token: input.parse()?,
+                    rename: input.parse()?,
+                }))
+            } else {
+                Ok(UseTree::Name(UseName { ident: ident }))
+            }
+        } else if lookahead.peek(Token![*]) {
+            Ok(UseTree::Glob(UseGlob {
+                star_token: input.parse()?,
+            }))
+        } else if lookahead.peek(token::Brace) {
+            let content;
+            Ok(UseTree::Group(UseGroup {
+                brace_token: braced!(content in input),
+                items: content.parse_terminated(use_tree)?,
+            }))
+        } else {
+            Err(lookahead.error())
+        }
+    }
+
+    impl Parse for ItemStatic {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ItemStatic {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                static_token: input.parse()?,
+                mutability: input.parse()?,
+                ident: input.parse()?,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+                eq_token: input.parse()?,
+                expr: input.parse()?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ItemConst {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ItemConst {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                const_token: input.parse()?,
+                ident: input.parse()?,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+                eq_token: input.parse()?,
+                expr: input.parse()?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ItemFn {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let vis: Visibility = input.parse()?;
+            let constness: Option<Token![const]> = input.parse()?;
+            let unsafety: Option<Token![unsafe]> = input.parse()?;
+            let asyncness: Option<Token![async]> = input.parse()?;
+            let abi: Option<Abi> = input.parse()?;
+            let fn_token: Token![fn] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let generics: Generics = input.parse()?;
+
+            let content;
+            let paren_token = parenthesized!(content in input);
+            let inputs = content.parse_terminated(FnArg::parse)?;
+
+            let output: ReturnType = input.parse()?;
+            let where_clause: Option<WhereClause> = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ItemFn {
+                attrs: private::attrs(outer_attrs, inner_attrs),
+                vis: vis,
+                constness: constness,
+                unsafety: unsafety,
+                asyncness: asyncness,
+                abi: abi,
+                ident: ident,
                 decl: Box::new(FnDecl {
-                    fn_token: fn_,
-                    paren_token: parens,
+                    fn_token: fn_token,
+                    paren_token: paren_token,
                     inputs: inputs,
-                    variadic: variadic,
-                    output: ret,
+                    output: output,
+                    variadic: None,
                     generics: Generics {
                         where_clause: where_clause,
                         ..generics
                     },
                 }),
-                vis: vis,
+                block: Box::new(Block {
+                    brace_token: brace_token,
+                    stmts: stmts,
+                }),
+            })
+        }
+    }
+
+    impl Parse for FnArg {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![&]) {
+                let ahead = input.fork();
+                if ahead.call(arg_self_ref).is_ok() && !ahead.peek(Token![:]) {
+                    return input.call(arg_self_ref).map(FnArg::SelfRef);
+                }
             }
-        })
-    ));
 
-    impl_synom!(ForeignItemStatic "foreign static" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        static_: keyword!(static) >>
-        mutability: option!(keyword!(mut)) >>
-        ident: syn!(Ident) >>
-        colon: punct!(:) >>
-        ty: syn!(Type) >>
-        semi: punct!(;) >>
-        (ForeignItemStatic {
-            ident: ident,
-            attrs: attrs,
-            semi_token: semi,
-            ty: Box::new(ty),
-            mutability: mutability,
-            static_token: static_,
-            colon_token: colon,
-            vis: vis,
-        })
-    ));
+            if input.peek(Token![mut]) || input.peek(Token![self]) {
+                let ahead = input.fork();
+                if ahead.call(arg_self).is_ok() && !ahead.peek(Token![:]) {
+                    return input.call(arg_self).map(FnArg::SelfValue);
+                }
+            }
 
-    impl_synom!(ForeignItemType "foreign type" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        type_: keyword!(type) >>
-        ident: syn!(Ident) >>
-        semi: punct!(;) >>
-        (ForeignItemType {
-            attrs: attrs,
-            vis: vis,
-            type_token: type_,
-            ident: ident,
-            semi_token: semi,
-        })
-    ));
-
-    named!(foreign_item_macro -> ForeignItemVerbatim, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        many0!(Attribute::parse_outer) >>
-        mac: syn!(Macro) >>
-        cond!(!is_brace(&mac.delimiter), punct!(;)) >>
-        end: call!(verbatim::grab_cursor) >>
-        (ForeignItemVerbatim {
-            tts: verbatim::token_range(begin..end),
-        })
-    ));
-
-    impl_synom!(ItemType "type item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        type_: keyword!(type) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        eq: punct!(=) >>
-        ty: syn!(Type) >>
-        semi: punct!(;) >>
-        (ItemType {
-            attrs: attrs,
-            vis: vis,
-            type_token: type_,
-            ident: ident,
-            generics: Generics {
-                where_clause: where_clause,
-                ..generics
-            },
-            eq_token: eq,
-            ty: Box::new(ty),
-            semi_token: semi,
-        })
-    ));
-
-    named!(existential_type_helper(vis: bool) -> TokenStream, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        many0!(Attribute::parse_outer) >>
-        cond_reduce!(vis, syn!(Visibility)) >>
-        custom_keyword!(existential) >>
-        keyword!(type) >>
-        syn!(Ident) >>
-        syn!(Generics) >>
-        option!(syn!(WhereClause)) >>
-        colon: option!(punct!(:)) >>
-        cond!(
-            colon.is_some(),
-            Punctuated::<TypeParamBound, Token![+]>::parse_separated_nonempty
-        ) >>
-        punct!(;) >>
-        end: call!(verbatim::grab_cursor) >>
-        (verbatim::token_range(begin..end))
-    ));
-
-    named!(unstable_existential_type -> ItemVerbatim, map!(
-        call!(existential_type_helper, true),
-        |tts| ItemVerbatim { tts: tts }
-    ));
-
-    impl_synom!(ItemStruct "struct item" switch!(
-        map!(syn!(DeriveInput), Into::into),
-        Item::Struct(item) => value!(item)
-        |
-        _ => reject!()
-    ));
-
-    impl_synom!(ItemEnum "enum item" switch!(
-        map!(syn!(DeriveInput), Into::into),
-        Item::Enum(item) => value!(item)
-        |
-        _ => reject!()
-    ));
-
-    impl_synom!(ItemUnion "union item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        union_: keyword!(union) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        fields: syn!(FieldsNamed) >>
-        (ItemUnion {
-            attrs: attrs,
-            vis: vis,
-            union_token: union_,
-            ident: ident,
-            generics: Generics {
-                where_clause: where_clause,
-                ..generics
-            },
-            fields: fields,
-        })
-    ));
-
-    impl_synom!(ItemTrait "trait item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        unsafety: option!(keyword!(unsafe)) >>
-        auto_: option!(keyword!(auto)) >>
-        trait_: keyword!(trait) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        colon: option!(punct!(:)) >>
-        bounds: cond!(colon.is_some(), Punctuated::parse_separated_nonempty) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        body: braces!(many0!(TraitItem::parse)) >>
-        (ItemTrait {
-            attrs: attrs,
-            vis: vis,
-            unsafety: unsafety,
-            auto_token: auto_,
-            trait_token: trait_,
-            ident: ident,
-            generics: Generics {
-                where_clause: where_clause,
-                ..generics
-            },
-            colon_token: colon,
-            supertraits: bounds.unwrap_or_default(),
-            brace_token: body.0,
-            items: body.1,
-        })
-    ));
-
-    impl_synom!(TraitItem "trait item" alt!(
-        syn!(TraitItemConst) => { TraitItem::Const }
-        |
-        syn!(TraitItemMethod) => { TraitItem::Method }
-        |
-        syn!(TraitItemType) => { TraitItem::Type }
-        |
-        call!(unstable_trait_existential_type) => { TraitItem::Verbatim }
-        |
-        syn!(TraitItemMacro) => { TraitItem::Macro }
-    ));
-
-    impl_synom!(TraitItemConst "const trait item" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        const_: keyword!(const) >>
-        ident: syn!(Ident) >>
-        colon: punct!(:) >>
-        ty: syn!(Type) >>
-        default: option!(tuple!(punct!(=), syn!(Expr))) >>
-        semi: punct!(;) >>
-        (TraitItemConst {
-            attrs: attrs,
-            const_token: const_,
-            ident: ident,
-            colon_token: colon,
-            ty: ty,
-            default: default,
-            semi_token: semi,
-        })
-    ));
-
-    impl_synom!(TraitItemMethod "method trait item" do_parse!(
-        outer_attrs: many0!(Attribute::parse_outer) >>
-        constness: option!(keyword!(const)) >>
-        unsafety: option!(keyword!(unsafe)) >>
-        abi: option!(syn!(Abi)) >>
-        fn_: keyword!(fn) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        inputs: parens!(Punctuated::parse_terminated) >>
-        ret: syn!(ReturnType) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        body: option!(braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            call!(Block::parse_within),
-        ))) >>
-        semi: cond!(body.is_none(), punct!(;)) >>
-        ({
-            let (inner_attrs, stmts) = match body {
-                Some((b, (inner_attrs, stmts))) => (inner_attrs, Some((stmts, b))),
-                None => (Vec::new(), None),
+            let ahead = input.fork();
+            let err = match ahead.call(arg_captured) {
+                Ok(_) => return input.call(arg_captured).map(FnArg::Captured),
+                Err(err) => err,
             };
-            TraitItemMethod {
-                attrs: {
-                    let mut attrs = outer_attrs;
-                    attrs.extend(inner_attrs);
-                    attrs
+
+            let ahead = input.fork();
+            if ahead.parse::<Type>().is_ok() {
+                return input.parse().map(FnArg::Ignored);
+            }
+
+            Err(err)
+        }
+    }
+
+    fn arg_self_ref(input: ParseStream) -> Result<ArgSelfRef> {
+        Ok(ArgSelfRef {
+            and_token: input.parse()?,
+            lifetime: input.parse()?,
+            mutability: input.parse()?,
+            self_token: input.parse()?,
+        })
+    }
+
+    fn arg_self(input: ParseStream) -> Result<ArgSelf> {
+        Ok(ArgSelf {
+            mutability: input.parse()?,
+            self_token: input.parse()?,
+        })
+    }
+
+    fn arg_captured(input: ParseStream) -> Result<ArgCaptured> {
+        Ok(ArgCaptured {
+            pat: input.parse()?,
+            colon_token: input.parse()?,
+            ty: input.parse()?,
+        })
+    }
+
+    impl Parse for ItemMod {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let vis: Visibility = input.parse()?;
+            let mod_token: Token![mod] = input.parse()?;
+            let ident: Ident = input.parse()?;
+
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![;]) {
+                Ok(ItemMod {
+                    attrs: outer_attrs,
+                    vis: vis,
+                    mod_token: mod_token,
+                    ident: ident,
+                    content: None,
+                    semi: Some(input.parse()?),
+                })
+            } else if lookahead.peek(token::Brace) {
+                let content;
+                let brace_token = braced!(content in input);
+                let inner_attrs = content.call(Attribute::parse_inner)?;
+
+                let mut items = Vec::new();
+                while !content.is_empty() {
+                    items.push(content.parse()?);
+                }
+
+                Ok(ItemMod {
+                    attrs: private::attrs(outer_attrs, inner_attrs),
+                    vis: vis,
+                    mod_token: mod_token,
+                    ident: ident,
+                    content: Some((brace_token, items)),
+                    semi: None,
+                })
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
+
+    impl Parse for ItemForeignMod {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let abi: Abi = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let mut items = Vec::new();
+            while !content.is_empty() {
+                items.push(content.parse()?);
+            }
+
+            Ok(ItemForeignMod {
+                attrs: private::attrs(outer_attrs, inner_attrs),
+                abi: abi,
+                brace_token: brace_token,
+                items: items,
+            })
+        }
+    }
+
+    impl Parse for ForeignItem {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let ahead = input.fork();
+            ahead.call(Attribute::parse_outer)?;
+            let vis: Visibility = ahead.parse()?;
+
+            let lookahead = ahead.lookahead1();
+            if lookahead.peek(Token![fn]) {
+                input.parse().map(ForeignItem::Fn)
+            } else if lookahead.peek(Token![static]) {
+                input.parse().map(ForeignItem::Static)
+            } else if lookahead.peek(Token![type]) {
+                input.parse().map(ForeignItem::Type)
+            } else if vis.is_inherited()
+                && (lookahead.peek(Ident)
+                    || lookahead.peek(Token![self])
+                    || lookahead.peek(Token![super])
+                    || lookahead.peek(Token![extern])
+                    || lookahead.peek(Token![crate])
+                    || lookahead.peek(Token![::]))
+            {
+                input.parse().map(ForeignItem::Macro)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
+
+    impl Parse for ForeignItemFn {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis: Visibility = input.parse()?;
+            let fn_token: Token![fn] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let generics: Generics = input.parse()?;
+
+            let content;
+            let paren_token = parenthesized!(content in input);
+            let mut inputs = Punctuated::new();
+            while !content.is_empty() && !content.peek(Token![...]) {
+                inputs.push_value(content.parse()?);
+                if content.is_empty() {
+                    break;
+                }
+                inputs.push_punct(content.parse()?);
+            }
+            let variadic: Option<Token![...]> = if inputs.empty_or_trailing() {
+                content.parse()?
+            } else {
+                None
+            };
+
+            let output: ReturnType = input.parse()?;
+            let where_clause: Option<WhereClause> = input.parse()?;
+            let semi_token: Token![;] = input.parse()?;
+
+            Ok(ForeignItemFn {
+                attrs: attrs,
+                vis: vis,
+                ident: ident,
+                decl: Box::new(FnDecl {
+                    fn_token: fn_token,
+                    paren_token: paren_token,
+                    inputs: inputs,
+                    output: output,
+                    variadic: variadic,
+                    generics: Generics {
+                        where_clause: where_clause,
+                        ..generics
+                    },
+                }),
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Parse for ForeignItemStatic {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ForeignItemStatic {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                static_token: input.parse()?,
+                mutability: input.parse()?,
+                ident: input.parse()?,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ForeignItemType {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ForeignItemType {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                type_token: input.parse()?,
+                ident: input.parse()?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ForeignItemMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let mac: Macro = input.parse()?;
+            let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
+                None
+            } else {
+                Some(input.parse()?)
+            };
+            Ok(ForeignItemMacro {
+                attrs: attrs,
+                mac: mac,
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Parse for ItemType {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ItemType {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                type_token: input.parse()?,
+                ident: input.parse()?,
+                generics: {
+                    let mut generics: Generics = input.parse()?;
+                    generics.where_clause = input.parse()?;
+                    generics
                 },
+                eq_token: input.parse()?,
+                ty: input.parse()?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ItemExistential {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ItemExistential {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                existential_token: input.parse()?,
+                type_token: input.parse()?,
+                ident: input.parse()?,
+                generics: {
+                    let mut generics: Generics = input.parse()?;
+                    generics.where_clause = input.parse()?;
+                    generics
+                },
+                colon_token: Some(input.parse()?),
+                bounds: {
+                    let mut bounds = Punctuated::new();
+                    while !input.peek(Token![;]) {
+                        if !bounds.is_empty() {
+                            bounds.push_punct(input.parse()?);
+                        }
+                        bounds.push_value(input.parse()?);
+                    }
+                    bounds
+                },
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ItemStruct {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis = input.parse::<Visibility>()?;
+            let struct_token = input.parse::<Token![struct]>()?;
+            let ident = input.parse::<Ident>()?;
+            let generics = input.parse::<Generics>()?;
+            let (where_clause, fields, semi_token) = derive::parsing::data_struct(input)?;
+            Ok(ItemStruct {
+                attrs: attrs,
+                vis: vis,
+                struct_token: struct_token,
+                ident: ident,
+                generics: Generics {
+                    where_clause: where_clause,
+                    ..generics
+                },
+                fields: fields,
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Parse for ItemEnum {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis = input.parse::<Visibility>()?;
+            let enum_token = input.parse::<Token![enum]>()?;
+            let ident = input.parse::<Ident>()?;
+            let generics = input.parse::<Generics>()?;
+            let (where_clause, brace_token, variants) = derive::parsing::data_enum(input)?;
+            Ok(ItemEnum {
+                attrs: attrs,
+                vis: vis,
+                enum_token: enum_token,
+                ident: ident,
+                generics: Generics {
+                    where_clause: where_clause,
+                    ..generics
+                },
+                brace_token: brace_token,
+                variants: variants,
+            })
+        }
+    }
+
+    impl Parse for ItemUnion {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis = input.parse::<Visibility>()?;
+            let union_token = input.parse::<Token![union]>()?;
+            let ident = input.parse::<Ident>()?;
+            let generics = input.parse::<Generics>()?;
+            let (where_clause, fields) = derive::parsing::data_union(input)?;
+            Ok(ItemUnion {
+                attrs: attrs,
+                vis: vis,
+                union_token: union_token,
+                ident: ident,
+                generics: Generics {
+                    where_clause: where_clause,
+                    ..generics
+                },
+                fields: fields,
+            })
+        }
+    }
+
+    impl Parse for ItemTrait {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis: Visibility = input.parse()?;
+            let unsafety: Option<Token![unsafe]> = input.parse()?;
+            let auto_token: Option<Token![auto]> = input.parse()?;
+            let trait_token: Token![trait] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let mut generics: Generics = input.parse()?;
+            let colon_token: Option<Token![:]> = input.parse()?;
+
+            let mut supertraits = Punctuated::new();
+            if colon_token.is_some() {
+                loop {
+                    supertraits.push_value(input.parse()?);
+                    if input.peek(Token![where]) || input.peek(token::Brace) {
+                        break;
+                    }
+                    supertraits.push_punct(input.parse()?);
+                    if input.peek(Token![where]) || input.peek(token::Brace) {
+                        break;
+                    }
+                }
+            }
+
+            generics.where_clause = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let mut items = Vec::new();
+            while !content.is_empty() {
+                items.push(content.parse()?);
+            }
+
+            Ok(ItemTrait {
+                attrs: attrs,
+                vis: vis,
+                unsafety: unsafety,
+                auto_token: auto_token,
+                trait_token: trait_token,
+                ident: ident,
+                generics: generics,
+                colon_token: colon_token,
+                supertraits: supertraits,
+                brace_token: brace_token,
+                items: items,
+            })
+        }
+    }
+
+    impl Parse for ItemTraitAlias {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let vis: Visibility = input.parse()?;
+            let trait_token: Token![trait] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let mut generics: Generics = input.parse()?;
+            let eq_token: Token![=] = input.parse()?;
+
+            let mut bounds = Punctuated::new();
+            loop {
+                if input.peek(Token![where]) || input.peek(Token![;]) {
+                    break;
+                }
+                bounds.push_value(input.parse()?);
+                if input.peek(Token![where]) || input.peek(Token![;]) {
+                    break;
+                }
+                bounds.push_punct(input.parse()?);
+            }
+
+            generics.where_clause = input.parse()?;
+            let semi_token: Token![;] = input.parse()?;
+
+            Ok(ItemTraitAlias {
+                attrs: attrs,
+                vis: vis,
+                trait_token: trait_token,
+                ident: ident,
+                generics: generics,
+                eq_token: eq_token,
+                bounds: bounds,
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Parse for TraitItem {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let ahead = input.fork();
+            ahead.call(Attribute::parse_outer)?;
+
+            let lookahead = ahead.lookahead1();
+            if lookahead.peek(Token![const]) {
+                ahead.parse::<Token![const]>()?;
+                let lookahead = ahead.lookahead1();
+                if lookahead.peek(Ident) {
+                    input.parse().map(TraitItem::Const)
+                } else if lookahead.peek(Token![unsafe])
+                    || lookahead.peek(Token![extern])
+                    || lookahead.peek(Token![fn])
+                {
+                    input.parse().map(TraitItem::Method)
+                } else {
+                    Err(lookahead.error())
+                }
+            } else if lookahead.peek(Token![unsafe])
+                || lookahead.peek(Token![extern])
+                || lookahead.peek(Token![fn])
+            {
+                input.parse().map(TraitItem::Method)
+            } else if lookahead.peek(Token![type]) {
+                input.parse().map(TraitItem::Type)
+            } else if lookahead.peek(Ident)
+                || lookahead.peek(Token![self])
+                || lookahead.peek(Token![super])
+                || lookahead.peek(Token![extern])
+                || lookahead.peek(Token![crate])
+                || lookahead.peek(Token![::])
+            {
+                input.parse().map(TraitItem::Macro)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
+
+    impl Parse for TraitItemConst {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TraitItemConst {
+                attrs: input.call(Attribute::parse_outer)?,
+                const_token: input.parse()?,
+                ident: input.parse()?,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+                default: {
+                    if input.peek(Token![=]) {
+                        let eq_token: Token![=] = input.parse()?;
+                        let default: Expr = input.parse()?;
+                        Some((eq_token, default))
+                    } else {
+                        None
+                    }
+                },
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for TraitItemMethod {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let constness: Option<Token![const]> = input.parse()?;
+            let unsafety: Option<Token![unsafe]> = input.parse()?;
+            let abi: Option<Abi> = input.parse()?;
+            let fn_token: Token![fn] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let generics: Generics = input.parse()?;
+
+            let content;
+            let paren_token = parenthesized!(content in input);
+            let inputs = content.parse_terminated(FnArg::parse)?;
+
+            let output: ReturnType = input.parse()?;
+            let where_clause: Option<WhereClause> = input.parse()?;
+
+            let lookahead = input.lookahead1();
+            let (brace_token, inner_attrs, stmts, semi_token) = if lookahead.peek(token::Brace) {
+                let content;
+                let brace_token = braced!(content in input);
+                let inner_attrs = content.call(Attribute::parse_inner)?;
+                let stmts = content.call(Block::parse_within)?;
+                (Some(brace_token), inner_attrs, stmts, None)
+            } else if lookahead.peek(Token![;]) {
+                let semi_token: Token![;] = input.parse()?;
+                (None, Vec::new(), Vec::new(), Some(semi_token))
+            } else {
+                return Err(lookahead.error());
+            };
+
+            Ok(TraitItemMethod {
+                attrs: private::attrs(outer_attrs, inner_attrs),
                 sig: MethodSig {
                     constness: constness,
                     unsafety: unsafety,
+                    asyncness: None,
                     abi: abi,
                     ident: ident,
                     decl: FnDecl {
-                        inputs: inputs.1,
-                        output: ret,
-                        fn_token: fn_,
-                        paren_token: inputs.0,
+                        fn_token: fn_token,
+                        paren_token: paren_token,
+                        inputs: inputs,
+                        output: output,
                         variadic: None,
                         generics: Generics {
                             where_clause: where_clause,
@@ -1396,260 +1630,322 @@
                         },
                     },
                 },
-                default: stmts.map(|stmts| {
-                    Block {
-                        stmts: stmts.0,
-                        brace_token: stmts.1,
-                    }
+                default: brace_token.map(|brace_token| Block {
+                    brace_token: brace_token,
+                    stmts: stmts,
                 }),
-                semi_token: semi,
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Parse for TraitItemType {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let type_token: Token![type] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let mut generics: Generics = input.parse()?;
+            let colon_token: Option<Token![:]> = input.parse()?;
+
+            let mut bounds = Punctuated::new();
+            if colon_token.is_some() {
+                while !input.peek(Token![where]) && !input.peek(Token![=]) && !input.peek(Token![;])
+                {
+                    if !bounds.is_empty() {
+                        bounds.push_punct(input.parse()?);
+                    }
+                    bounds.push_value(input.parse()?);
+                }
             }
-        })
-    ));
 
-    impl_synom!(TraitItemType "trait item type" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        type_: keyword!(type) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        colon: option!(punct!(:)) >>
-        bounds: cond!(colon.is_some(), Punctuated::parse_separated_nonempty) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        default: option!(tuple!(punct!(=), syn!(Type))) >>
-        semi: punct!(;) >>
-        (TraitItemType {
-            attrs: attrs,
-            type_token: type_,
-            ident: ident,
-            generics: Generics {
-                where_clause: where_clause,
-                ..generics
-            },
-            colon_token: colon,
-            bounds: bounds.unwrap_or_default(),
-            default: default,
-            semi_token: semi,
-        })
-    ));
+            generics.where_clause = input.parse()?;
+            let default = if input.peek(Token![=]) {
+                let eq_token: Token![=] = input.parse()?;
+                let default: Type = input.parse()?;
+                Some((eq_token, default))
+            } else {
+                None
+            };
+            let semi_token: Token![;] = input.parse()?;
 
-    named!(unstable_trait_existential_type -> TraitItemVerbatim, map!(
-        call!(existential_type_helper, false),
-        |tts| TraitItemVerbatim { tts: tts }
-    ));
-
-    impl_synom!(TraitItemMacro "trait item macro" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        mac: syn!(Macro) >>
-        semi: cond!(!is_brace(&mac.delimiter), punct!(;)) >>
-        (TraitItemMacro {
-            attrs: attrs,
-            mac: mac,
-            semi_token: semi,
-        })
-    ));
-
-    impl_synom!(ItemImpl "impl item" do_parse!(
-        outer_attrs: many0!(Attribute::parse_outer) >>
-        defaultness: option!(keyword!(default)) >>
-        unsafety: option!(keyword!(unsafe)) >>
-        impl_: keyword!(impl) >>
-        generics: syn!(Generics) >>
-        polarity_path: alt!(
-            do_parse!(
-                polarity: option!(punct!(!)) >>
-                path: syn!(Path) >>
-                for_: keyword!(for) >>
-                (Some((polarity, path, for_)))
-            )
-            |
-            epsilon!() => { |_| None }
-        ) >>
-        self_ty: syn!(Type) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        inner: braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            many0!(ImplItem::parse),
-        )) >>
-        (ItemImpl {
-            attrs: {
-                let mut attrs = outer_attrs;
-                attrs.extend((inner.1).0);
-                attrs
-            },
-            defaultness: defaultness,
-            unsafety: unsafety,
-            impl_token: impl_,
-            generics: Generics {
-                where_clause: where_clause,
-                ..generics
-            },
-            trait_: polarity_path,
-            self_ty: Box::new(self_ty),
-            brace_token: inner.0,
-            items: (inner.1).1,
-        })
-    ));
-
-    impl_synom!(ImplItem "item in impl block" alt!(
-        syn!(ImplItemConst) => { ImplItem::Const }
-        |
-        syn!(ImplItemMethod) => { ImplItem::Method }
-        |
-        call!(unstable_async_method) => { ImplItem::Verbatim }
-        |
-        syn!(ImplItemType) => { ImplItem::Type }
-        |
-        call!(unstable_impl_existential_type) => { ImplItem::Verbatim }
-        |
-        syn!(ImplItemMacro) => { ImplItem::Macro }
-    ));
-
-    impl_synom!(ImplItemConst "const item in impl block" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        defaultness: option!(keyword!(default)) >>
-        const_: keyword!(const) >>
-        ident: syn!(Ident) >>
-        colon: punct!(:) >>
-        ty: syn!(Type) >>
-        eq: punct!(=) >>
-        value: syn!(Expr) >>
-        semi: punct!(;) >>
-        (ImplItemConst {
-            attrs: attrs,
-            vis: vis,
-            defaultness: defaultness,
-            const_token: const_,
-            ident: ident,
-            colon_token: colon,
-            ty: ty,
-            eq_token: eq,
-            expr: value,
-            semi_token: semi,
-        })
-    ));
-
-    impl_synom!(ImplItemMethod "method in impl block" do_parse!(
-        outer_attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        defaultness: option!(keyword!(default)) >>
-        constness: option!(keyword!(const)) >>
-        unsafety: option!(keyword!(unsafe)) >>
-        abi: option!(syn!(Abi)) >>
-        fn_: keyword!(fn) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        inputs: parens!(Punctuated::parse_terminated) >>
-        ret: syn!(ReturnType) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        inner_attrs_stmts: braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            call!(Block::parse_within),
-        )) >>
-        (ImplItemMethod {
-            attrs: {
-                let mut attrs = outer_attrs;
-                attrs.extend((inner_attrs_stmts.1).0);
-                attrs
-            },
-            vis: vis,
-            defaultness: defaultness,
-            sig: MethodSig {
-                constness: constness,
-                unsafety: unsafety,
-                abi: abi,
+            Ok(TraitItemType {
+                attrs: attrs,
+                type_token: type_token,
                 ident: ident,
-                decl: FnDecl {
-                    fn_token: fn_,
-                    paren_token: inputs.0,
-                    inputs: inputs.1,
-                    output: ret,
-                    generics: Generics {
-                        where_clause: where_clause,
-                        ..generics
-                    },
-                    variadic: None,
+                generics: generics,
+                colon_token: colon_token,
+                bounds: bounds,
+                default: default,
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Parse for TraitItemMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let mac: Macro = input.parse()?;
+            let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
+                None
+            } else {
+                Some(input.parse()?)
+            };
+            Ok(TraitItemMacro {
+                attrs: attrs,
+                mac: mac,
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Parse for ItemImpl {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let defaultness: Option<Token![default]> = input.parse()?;
+            let unsafety: Option<Token![unsafe]> = input.parse()?;
+            let impl_token: Token![impl ] = input.parse()?;
+            let generics: Generics = input.parse()?;
+            let trait_ = {
+                let ahead = input.fork();
+                if ahead.parse::<Option<Token![!]>>().is_ok()
+                    && ahead.parse::<Path>().is_ok()
+                    && ahead.parse::<Token![for]>().is_ok()
+                {
+                    let polarity: Option<Token![!]> = input.parse()?;
+                    let path: Path = input.parse()?;
+                    let for_token: Token![for] = input.parse()?;
+                    Some((polarity, path, for_token))
+                } else {
+                    None
+                }
+            };
+            let self_ty: Type = input.parse()?;
+            let where_clause: Option<WhereClause> = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+
+            let mut items = Vec::new();
+            while !content.is_empty() {
+                items.push(content.parse()?);
+            }
+
+            Ok(ItemImpl {
+                attrs: private::attrs(outer_attrs, inner_attrs),
+                defaultness: defaultness,
+                unsafety: unsafety,
+                impl_token: impl_token,
+                generics: Generics {
+                    where_clause: where_clause,
+                    ..generics
                 },
-            },
-            block: Block {
-                brace_token: inner_attrs_stmts.0,
-                stmts: (inner_attrs_stmts.1).1,
-            },
-        })
-    ));
+                trait_: trait_,
+                self_ty: Box::new(self_ty),
+                brace_token: brace_token,
+                items: items,
+            })
+        }
+    }
 
-    named!(unstable_async_method -> ImplItemVerbatim, do_parse!(
-        begin: call!(verbatim::grab_cursor) >>
-        many0!(Attribute::parse_outer) >>
-        syn!(Visibility) >>
-        option!(keyword!(default)) >>
-        option!(keyword!(const)) >>
-        option!(keyword!(unsafe)) >>
-        keyword!(async) >>
-        option!(syn!(Abi)) >>
-        keyword!(fn) >>
-        syn!(Ident) >>
-        syn!(Generics) >>
-        parens!(Punctuated::<FnArg, Token![,]>::parse_terminated) >>
-        syn!(ReturnType) >>
-        option!(syn!(WhereClause)) >>
-        braces!(tuple!(
-            many0!(Attribute::parse_inner),
-            call!(Block::parse_within),
-        )) >>
-        end: call!(verbatim::grab_cursor) >>
-        (ImplItemVerbatim {
-            tts: verbatim::token_range(begin..end),
-        })
-    ));
+    impl Parse for ImplItem {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let ahead = input.fork();
+            ahead.call(Attribute::parse_outer)?;
+            let vis: Visibility = ahead.parse()?;
 
-    impl_synom!(ImplItemType "type in impl block" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        vis: syn!(Visibility) >>
-        defaultness: option!(keyword!(default)) >>
-        type_: keyword!(type) >>
-        ident: syn!(Ident) >>
-        generics: syn!(Generics) >>
-        where_clause: option!(syn!(WhereClause)) >>
-        eq: punct!(=) >>
-        ty: syn!(Type) >>
-        semi: punct!(;) >>
-        (ImplItemType {
-            attrs: attrs,
-            vis: vis,
-            defaultness: defaultness,
-            type_token: type_,
-            ident: ident,
-            generics: Generics {
-                where_clause: where_clause,
-                ..generics
-            },
-            eq_token: eq,
-            ty: ty,
-            semi_token: semi,
-        })
-    ));
+            let mut lookahead = ahead.lookahead1();
+            let defaultness = if lookahead.peek(Token![default]) && !ahead.peek2(Token![!]) {
+                let defaultness: Token![default] = ahead.parse()?;
+                lookahead = ahead.lookahead1();
+                Some(defaultness)
+            } else {
+                None
+            };
 
-    named!(unstable_impl_existential_type -> ImplItemVerbatim, map!(
-        call!(existential_type_helper, true),
-        |tts| ImplItemVerbatim { tts: tts }
-    ));
+            if lookahead.peek(Token![const]) {
+                ahead.parse::<Token![const]>()?;
+                let lookahead = ahead.lookahead1();
+                if lookahead.peek(Ident) {
+                    input.parse().map(ImplItem::Const)
+                } else if lookahead.peek(Token![unsafe])
+                    || lookahead.peek(Token![async])
+                    || lookahead.peek(Token![extern])
+                    || lookahead.peek(Token![fn])
+                {
+                    input.parse().map(ImplItem::Method)
+                } else {
+                    Err(lookahead.error())
+                }
+            } else if lookahead.peek(Token![unsafe])
+                || lookahead.peek(Token![async])
+                || lookahead.peek(Token![extern])
+                || lookahead.peek(Token![fn])
+            {
+                input.parse().map(ImplItem::Method)
+            } else if lookahead.peek(Token![type]) {
+                input.parse().map(ImplItem::Type)
+            } else if vis.is_inherited()
+                && defaultness.is_none()
+                && lookahead.peek(Token![existential])
+            {
+                input.parse().map(ImplItem::Existential)
+            } else if vis.is_inherited()
+                && defaultness.is_none()
+                && (lookahead.peek(Ident)
+                    || lookahead.peek(Token![self])
+                    || lookahead.peek(Token![super])
+                    || lookahead.peek(Token![extern])
+                    || lookahead.peek(Token![crate])
+                    || lookahead.peek(Token![::]))
+            {
+                input.parse().map(ImplItem::Macro)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
 
-    impl_synom!(ImplItemMacro "macro in impl block" do_parse!(
-        attrs: many0!(Attribute::parse_outer) >>
-        mac: syn!(Macro) >>
-        semi: cond!(!is_brace(&mac.delimiter), punct!(;)) >>
-        (ImplItemMacro {
-            attrs: attrs,
-            mac: mac,
-            semi_token: semi,
-        })
-    ));
+    impl Parse for ImplItemConst {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ImplItemConst {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                defaultness: input.parse()?,
+                const_token: input.parse()?,
+                ident: input.parse()?,
+                colon_token: input.parse()?,
+                ty: input.parse()?,
+                eq_token: input.parse()?,
+                expr: input.parse()?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
 
-    fn is_brace(delimiter: &MacroDelimiter) -> bool {
-        match *delimiter {
-            MacroDelimiter::Brace(_) => true,
-            MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false,
+    impl Parse for ImplItemMethod {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
+            let vis: Visibility = input.parse()?;
+            let defaultness: Option<Token![default]> = input.parse()?;
+            let constness: Option<Token![const]> = input.parse()?;
+            let unsafety: Option<Token![unsafe]> = input.parse()?;
+            let asyncness: Option<Token![async]> = input.parse()?;
+            let abi: Option<Abi> = input.parse()?;
+            let fn_token: Token![fn] = input.parse()?;
+            let ident: Ident = input.parse()?;
+            let generics: Generics = input.parse()?;
+
+            let content;
+            let paren_token = parenthesized!(content in input);
+            let inputs = content.parse_terminated(FnArg::parse)?;
+
+            let output: ReturnType = input.parse()?;
+            let where_clause: Option<WhereClause> = input.parse()?;
+
+            let content;
+            let brace_token = braced!(content in input);
+            let inner_attrs = content.call(Attribute::parse_inner)?;
+            let stmts = content.call(Block::parse_within)?;
+
+            Ok(ImplItemMethod {
+                attrs: private::attrs(outer_attrs, inner_attrs),
+                vis: vis,
+                defaultness: defaultness,
+                sig: MethodSig {
+                    constness: constness,
+                    unsafety: unsafety,
+                    asyncness: asyncness,
+                    abi: abi,
+                    ident: ident,
+                    decl: FnDecl {
+                        fn_token: fn_token,
+                        paren_token: paren_token,
+                        inputs: inputs,
+                        output: output,
+                        variadic: None,
+                        generics: Generics {
+                            where_clause: where_clause,
+                            ..generics
+                        },
+                    },
+                },
+                block: Block {
+                    brace_token: brace_token,
+                    stmts: stmts,
+                },
+            })
+        }
+    }
+
+    impl Parse for ImplItemType {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(ImplItemType {
+                attrs: input.call(Attribute::parse_outer)?,
+                vis: input.parse()?,
+                defaultness: input.parse()?,
+                type_token: input.parse()?,
+                ident: input.parse()?,
+                generics: {
+                    let mut generics: Generics = input.parse()?;
+                    generics.where_clause = input.parse()?;
+                    generics
+                },
+                eq_token: input.parse()?,
+                ty: input.parse()?,
+                semi_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for ImplItemExistential {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let ety: ItemExistential = input.parse()?;
+            Ok(ImplItemExistential {
+                attrs: ety.attrs,
+                existential_token: ety.existential_token,
+                type_token: ety.type_token,
+                ident: ety.ident,
+                generics: ety.generics,
+                colon_token: ety.colon_token,
+                bounds: ety.bounds,
+                semi_token: ety.semi_token,
+            })
+        }
+    }
+
+    impl Parse for ImplItemMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let mac: Macro = input.parse()?;
+            let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
+                None
+            } else {
+                Some(input.parse()?)
+            };
+            Ok(ImplItemMacro {
+                attrs: attrs,
+                mac: mac,
+                semi_token: semi_token,
+            })
+        }
+    }
+
+    impl Visibility {
+        fn is_inherited(&self) -> bool {
+            match *self {
+                Visibility::Inherited => true,
+                _ => false,
+            }
+        }
+    }
+
+    impl MacroDelimiter {
+        fn is_brace(&self) -> bool {
+            match *self {
+                MacroDelimiter::Brace(_) => true,
+                MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false,
+            }
         }
     }
 }
@@ -1657,10 +1953,13 @@
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
-    use attr::FilterAttrs;
+
     use proc_macro2::TokenStream;
     use quote::{ToTokens, TokenStreamExt};
 
+    use attr::FilterAttrs;
+    use print::TokensOrDefault;
+
     impl ToTokens for ItemExternCrate {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
@@ -1722,6 +2021,7 @@
             self.vis.to_tokens(tokens);
             self.constness.to_tokens(tokens);
             self.unsafety.to_tokens(tokens);
+            self.asyncness.to_tokens(tokens);
             self.abi.to_tokens(tokens);
             NamedDecl(&self.decl, &self.ident).to_tokens(tokens);
             self.block.brace_token.surround(tokens, |tokens| {
@@ -1773,6 +2073,23 @@
         }
     }
 
+    impl ToTokens for ItemExistential {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.existential_token.to_tokens(tokens);
+            self.type_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            self.generics.where_clause.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                TokensOrDefault(&self.colon_token).to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for ItemEnum {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
@@ -1844,6 +2161,20 @@
         }
     }
 
+    impl ToTokens for ItemTraitAlias {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.trait_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.bounds.to_tokens(tokens);
+            self.generics.where_clause.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for ItemImpl {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
@@ -2052,6 +2383,22 @@
         }
     }
 
+    impl ToTokens for ImplItemExistential {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.existential_token.to_tokens(tokens);
+            self.type_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            self.generics.where_clause.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                TokensOrDefault(&self.colon_token).to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for ImplItemMacro {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             tokens.append_all(self.attrs.outer());
@@ -2098,6 +2445,14 @@
         }
     }
 
+    impl ToTokens for ForeignItemMacro {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.mac.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for ForeignItemVerbatim {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             self.tts.to_tokens(tokens);
@@ -2108,6 +2463,7 @@
         fn to_tokens(&self, tokens: &mut TokenStream) {
             self.constness.to_tokens(tokens);
             self.unsafety.to_tokens(tokens);
+            self.asyncness.to_tokens(tokens);
             self.abi.to_tokens(tokens);
             NamedDecl(&self.decl, &self.ident).to_tokens(tokens);
         }
diff --git a/src/lib.rs b/src/lib.rs
index debb5b0..d0a972e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -76,13 +76,12 @@
 //! ```
 //!
 //! ```rust
-//! extern crate proc_macro;
-//! extern crate syn;
-//!
-//! #[macro_use]
-//! extern crate quote;
-//!
+//! # extern crate proc_macro;
+//! # extern crate quote;
+//! # extern crate syn;
+//! #
 //! use proc_macro::TokenStream;
+//! use quote::quote;
 //! use syn::DeriveInput;
 //!
 //! # const IGNORE_TOKENS: &str = stringify! {
@@ -264,10 +263,14 @@
 #![cfg_attr(
     feature = "cargo-clippy",
     allow(
+        block_in_if_condition_stmt,
         const_static_lifetime,
+        cyclomatic_complexity,
         doc_markdown,
+        eval_order_dependence,
         large_enum_variant,
         match_bool,
+        never_loop,
         redundant_closure,
         needless_pass_by_value,
         redundant_field_names,
@@ -280,6 +283,7 @@
     allow(
         cast_possible_truncation,
         cast_possible_wrap,
+        empty_enum,
         if_not_else,
         indexing_slicing,
         items_after_statements,
@@ -304,18 +308,20 @@
 #[cfg(feature = "printing")]
 extern crate quote;
 
-#[cfg(feature = "parsing")]
-#[macro_use]
-#[doc(hidden)]
-pub mod parsers;
-
 #[macro_use]
 mod macros;
 
+// Not public API.
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+#[macro_use]
+pub mod group;
+
 #[macro_use]
 pub mod token;
 
-pub use proc_macro2::Ident;
+mod ident;
+pub use ident::Ident;
 
 #[cfg(any(feature = "full", feature = "derive"))]
 mod attr;
@@ -334,12 +340,12 @@
 mod expr;
 #[cfg(any(feature = "full", feature = "derive"))]
 pub use expr::{
-    Expr, ExprArray, ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox, ExprBreak, ExprCall,
-    ExprCast, ExprCatch, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup, ExprIf,
-    ExprIfLet, ExprInPlace, ExprIndex, ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall,
-    ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry,
-    ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim, ExprWhile, ExprWhileLet, ExprYield,
-    Index, Member,
+    Expr, ExprArray, ExprAssign, ExprAssignOp, ExprAsync, ExprBinary, ExprBlock, ExprBox,
+    ExprBreak, ExprCall, ExprCast, ExprClosure, ExprContinue, ExprField, ExprForLoop, ExprGroup,
+    ExprIf, ExprIfLet, ExprInPlace, ExprIndex, ExprLit, ExprLoop, ExprMacro, ExprMatch,
+    ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprReference, ExprRepeat, ExprReturn,
+    ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprType, ExprUnary, ExprUnsafe, ExprVerbatim,
+    ExprWhile, ExprWhileLet, ExprYield, Index, Member,
 };
 
 #[cfg(feature = "full")]
@@ -367,13 +373,14 @@
 mod item;
 #[cfg(feature = "full")]
 pub use item::{
-    ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemStatic,
-    ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst, ImplItemMacro, ImplItemMethod,
-    ImplItemType, ImplItemVerbatim, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn,
-    ItemForeignMod, ItemImpl, ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait,
-    ItemType, ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst,
-    TraitItemMacro, TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName,
-    UsePath, UseRename, UseTree,
+    ArgCaptured, ArgSelf, ArgSelfRef, FnArg, FnDecl, ForeignItem, ForeignItemFn, ForeignItemMacro,
+    ForeignItemStatic, ForeignItemType, ForeignItemVerbatim, ImplItem, ImplItemConst,
+    ImplItemExistential, ImplItemMacro, ImplItemMethod, ImplItemType, ImplItemVerbatim, Item,
+    ItemConst, ItemEnum, ItemExistential, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl,
+    ItemMacro, ItemMacro2, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType,
+    ItemUnion, ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemMacro,
+    TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName, UsePath,
+    UseRename, UseTree,
 };
 
 #[cfg(feature = "full")]
@@ -381,9 +388,7 @@
 #[cfg(feature = "full")]
 pub use file::File;
 
-#[cfg(any(feature = "full", feature = "derive"))]
 mod lifetime;
-#[cfg(any(feature = "full", feature = "derive"))]
 pub use lifetime::Lifetime;
 
 #[cfg(any(feature = "full", feature = "derive"))]
@@ -420,11 +425,6 @@
 
 #[cfg(any(feature = "full", feature = "derive"))]
 mod path;
-#[cfg(all(
-    any(feature = "full", feature = "derive"),
-    feature = "printing"
-))]
-pub use path::PathTokens;
 #[cfg(any(feature = "full", feature = "derive"))]
 pub use path::{
     AngleBracketedGenericArguments, Binding, GenericArgument, ParenthesizedGenericArguments, Path,
@@ -433,10 +433,13 @@
 
 #[cfg(feature = "parsing")]
 pub mod buffer;
-pub mod punctuated;
 #[cfg(feature = "parsing")]
-pub mod synom;
-#[cfg(any(feature = "full", feature = "derive"))]
+pub mod ext;
+pub mod punctuated;
+#[cfg(all(
+    any(feature = "full", feature = "derive"),
+    feature = "extra-traits"
+))]
 mod tt;
 
 // Not public API except the `parse_quote!` macro.
@@ -447,9 +450,6 @@
 #[cfg(all(feature = "parsing", feature = "printing"))]
 pub mod spanned;
 
-#[cfg(all(feature = "parsing", feature = "full"))]
-mod verbatim;
-
 mod gen {
     /// Syntax tree traversal to walk a shared borrow of a syntax tree.
     ///
@@ -567,20 +567,36 @@
 }
 pub use gen::*;
 
-////////////////////////////////////////////////////////////////////////////////
+// Not public API.
+#[doc(hidden)]
+pub mod export;
 
 #[cfg(feature = "parsing")]
-use synom::{Parser, Synom};
+mod lookahead;
+
+#[cfg(feature = "parsing")]
+pub mod parse;
+
+mod span;
+
+#[cfg(all(
+    any(feature = "full", feature = "derive"),
+    feature = "printing"
+))]
+mod print;
+
+////////////////////////////////////////////////////////////////////////////////
+
+#[cfg(any(feature = "parsing", feature = "full", feature = "derive"))]
+#[allow(non_camel_case_types)]
+struct private;
+
+////////////////////////////////////////////////////////////////////////////////
 
 #[cfg(feature = "parsing")]
 mod error;
 #[cfg(feature = "parsing")]
-use error::ParseError;
-
-// Not public API.
-#[cfg(feature = "parsing")]
-#[doc(hidden)]
-pub use error::parse_error;
+use error::Error;
 
 /// Parse tokens of source code into the chosen syntax tree node.
 ///
@@ -601,14 +617,12 @@
 /// # Examples
 ///
 /// ```rust
-/// extern crate proc_macro;
+/// # extern crate proc_macro;
+/// # extern crate quote;
+/// # extern crate syn;
+/// #
 /// use proc_macro::TokenStream;
-///
-/// extern crate syn;
-///
-/// #[macro_use]
-/// extern crate quote;
-///
+/// use quote::quote;
 /// use syn::DeriveInput;
 ///
 /// # const IGNORE_TOKENS: &str = stringify! {
@@ -634,11 +648,8 @@
     feature = "parsing",
     feature = "proc-macro"
 ))]
-pub fn parse<T>(tokens: proc_macro::TokenStream) -> Result<T, ParseError>
-where
-    T: Synom,
-{
-    parse2(tokens.into())
+pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T, Error> {
+    parse::Parser::parse(T::parse, tokens)
 }
 
 /// Parse a proc-macro2 token stream into the chosen syntax tree node.
@@ -654,15 +665,8 @@
 ///
 /// *This function is available if Syn is built with the `"parsing"` feature.*
 #[cfg(feature = "parsing")]
-pub fn parse2<T>(tokens: proc_macro2::TokenStream) -> Result<T, ParseError>
-where
-    T: Synom,
-{
-    let parser = T::parse;
-    parser.parse2(tokens).map_err(|err| match T::description() {
-        Some(s) => ParseError::new(format!("failed to parse {}: {}", s, err)),
-        None => err,
-    })
+pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T, Error> {
+    parse::Parser::parse2(T::parse, tokens)
 }
 
 /// Parse a string of Rust code into the chosen syntax tree node.
@@ -677,12 +681,10 @@
 /// # Examples
 ///
 /// ```rust
-/// extern crate syn;
+/// # extern crate syn;
 /// #
-/// #
-/// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
-///
 /// use syn::Expr;
+/// use syn::parse::Result;
 ///
 /// fn run() -> Result<()> {
 ///     let code = "assert_eq!(u8::max_value(), 255)";
@@ -694,11 +696,8 @@
 /// # fn main() { run().unwrap() }
 /// ```
 #[cfg(feature = "parsing")]
-pub fn parse_str<T: Synom>(s: &str) -> Result<T, ParseError> {
-    match s.parse() {
-        Ok(tts) => parse2(tts),
-        Err(_) => Err(ParseError::new("error while lexing input string")),
-    }
+pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T, Error> {
+    parse::Parser::parse_str(T::parse, s)
 }
 
 // FIXME the name parse_file makes it sound like you might pass in a path to a
@@ -717,15 +716,13 @@
 /// # Examples
 ///
 /// ```rust,no_run
-/// extern crate syn;
+/// # extern crate syn;
 /// #
-/// #
-/// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
-///
+/// use std::error::Error;
 /// use std::fs::File;
 /// use std::io::Read;
 ///
-/// fn run() -> Result<()> {
+/// fn run() -> Result<(), Box<Error>> {
 ///     let mut file = File::open("path/to/code.rs")?;
 ///     let mut content = String::new();
 ///     file.read_to_string(&mut content)?;
@@ -742,7 +739,7 @@
 /// # fn main() { run().unwrap() }
 /// ```
 #[cfg(all(feature = "parsing", feature = "full"))]
-pub fn parse_file(mut content: &str) -> Result<File, ParseError> {
+pub fn parse_file(mut content: &str) -> Result<File, Error> {
     // Strip the BOM if it is present
     const BOM: &'static str = "\u{feff}";
     if content.starts_with(BOM) {
@@ -765,24 +762,56 @@
     Ok(file)
 }
 
-#[cfg(all(
-    any(feature = "full", feature = "derive"),
-    feature = "printing"
-))]
-struct TokensOrDefault<'a, T: 'a>(&'a Option<T>);
-
-#[cfg(all(
-    any(feature = "full", feature = "derive"),
-    feature = "printing"
-))]
-impl<'a, T> quote::ToTokens for TokensOrDefault<'a, T>
-where
-    T: quote::ToTokens + Default,
-{
-    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
-        match *self.0 {
-            Some(ref t) => t.to_tokens(tokens),
-            None => T::default().to_tokens(tokens),
-        }
-    }
+/// Parse the input TokenStream of a macro, triggering a compile error if the
+/// tokens fail to parse.
+///
+/// Refer to the [`parse` module] documentation for more details about parsing
+/// in Syn.
+///
+/// [`parse` module]: parse/index.html
+///
+/// # Intended usage
+///
+/// ```rust
+/// # extern crate proc_macro;
+/// # extern crate syn;
+/// #
+/// use proc_macro::TokenStream;
+/// use syn::parse_macro_input;
+/// use syn::parse::{Parse, ParseStream, Result};
+///
+/// struct MyMacroInput {
+///     /* ... */
+/// }
+///
+/// impl Parse for MyMacroInput {
+///     fn parse(input: ParseStream) -> Result<Self> {
+///         /* ... */
+/// #       Ok(MyMacroInput {})
+///     }
+/// }
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro]
+/// # };
+/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
+///     let input = parse_macro_input!(tokens as MyMacroInput);
+///
+///     /* ... */
+/// #   "".parse().unwrap()
+/// }
+/// #
+/// # fn main() {}
+/// ```
+#[cfg(feature = "proc-macro")]
+#[macro_export]
+macro_rules! parse_macro_input {
+    ($tokenstream:ident as $ty:ty) => {
+        match $crate::parse::<$ty>($tokenstream) {
+            $crate::export::Ok(data) => data,
+            $crate::export::Err(err) => {
+                return $crate::export::TokenStream::from(err.into_compile_error());
+            }
+        };
+    };
 }
diff --git a/src/lifetime.rs b/src/lifetime.rs
index 5ca876f..3f093c8 100644
--- a/src/lifetime.rs
+++ b/src/lifetime.rs
@@ -13,7 +13,8 @@
 use proc_macro2::{Ident, Span};
 use unicode_xid::UnicodeXID;
 
-use token::Apostrophe;
+#[cfg(feature = "parsing")]
+use lookahead;
 
 /// A Rust lifetime: `'a`.
 ///
@@ -31,25 +32,42 @@
 #[cfg_attr(feature = "extra-traits", derive(Debug))]
 #[derive(Clone)]
 pub struct Lifetime {
-    pub apostrophe: Apostrophe,
+    pub apostrophe: Span,
     pub ident: Ident,
 }
 
 impl Lifetime {
-    pub fn new(s: &str, span: Span) -> Self {
-        if !s.starts_with('\'') {
+    /// # Panics
+    ///
+    /// Panics if the lifetime does not conform to the bulleted rules above.
+    ///
+    /// # Invocation
+    ///
+    /// ```
+    /// # extern crate proc_macro2;
+    /// # extern crate syn;
+    /// #
+    /// # use proc_macro2::Span;
+    /// # use syn::Lifetime;
+    /// #
+    /// # fn f() -> Lifetime {
+    /// Lifetime::new("'a", Span::call_site())
+    /// # }
+    /// ```
+    pub fn new(symbol: &str, span: Span) -> Self {
+        if !symbol.starts_with('\'') {
             panic!(
                 "lifetime name must start with apostrophe as in \"'a\", got {:?}",
-                s
+                symbol
             );
         }
 
-        if s == "'" {
+        if symbol == "'" {
             panic!("lifetime name must not be empty");
         }
 
-        fn xid_ok(s: &str) -> bool {
-            let mut chars = s.chars();
+        fn xid_ok(symbol: &str) -> bool {
+            let mut chars = symbol.chars();
             let first = chars.next().unwrap();
             if !(UnicodeXID::is_xid_start(first) || first == '_') {
                 return false;
@@ -62,13 +80,13 @@
             true
         }
 
-        if !xid_ok(&s[1..]) {
-            panic!("{:?} is not a valid lifetime name", s);
+        if !xid_ok(&symbol[1..]) {
+            panic!("{:?} is not a valid lifetime name", symbol);
         }
 
         Lifetime {
-            apostrophe: Apostrophe::default(),
-            ident: Ident::new(&s[1..], span),
+            apostrophe: span,
+            ident: Ident::new(&symbol[1..], span),
         }
     }
 }
@@ -107,30 +125,25 @@
 }
 
 #[cfg(feature = "parsing")]
+#[doc(hidden)]
+#[allow(non_snake_case)]
+pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
+    match marker {}
+}
+
+#[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use buffer::Cursor;
-    use parse_error;
-    use synom::PResult;
-    use synom::Synom;
 
-    impl Synom for Lifetime {
-        fn parse(input: Cursor) -> PResult<Self> {
-            let (apostrophe, rest) = Apostrophe::parse(input)?;
-            let (ident, rest) = match rest.ident() {
-                Some(pair) => pair,
-                None => return parse_error(),
-            };
+    use parse::{Parse, ParseStream, Result};
 
-            let ret = Lifetime {
-                ident: ident,
-                apostrophe: apostrophe,
-            };
-            Ok((ret, rest))
-        }
-
-        fn description() -> Option<&'static str> {
-            Some("lifetime")
+    impl Parse for Lifetime {
+        fn parse(input: ParseStream) -> Result<Self> {
+            input.step(|cursor| {
+                cursor
+                    .lifetime()
+                    .ok_or_else(|| cursor.error("expected lifetime"))
+            })
         }
     }
 }
@@ -138,12 +151,15 @@
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
-    use proc_macro2::TokenStream;
-    use quote::ToTokens;
+
+    use proc_macro2::{Punct, Spacing, TokenStream};
+    use quote::{ToTokens, TokenStreamExt};
 
     impl ToTokens for Lifetime {
         fn to_tokens(&self, tokens: &mut TokenStream) {
-            self.apostrophe.to_tokens(tokens);
+            let mut apostrophe = Punct::new('\'', Spacing::Joint);
+            apostrophe.set_span(self.apostrophe);
+            tokens.append(apostrophe);
             self.ident.to_tokens(tokens);
         }
     }
diff --git a/src/lit.rs b/src/lit.rs
index 47555d4..52d1156 100644
--- a/src/lit.rs
+++ b/src/lit.rs
@@ -15,13 +15,18 @@
 #[cfg(feature = "parsing")]
 use proc_macro2::TokenStream;
 #[cfg(feature = "parsing")]
-use {ParseError, Synom};
+use Error;
 
 use proc_macro2::TokenTree;
 
 #[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
 
+#[cfg(feature = "parsing")]
+use lookahead;
+#[cfg(feature = "parsing")]
+use parse::Parse;
+
 ast_enum_of_structs! {
     /// A Rust literal such as a string or integer or boolean.
     ///
@@ -121,13 +126,54 @@
     /// Parse a syntax tree node from the content of this string literal.
     ///
     /// All spans in the syntax tree will point to the span of this `LitStr`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate proc_macro2;
+    /// # extern crate syn;
+    /// #
+    /// use proc_macro2::Span;
+    /// use syn::{Attribute, Ident, Lit, Meta, MetaNameValue, Path};
+    /// use syn::parse::{Error, Result};
+    ///
+    /// // Parses the path from an attribute that looks like:
+    /// //
+    /// //     #[path = "a::b::c"]
+    /// //
+    /// // or returns the path `Self` as a default if the attribute is not of
+    /// // that form.
+    /// fn get_path(attr: &Attribute) -> Result<Path> {
+    ///     let default = || Path::from(Ident::new("Self", Span::call_site()));
+    ///
+    ///     let meta = match attr.interpret_meta() {
+    ///         Some(meta) => meta,
+    ///         None => return Ok(default()),
+    ///     };
+    ///
+    ///     if meta.name() != "path" {
+    ///         return Ok(default());
+    ///     }
+    ///
+    ///     match meta {
+    ///         Meta::NameValue(MetaNameValue { lit: Lit::Str(lit_str), .. }) => {
+    ///             lit_str.parse()
+    ///         }
+    ///         _ => {
+    ///             let error_span = attr.bracket_token.span;
+    ///             let message = "expected #[path = \"...\"]";
+    ///             Err(Error::new(error_span, message))
+    ///         }
+    ///     }
+    /// }
+    /// ```
     #[cfg(feature = "parsing")]
-    pub fn parse<T: Synom>(&self) -> Result<T, ParseError> {
+    pub fn parse<T: Parse>(&self) -> Result<T, Error> {
         use proc_macro2::Group;
 
         // Parse string literal into a token stream with every span equal to the
         // original literal's span.
-        fn spanned_tokens(s: &LitStr) -> Result<TokenStream, ParseError> {
+        fn spanned_tokens(s: &LitStr) -> Result<TokenStream, Error> {
             let stream = ::parse_str(&s.value())?;
             Ok(respan_token_stream(stream, s.span()))
         }
@@ -337,6 +383,13 @@
                 self.$field.to_string().hash(state);
             }
         }
+
+        #[cfg(feature = "parsing")]
+        #[doc(hidden)]
+        #[allow(non_snake_case)]
+        pub fn $ty(marker: lookahead::TokenMarker) -> $ty {
+            match marker {}
+        }
     };
 }
 
@@ -411,96 +464,111 @@
 }
 
 #[cfg(feature = "parsing")]
+#[doc(hidden)]
+#[allow(non_snake_case)]
+pub fn Lit(marker: lookahead::TokenMarker) -> Lit {
+    match marker {}
+}
+
+#[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use buffer::Cursor;
-    use parse_error;
-    use synom::PResult;
-    use synom::Synom;
+    use parse::{Parse, ParseStream, Result};
 
-    impl Synom for Lit {
-        fn parse(input: Cursor) -> PResult<Self> {
-            match input.literal() {
-                Some((lit, rest)) => {
-                    if lit.to_string().starts_with('/') {
-                        // Doc comment literal which is not a Syn literal
-                        parse_error()
-                    } else {
-                        Ok((Lit::new(lit), rest))
-                    }
+    impl Parse for Lit {
+        fn parse(input: ParseStream) -> Result<Self> {
+            input.step(|cursor| {
+                if let Some((lit, rest)) = cursor.literal() {
+                    return Ok((Lit::new(lit), rest));
                 }
-                _ => match input.ident() {
-                    Some((ident, rest)) => Ok((
-                        Lit::Bool(LitBool {
-                            value: if ident == "true" {
-                                true
-                            } else if ident == "false" {
-                                false
-                            } else {
-                                return parse_error();
-                            },
-                            span: ident.span(),
-                        }),
-                        rest,
-                    )),
-                    _ => parse_error(),
-                },
-            }
-        }
-
-        fn description() -> Option<&'static str> {
-            Some("literal")
+                while let Some((ident, rest)) = cursor.ident() {
+                    let value = if ident == "true" {
+                        true
+                    } else if ident == "false" {
+                        false
+                    } else {
+                        break;
+                    };
+                    let lit_bool = LitBool {
+                        value: value,
+                        span: ident.span(),
+                    };
+                    return Ok((Lit::Bool(lit_bool), rest));
+                }
+                Err(cursor.error("expected literal"))
+            })
         }
     }
 
-    impl_synom!(LitStr "string literal" switch!(
-        syn!(Lit),
-        Lit::Str(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitStr {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Str(lit) => Ok(lit),
+                _ => Err(head.error("expected string literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitByteStr "byte string literal" switch!(
-        syn!(Lit),
-        Lit::ByteStr(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitByteStr {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::ByteStr(lit) => Ok(lit),
+                _ => Err(head.error("expected byte string literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitByte "byte literal" switch!(
-        syn!(Lit),
-        Lit::Byte(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitByte {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Byte(lit) => Ok(lit),
+                _ => Err(head.error("expected byte literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitChar "character literal" switch!(
-        syn!(Lit),
-        Lit::Char(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitChar {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Char(lit) => Ok(lit),
+                _ => Err(head.error("expected character literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitInt "integer literal" switch!(
-        syn!(Lit),
-        Lit::Int(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitInt {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Int(lit) => Ok(lit),
+                _ => Err(head.error("expected integer literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitFloat "floating point literal" switch!(
-        syn!(Lit),
-        Lit::Float(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitFloat {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Float(lit) => Ok(lit),
+                _ => Err(head.error("expected floating point literal")),
+            }
+        }
+    }
 
-    impl_synom!(LitBool "boolean literal" switch!(
-        syn!(Lit),
-        Lit::Bool(lit) => value!(lit)
-        |
-        _ => reject!()
-    ));
+    impl Parse for LitBool {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let head = input.fork();
+            match input.parse()? {
+                Lit::Bool(lit) => Ok(lit),
+                _ => Err(head.error("expected boolean literal")),
+            }
+        }
+    }
 }
 
 #[cfg(feature = "printing")]
diff --git a/src/lookahead.rs b/src/lookahead.rs
new file mode 100644
index 0000000..5a3c901
--- /dev/null
+++ b/src/lookahead.rs
@@ -0,0 +1,168 @@
+use std::cell::RefCell;
+
+use proc_macro2::{Delimiter, Span};
+
+use buffer::Cursor;
+use error::{self, Error};
+use span::IntoSpans;
+use token::Token;
+
+/// Support for checking the next token in a stream to decide how to parse.
+///
+/// An important advantage over [`ParseStream::peek`] is that here we
+/// automatically construct an appropriate error message based on the token
+/// alternatives that get peeked. If you are producing your own error message,
+/// go ahead and use `ParseStream::peek` instead.
+///
+/// Use [`ParseStream::lookahead1`] to construct this object.
+///
+/// [`ParseStream::peek`]: struct.ParseBuffer.html#method.peek
+/// [`ParseStream::lookahead1`]: struct.ParseBuffer.html#method.lookahead1
+///
+/// # Example
+///
+/// ```
+/// # extern crate syn;
+/// #
+/// use syn::{ConstParam, Ident, Lifetime, LifetimeDef, Token, TypeParam};
+/// use syn::parse::{Parse, ParseStream, Result};
+///
+/// // A generic parameter, a single one of the comma-separated elements inside
+/// // angle brackets in:
+/// //
+/// //     fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
+/// //
+/// // On invalid input, lookahead gives us a reasonable error message.
+/// //
+/// //     error: expected one of: identifier, lifetime, `const`
+/// //       |
+/// //     5 |     fn f<!Sized>() {}
+/// //       |          ^
+/// enum GenericParam {
+///     Type(TypeParam),
+///     Lifetime(LifetimeDef),
+///     Const(ConstParam),
+/// }
+///
+/// impl Parse for GenericParam {
+///     fn parse(input: ParseStream) -> Result<Self> {
+///         let lookahead = input.lookahead1();
+///         if lookahead.peek(Ident) {
+///             input.parse().map(GenericParam::Type)
+///         } else if lookahead.peek(Lifetime) {
+///             input.parse().map(GenericParam::Lifetime)
+///         } else if lookahead.peek(Token![const]) {
+///             input.parse().map(GenericParam::Const)
+///         } else {
+///             Err(lookahead.error())
+///         }
+///     }
+/// }
+/// #
+/// # fn main() {}
+/// ```
+pub struct Lookahead1<'a> {
+    scope: Span,
+    cursor: Cursor<'a>,
+    comparisons: RefCell<Vec<&'static str>>,
+}
+
+pub fn new(scope: Span, cursor: Cursor) -> Lookahead1 {
+    Lookahead1 {
+        scope: scope,
+        cursor: cursor,
+        comparisons: RefCell::new(Vec::new()),
+    }
+}
+
+fn peek_impl(
+    lookahead: &Lookahead1,
+    peek: fn(Cursor) -> bool,
+    display: fn() -> &'static str,
+) -> bool {
+    if peek(lookahead.cursor) {
+        return true;
+    }
+    lookahead.comparisons.borrow_mut().push(display());
+    false
+}
+
+impl<'a> Lookahead1<'a> {
+    /// Looks at the next token in the parse stream to determine whether it
+    /// matches the requested type of token.
+    ///
+    /// # Syntax
+    ///
+    /// Note that this method does not use turbofish syntax. Pass the peek type
+    /// inside of parentheses.
+    ///
+    /// - `input.peek(Token![struct])`
+    /// - `input.peek(Token![==])`
+    /// - `input.peek(Ident)`
+    /// - `input.peek(Lifetime)`
+    /// - `input.peek(token::Brace)`
+    pub fn peek<T: Peek>(&self, token: T) -> bool {
+        let _ = token;
+        peek_impl(self, T::Token::peek, T::Token::display)
+    }
+
+    /// Triggers an error at the current position of the parse stream.
+    ///
+    /// The error message will identify all of the expected token types that
+    /// have been peeked against this lookahead instance.
+    pub fn error(self) -> Error {
+        let comparisons = self.comparisons.borrow();
+        match comparisons.len() {
+            0 => if self.cursor.eof() {
+                Error::new(self.scope, "unexpected end of input")
+            } else {
+                Error::new(self.cursor.span(), "unexpected token")
+            },
+            1 => {
+                let message = format!("expected {}", comparisons[0]);
+                error::new_at(self.scope, self.cursor, message)
+            }
+            _ => {
+                let join = comparisons.join(", ");
+                let message = format!("expected one of: {}", join);
+                error::new_at(self.scope, self.cursor, message)
+            }
+        }
+    }
+}
+
+/// Types that can be parsed by looking at just one token.
+///
+/// Use [`ParseStream::peek`] to peek one of these types in a parse stream
+/// without consuming it from the stream.
+///
+/// This trait is sealed and cannot be implemented for types outside of Syn.
+///
+/// [`ParseStream::peek`]: struct.ParseBuffer.html#method.peek
+pub trait Peek: private::Sealed {
+    // Not public API.
+    #[doc(hidden)]
+    type Token: Token;
+}
+
+impl<F: FnOnce(TokenMarker) -> T, T: Token> Peek for F {
+    type Token = T;
+}
+
+pub enum TokenMarker {}
+
+impl<S> IntoSpans<S> for TokenMarker {
+    fn into_spans(self) -> S {
+        match self {}
+    }
+}
+
+pub fn is_delimiter(cursor: Cursor, delimiter: Delimiter) -> bool {
+    cursor.group(delimiter).is_some()
+}
+
+mod private {
+    use super::{Token, TokenMarker};
+    pub trait Sealed {}
+    impl<F: FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}
+}
diff --git a/src/mac.rs b/src/mac.rs
index a9219fe..4bffb55 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -8,8 +8,12 @@
 
 use super::*;
 use proc_macro2::TokenStream;
+#[cfg(feature = "parsing")]
+use proc_macro2::{Delimiter, TokenTree};
 use token::{Brace, Bracket, Paren};
 
+#[cfg(feature = "parsing")]
+use parse::{ParseStream, Result};
 #[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
 #[cfg(feature = "extra-traits")]
@@ -67,26 +71,44 @@
 }
 
 #[cfg(feature = "parsing")]
+pub fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStream)> {
+    input.step(|cursor| {
+        if let Some((TokenTree::Group(g), rest)) = cursor.token_tree() {
+            let span = g.span();
+            let delimiter = match g.delimiter() {
+                Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
+                Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
+                Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
+                Delimiter::None => {
+                    return Err(cursor.error("expected delimiter"));
+                }
+            };
+            Ok(((delimiter, g.stream().clone()), rest))
+        } else {
+            Err(cursor.error("expected delimiter"))
+        }
+    })
+}
+
+#[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
 
-    use synom::Synom;
+    use parse::{Parse, ParseStream, Result};
 
-    impl Synom for Macro {
-        named!(parse -> Self, do_parse!(
-            what: call!(Path::parse_mod_style) >>
-            bang: punct!(!) >>
-            body: call!(tt::delimited) >>
-            (Macro {
-                path: what,
-                bang_token: bang,
-                delimiter: body.0,
-                tts: body.1,
+    impl Parse for Macro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let tts;
+            Ok(Macro {
+                path: input.call(Path::parse_mod_style)?,
+                bang_token: input.parse()?,
+                delimiter: {
+                    let (delimiter, content) = parse_delimiter(input)?;
+                    tts = content;
+                    delimiter
+                },
+                tts: tts,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("macro invocation")
         }
     }
 }
diff --git a/src/macros.rs b/src/macros.rs
index f4e7d0a..519c73c 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -178,19 +178,3 @@
 
     ($($rest:tt)*) => (ast_struct! { $($rest)* });
 }
-
-#[cfg(all(
-    feature = "parsing",
-    any(feature = "full", feature = "derive")
-))]
-macro_rules! impl_synom {
-    ($t:ident $description:tt $($parser:tt)+) => {
-        impl Synom for $t {
-            named!(parse -> Self, $($parser)+);
-
-            fn description() -> Option<&'static str> {
-                Some($description)
-            }
-        }
-    }
-}
diff --git a/src/op.rs b/src/op.rs
index a5188d0..c777242 100644
--- a/src/op.rs
+++ b/src/op.rs
@@ -91,82 +91,97 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use synom::Synom;
 
-    impl BinOp {
-        named!(pub parse_binop -> Self, alt!(
-            punct!(&&) => { BinOp::And }
-            |
-            punct!(||) => { BinOp::Or }
-            |
-            punct!(<<) => { BinOp::Shl }
-            |
-            punct!(>>) => { BinOp::Shr }
-            |
-            punct!(==) => { BinOp::Eq }
-            |
-            punct!(<=) => { BinOp::Le }
-            |
-            punct!(!=) => { BinOp::Ne }
-            |
-            punct!(>=) => { BinOp::Ge }
-            |
-            punct!(+) => { BinOp::Add }
-            |
-            punct!(-) => { BinOp::Sub }
-            |
-            punct!(*) => { BinOp::Mul }
-            |
-            punct!(/) => { BinOp::Div }
-            |
-            punct!(%) => { BinOp::Rem }
-            |
-            punct!(^) => { BinOp::BitXor }
-            |
-            punct!(&) => { BinOp::BitAnd }
-            |
-            punct!(|) => { BinOp::BitOr }
-            |
-            punct!(<) => { BinOp::Lt }
-            |
-            punct!(>) => { BinOp::Gt }
-        ));
+    use parse::{Parse, ParseStream, Result};
 
-        #[cfg(feature = "full")]
-        named!(pub parse_assign_op -> Self, alt!(
-            punct!(+=) => { BinOp::AddEq }
-            |
-            punct!(-=) => { BinOp::SubEq }
-            |
-            punct!(*=) => { BinOp::MulEq }
-            |
-            punct!(/=) => { BinOp::DivEq }
-            |
-            punct!(%=) => { BinOp::RemEq }
-            |
-            punct!(^=) => { BinOp::BitXorEq }
-            |
-            punct!(&=) => { BinOp::BitAndEq }
-            |
-            punct!(|=) => { BinOp::BitOrEq }
-            |
-            punct!(<<=) => { BinOp::ShlEq }
-            |
-            punct!(>>=) => { BinOp::ShrEq }
-        ));
+    fn parse_binop(input: ParseStream) -> Result<BinOp> {
+        if input.peek(Token![&&]) {
+            input.parse().map(BinOp::And)
+        } else if input.peek(Token![||]) {
+            input.parse().map(BinOp::Or)
+        } else if input.peek(Token![<<]) {
+            input.parse().map(BinOp::Shl)
+        } else if input.peek(Token![>>]) {
+            input.parse().map(BinOp::Shr)
+        } else if input.peek(Token![==]) {
+            input.parse().map(BinOp::Eq)
+        } else if input.peek(Token![<=]) {
+            input.parse().map(BinOp::Le)
+        } else if input.peek(Token![!=]) {
+            input.parse().map(BinOp::Ne)
+        } else if input.peek(Token![>=]) {
+            input.parse().map(BinOp::Ge)
+        } else if input.peek(Token![+]) {
+            input.parse().map(BinOp::Add)
+        } else if input.peek(Token![-]) {
+            input.parse().map(BinOp::Sub)
+        } else if input.peek(Token![*]) {
+            input.parse().map(BinOp::Mul)
+        } else if input.peek(Token![/]) {
+            input.parse().map(BinOp::Div)
+        } else if input.peek(Token![%]) {
+            input.parse().map(BinOp::Rem)
+        } else if input.peek(Token![^]) {
+            input.parse().map(BinOp::BitXor)
+        } else if input.peek(Token![&]) {
+            input.parse().map(BinOp::BitAnd)
+        } else if input.peek(Token![|]) {
+            input.parse().map(BinOp::BitOr)
+        } else if input.peek(Token![<]) {
+            input.parse().map(BinOp::Lt)
+        } else if input.peek(Token![>]) {
+            input.parse().map(BinOp::Gt)
+        } else {
+            Err(input.error("expected binary operator"))
+        }
     }
 
-    impl Synom for UnOp {
-        named!(parse -> Self, alt!(
-            punct!(*) => { UnOp::Deref }
-            |
-            punct!(!) => { UnOp::Not }
-            |
-            punct!(-) => { UnOp::Neg }
-        ));
+    impl Parse for BinOp {
+        #[cfg(not(feature = "full"))]
+        fn parse(input: ParseStream) -> Result<Self> {
+            parse_binop(input)
+        }
 
-        fn description() -> Option<&'static str> {
-            Some("unary operator: `*`, `!`, or `-`")
+        #[cfg(feature = "full")]
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![+=]) {
+                input.parse().map(BinOp::AddEq)
+            } else if input.peek(Token![-=]) {
+                input.parse().map(BinOp::SubEq)
+            } else if input.peek(Token![*=]) {
+                input.parse().map(BinOp::MulEq)
+            } else if input.peek(Token![/=]) {
+                input.parse().map(BinOp::DivEq)
+            } else if input.peek(Token![%=]) {
+                input.parse().map(BinOp::RemEq)
+            } else if input.peek(Token![^=]) {
+                input.parse().map(BinOp::BitXorEq)
+            } else if input.peek(Token![&=]) {
+                input.parse().map(BinOp::BitAndEq)
+            } else if input.peek(Token![|=]) {
+                input.parse().map(BinOp::BitOrEq)
+            } else if input.peek(Token![<<=]) {
+                input.parse().map(BinOp::ShlEq)
+            } else if input.peek(Token![>>=]) {
+                input.parse().map(BinOp::ShrEq)
+            } else {
+                parse_binop(input)
+            }
+        }
+    }
+
+    impl Parse for UnOp {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![*]) {
+                input.parse().map(UnOp::Deref)
+            } else if lookahead.peek(Token![!]) {
+                input.parse().map(UnOp::Not)
+            } else if lookahead.peek(Token![-]) {
+                input.parse().map(UnOp::Neg)
+            } else {
+                Err(lookahead.error())
+            }
         }
     }
 }
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 0000000..c063d4e
--- /dev/null
+++ b/src/parse.rs
@@ -0,0 +1,1043 @@
+// Copyright 2018 Syn Developers
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Parsing interface for parsing a token stream into a syntax tree node.
+//!
+//! Parsing in Syn is built on parser functions that take in a [`ParseStream`]
+//! and produce a [`Result<T>`] where `T` is some syntax tree node. Underlying
+//! these parser functions is a lower level mechanism built around the
+//! [`Cursor`] type. `Cursor` is a cheaply copyable cursor over a range of
+//! tokens in a token stream.
+//!
+//! [`ParseStream`]: type.ParseStream.html
+//! [`Result<T>`]: type.Result.html
+//! [`Cursor`]: ../buffer/index.html
+//!
+//! # Example
+//!
+//! Here is a snippet of parsing code to get a feel for the style of the
+//! library. We define data structures for a subset of Rust syntax including
+//! enums (not shown) and structs, then provide implementations of the [`Parse`]
+//! trait to parse these syntax tree data structures from a token stream.
+//!
+//! Once `Parse` impls have been defined, they can be called conveniently from a
+//! procedural macro as shown at the bottom of the snippet. If the caller
+//! provides syntactically invalid input to the procedural macro, they will
+//! receive a helpful compiler error message pointing out the exact token that
+//! triggered the failure to parse.
+//!
+//! ```
+//! # extern crate proc_macro;
+//! # extern crate syn;
+//! #
+//! use proc_macro::TokenStream;
+//! use syn::{braced, parse_macro_input, token, Field, Ident, Token};
+//! use syn::parse::{Parse, ParseStream, Result};
+//! use syn::punctuated::Punctuated;
+//!
+//! enum Item {
+//!     Struct(ItemStruct),
+//!     Enum(ItemEnum),
+//! }
+//!
+//! struct ItemStruct {
+//!     struct_token: Token![struct],
+//!     ident: Ident,
+//!     brace_token: token::Brace,
+//!     fields: Punctuated<Field, Token![,]>,
+//! }
+//! #
+//! # enum ItemEnum {}
+//!
+//! impl Parse for Item {
+//!     fn parse(input: ParseStream) -> Result<Self> {
+//!         let lookahead = input.lookahead1();
+//!         if lookahead.peek(Token![struct]) {
+//!             input.parse().map(Item::Struct)
+//!         } else if lookahead.peek(Token![enum]) {
+//!             input.parse().map(Item::Enum)
+//!         } else {
+//!             Err(lookahead.error())
+//!         }
+//!     }
+//! }
+//!
+//! impl Parse for ItemStruct {
+//!     fn parse(input: ParseStream) -> Result<Self> {
+//!         let content;
+//!         Ok(ItemStruct {
+//!             struct_token: input.parse()?,
+//!             ident: input.parse()?,
+//!             brace_token: braced!(content in input),
+//!             fields: content.parse_terminated(Field::parse_named)?,
+//!         })
+//!     }
+//! }
+//! #
+//! # impl Parse for ItemEnum {
+//! #     fn parse(input: ParseStream) -> Result<Self> {
+//! #         unimplemented!()
+//! #     }
+//! # }
+//!
+//! # const IGNORE: &str = stringify! {
+//! #[proc_macro]
+//! # };
+//! pub fn my_macro(tokens: TokenStream) -> TokenStream {
+//!     let input = parse_macro_input!(tokens as Item);
+//!
+//!     /* ... */
+//! #   "".parse().unwrap()
+//! }
+//! #
+//! # fn main() {}
+//! ```
+//!
+//! # The `syn::parse*` functions
+//!
+//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
+//! as an entry point for parsing syntax tree nodes that can be parsed in an
+//! obvious default way. These functions can return any syntax tree node that
+//! implements the [`Parse`] trait, which includes most types in Syn.
+//!
+//! [`syn::parse`]: ../fn.parse.html
+//! [`syn::parse2`]: ../fn.parse2.html
+//! [`syn::parse_str`]: ../fn.parse_str.html
+//! [`Parse`]: trait.Parse.html
+//!
+//! ```
+//! use syn::Type;
+//!
+//! # fn run_parser() -> Result<(), syn::parse::Error> {
+//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
+//! #     Ok(())
+//! # }
+//! #
+//! # fn main() {
+//! #     run_parser().unwrap();
+//! # }
+//! ```
+//!
+//! The [`parse_quote!`] macro also uses this approach.
+//!
+//! [`parse_quote!`]: ../macro.parse_quote.html
+//!
+//! # The `Parser` trait
+//!
+//! Some types can be parsed in several ways depending on context. For example
+//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
+//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
+//! may or may not allow trailing punctuation, and parsing it the wrong way
+//! would either reject valid input or accept invalid input.
+//!
+//! [`Attribute`]: ../struct.Attribute.html
+//! [`Punctuated`]: ../punctuated/index.html
+//!
+//! The `Parse` trait is not implemented in these cases because there is no good
+//! behavior to consider the default.
+//!
+//! ```ignore
+//! // Can't parse `Punctuated` without knowing whether trailing punctuation
+//! // should be allowed in this context.
+//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
+//! ```
+//!
+//! In these cases the types provide a choice of parser functions rather than a
+//! single `Parse` implementation, and those parser functions can be invoked
+//! through the [`Parser`] trait.
+//!
+//! [`Parser`]: trait.Parser.html
+//!
+//! ```
+//! # extern crate syn;
+//! #
+//! # extern crate proc_macro2;
+//! # use proc_macro2::TokenStream;
+//! #
+//! use syn::parse::Parser;
+//! use syn::punctuated::Punctuated;
+//! use syn::{Attribute, Expr, PathSegment, Token};
+//!
+//! # fn run_parsers() -> Result<(), syn::parse::Error> {
+//! #     let tokens = TokenStream::new().into();
+//! // Parse a nonempty sequence of path segments separated by `::` punctuation
+//! // with no trailing punctuation.
+//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
+//! let path = parser.parse(tokens)?;
+//!
+//! #     let tokens = TokenStream::new().into();
+//! // Parse a possibly empty sequence of expressions terminated by commas with
+//! // an optional trailing punctuation.
+//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
+//! let args = parser.parse(tokens)?;
+//!
+//! #     let tokens = TokenStream::new().into();
+//! // Parse zero or more outer attributes but not inner attributes.
+//! let parser = Attribute::parse_outer;
+//! let attrs = parser.parse(tokens)?;
+//! #
+//! #     Ok(())
+//! # }
+//! #
+//! # fn main() {}
+//! ```
+//!
+//! ---
+//!
+//! *This module is available if Syn is built with the `"parsing"` feature.*
+
+use std::cell::Cell;
+use std::fmt::Display;
+use std::marker::PhantomData;
+use std::mem;
+use std::ops::Deref;
+use std::rc::Rc;
+use std::str::FromStr;
+
+#[cfg(all(
+    not(all(target_arch = "wasm32", target_os = "unknown")),
+    feature = "proc-macro"
+))]
+use proc_macro;
+use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
+
+use buffer::{Cursor, TokenBuffer};
+use error;
+use lookahead;
+use private;
+use punctuated::Punctuated;
+use token::Token;
+
+pub use error::{Error, Result};
+pub use lookahead::{Lookahead1, Peek};
+
+/// Parsing interface implemented by all types that can be parsed in a default
+/// way from a token stream.
+pub trait Parse: Sized {
+    fn parse(input: ParseStream) -> Result<Self>;
+}
+
+/// Input to a Syn parser function.
+///
+/// See the methods of this type under the documentation of [`ParseBuffer`]. For
+/// an overview of parsing in Syn, refer to the [module documentation].
+///
+/// [module documentation]: index.html
+pub type ParseStream<'a> = &'a ParseBuffer<'a>;
+
+/// Cursor position within a buffered token stream.
+///
+/// This type is more commonly used through the type alias [`ParseStream`] which
+/// is an alias for `&ParseBuffer`.
+///
+/// `ParseStream` is the input type for all parser functions in Syn. They have
+/// the signature `fn(ParseStream) -> Result<T>`.
+pub struct ParseBuffer<'a> {
+    scope: Span,
+    cell: Cell<Cursor<'static>>,
+    marker: PhantomData<Cursor<'a>>,
+    unexpected: Rc<Cell<Option<Span>>>,
+}
+
+impl<'a> Drop for ParseBuffer<'a> {
+    fn drop(&mut self) {
+        if !self.is_empty() && self.unexpected.get().is_none() {
+            self.unexpected.set(Some(self.cursor().span()));
+        }
+    }
+}
+
+/// Cursor state associated with speculative parsing.
+///
+/// This type is the input of the closure provided to [`ParseStream::step`].
+///
+/// [`ParseStream::step`]: struct.ParseBuffer.html#method.step
+///
+/// # Example
+///
+/// ```
+/// # extern crate proc_macro2;
+/// # extern crate syn;
+/// #
+/// use proc_macro2::TokenTree;
+/// use syn::parse::{ParseStream, Result};
+///
+/// // This function advances the stream past the next occurrence of `@`. If
+/// // no `@` is present in the stream, the stream position is unchanged and
+/// // an error is returned.
+/// fn skip_past_next_at(input: ParseStream) -> Result<()> {
+///     input.step(|cursor| {
+///         let mut rest = *cursor;
+///         while let Some((tt, next)) = cursor.token_tree() {
+///             match tt {
+///                 TokenTree::Punct(ref punct) if punct.as_char() == '@' => {
+///                     return Ok(((), next));
+///                 }
+///                 _ => rest = next,
+///             }
+///         }
+///         Err(cursor.error("no `@` was found after this point"))
+///     })
+/// }
+/// #
+/// # fn main() {}
+/// ```
+#[derive(Copy, Clone)]
+pub struct StepCursor<'c, 'a> {
+    scope: Span,
+    cursor: Cursor<'c>,
+    marker: PhantomData<fn(Cursor<'c>) -> Cursor<'a>>,
+}
+
+impl<'c, 'a> Deref for StepCursor<'c, 'a> {
+    type Target = Cursor<'c>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.cursor
+    }
+}
+
+impl<'c, 'a> StepCursor<'c, 'a> {
+    /// Triggers an error at the current position of the parse stream.
+    ///
+    /// The `ParseStream::step` invocation will return this same error without
+    /// advancing the stream state.
+    pub fn error<T: Display>(self, message: T) -> Error {
+        error::new_at(self.scope, self.cursor, message)
+    }
+}
+
+impl private {
+    pub fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> {
+        let _ = proof;
+        unsafe { mem::transmute::<Cursor<'c>, Cursor<'a>>(to) }
+    }
+}
+
+fn skip(input: ParseStream) -> bool {
+    input
+        .step(|cursor| {
+            if let Some((_lifetime, rest)) = cursor.lifetime() {
+                Ok((true, rest))
+            } else if let Some((_token, rest)) = cursor.token_tree() {
+                Ok((true, rest))
+            } else {
+                Ok((false, *cursor))
+            }
+        }).unwrap()
+}
+
+impl private {
+    pub fn new_parse_buffer(
+        scope: Span,
+        cursor: Cursor,
+        unexpected: Rc<Cell<Option<Span>>>,
+    ) -> ParseBuffer {
+        let extend = unsafe { mem::transmute::<Cursor, Cursor<'static>>(cursor) };
+        ParseBuffer {
+            scope: scope,
+            cell: Cell::new(extend),
+            marker: PhantomData,
+            unexpected: unexpected,
+        }
+    }
+
+    pub fn get_unexpected(buffer: &ParseBuffer) -> Rc<Cell<Option<Span>>> {
+        buffer.unexpected.clone()
+    }
+}
+
+impl<'a> ParseBuffer<'a> {
+    /// Parses a syntax tree node of type `T`, advancing the position of our
+    /// parse stream past it.
+    pub fn parse<T: Parse>(&self) -> Result<T> {
+        T::parse(self)
+    }
+
+    /// Calls the given parser function to parse a syntax tree node of type `T`
+    /// from this stream.
+    ///
+    /// # Example
+    ///
+    /// The parser below invokes [`Attribute::parse_outer`] to parse a vector of
+    /// zero or more outer attributes.
+    ///
+    /// [`Attribute::parse_outer`]: ../struct.Attribute.html#method.parse_outer
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{Attribute, Ident, Token};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    ///
+    /// // Parses a unit struct with attributes.
+    /// //
+    /// //     #[path = "s.tmpl"]
+    /// //     struct S;
+    /// struct UnitStruct {
+    ///     attrs: Vec<Attribute>,
+    ///     struct_token: Token![struct],
+    ///     name: Ident,
+    ///     semi_token: Token![;],
+    /// }
+    ///
+    /// impl Parse for UnitStruct {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         Ok(UnitStruct {
+    ///             attrs: input.call(Attribute::parse_outer)?,
+    ///             struct_token: input.parse()?,
+    ///             name: input.parse()?,
+    ///             semi_token: input.parse()?,
+    ///         })
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    pub fn call<T>(&self, function: fn(ParseStream) -> Result<T>) -> Result<T> {
+        function(self)
+    }
+
+    /// Looks at the next token in the parse stream to determine whether it
+    /// matches the requested type of token.
+    ///
+    /// Does not advance the position of the parse stream.
+    ///
+    /// # Syntax
+    ///
+    /// Note that this method does not use turbofish syntax. Pass the peek type
+    /// inside of parentheses.
+    ///
+    /// - `input.peek(Token![struct])`
+    /// - `input.peek(Token![==])`
+    /// - `input.peek(Ident)`
+    /// - `input.peek(Lifetime)`
+    /// - `input.peek(token::Brace)`
+    ///
+    /// # Example
+    ///
+    /// In this example we finish parsing the list of supertraits when the next
+    /// token in the input is either `where` or an opening curly brace.
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{braced, token, Generics, Ident, Token, TypeParamBound};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    /// use syn::punctuated::Punctuated;
+    ///
+    /// // Parses a trait definition containing no associated items.
+    /// //
+    /// //     trait Marker<'de, T>: A + B<'de> where Box<T>: Clone {}
+    /// struct MarkerTrait {
+    ///     trait_token: Token![trait],
+    ///     ident: Ident,
+    ///     generics: Generics,
+    ///     colon_token: Option<Token![:]>,
+    ///     supertraits: Punctuated<TypeParamBound, Token![+]>,
+    ///     brace_token: token::Brace,
+    /// }
+    ///
+    /// impl Parse for MarkerTrait {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         let trait_token: Token![trait] = input.parse()?;
+    ///         let ident: Ident = input.parse()?;
+    ///         let mut generics: Generics = input.parse()?;
+    ///         let colon_token: Option<Token![:]> = input.parse()?;
+    ///
+    ///         let mut supertraits = Punctuated::new();
+    ///         if colon_token.is_some() {
+    ///             loop {
+    ///                 supertraits.push_value(input.parse()?);
+    ///                 if input.peek(Token![where]) || input.peek(token::Brace) {
+    ///                     break;
+    ///                 }
+    ///                 supertraits.push_punct(input.parse()?);
+    ///             }
+    ///         }
+    ///
+    ///         generics.where_clause = input.parse()?;
+    ///         let content;
+    ///         let empty_brace_token = braced!(content in input);
+    ///
+    ///         Ok(MarkerTrait {
+    ///             trait_token: trait_token,
+    ///             ident: ident,
+    ///             generics: generics,
+    ///             colon_token: colon_token,
+    ///             supertraits: supertraits,
+    ///             brace_token: empty_brace_token,
+    ///         })
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    pub fn peek<T: Peek>(&self, token: T) -> bool {
+        let _ = token;
+        T::Token::peek(self.cursor())
+    }
+
+    /// Looks at the second-next token in the parse stream.
+    ///
+    /// This is commonly useful as a way to implement contextual keywords.
+    ///
+    /// # Example
+    ///
+    /// This example needs to use `peek2` because the symbol `union` is not a
+    /// keyword in Rust. We can't use just `peek` and decide to parse a union if
+    /// the very next token is `union`, because someone is free to write a `mod
+    /// union` and a macro invocation that looks like `union::some_macro! { ...
+    /// }`. In other words `union` is a contextual keyword.
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{Ident, ItemUnion, Macro, Token};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    ///
+    /// // Parses either a union or a macro invocation.
+    /// enum UnionOrMacro {
+    ///     // union MaybeUninit<T> { uninit: (), value: T }
+    ///     Union(ItemUnion),
+    ///     // lazy_static! { ... }
+    ///     Macro(Macro),
+    /// }
+    ///
+    /// impl Parse for UnionOrMacro {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         if input.peek(Token![union]) && input.peek2(Ident) {
+    ///             input.parse().map(UnionOrMacro::Union)
+    ///         } else {
+    ///             input.parse().map(UnionOrMacro::Macro)
+    ///         }
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    pub fn peek2<T: Peek>(&self, token: T) -> bool {
+        let ahead = self.fork();
+        skip(&ahead) && ahead.peek(token)
+    }
+
+    /// Looks at the third-next token in the parse stream.
+    pub fn peek3<T: Peek>(&self, token: T) -> bool {
+        let ahead = self.fork();
+        skip(&ahead) && skip(&ahead) && ahead.peek(token)
+    }
+
+    /// Parses zero or more occurrences of `T` separated by punctuation of type
+    /// `P`, with optional trailing punctuation.
+    ///
+    /// Parsing continues until the end of this parse stream. The entire content
+    /// of this parse stream must consist of `T` and `P`.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # extern crate quote;
+    /// # extern crate syn;
+    /// #
+    /// # use quote::quote;
+    /// #
+    /// use syn::{parenthesized, token, Ident, Token, Type};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    /// use syn::punctuated::Punctuated;
+    ///
+    /// // Parse a simplified tuple struct syntax like:
+    /// //
+    /// //     struct S(A, B);
+    /// struct TupleStruct {
+    ///     struct_token: Token![struct],
+    ///     ident: Ident,
+    ///     paren_token: token::Paren,
+    ///     fields: Punctuated<Type, Token![,]>,
+    ///     semi_token: Token![;],
+    /// }
+    ///
+    /// impl Parse for TupleStruct {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         let content;
+    ///         Ok(TupleStruct {
+    ///             struct_token: input.parse()?,
+    ///             ident: input.parse()?,
+    ///             paren_token: parenthesized!(content in input),
+    ///             fields: content.parse_terminated(Type::parse)?,
+    ///             semi_token: input.parse()?,
+    ///         })
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {
+    /// #     let input = quote! {
+    /// #         struct S(A, B);
+    /// #     };
+    /// #     syn::parse2::<TupleStruct>(input).unwrap();
+    /// # }
+    /// ```
+    pub fn parse_terminated<T, P: Parse>(
+        &self,
+        parser: fn(ParseStream) -> Result<T>,
+    ) -> Result<Punctuated<T, P>> {
+        Punctuated::parse_terminated_with(self, parser)
+    }
+
+    /// Returns whether there are tokens remaining in this stream.
+    ///
+    /// This method returns true at the end of the content of a set of
+    /// delimiters, as well as at the very end of the complete macro input.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// # extern crate syn;
+    /// #
+    /// use syn::{braced, token, Ident, Item, Token};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    ///
+    /// // Parses a Rust `mod m { ... }` containing zero or more items.
+    /// struct Mod {
+    ///     mod_token: Token![mod],
+    ///     name: Ident,
+    ///     brace_token: token::Brace,
+    ///     items: Vec<Item>,
+    /// }
+    ///
+    /// impl Parse for Mod {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         let content;
+    ///         Ok(Mod {
+    ///             mod_token: input.parse()?,
+    ///             name: input.parse()?,
+    ///             brace_token: braced!(content in input),
+    ///             items: {
+    ///                 let mut items = Vec::new();
+    ///                 while !content.is_empty() {
+    ///                     items.push(content.parse()?);
+    ///                 }
+    ///                 items
+    ///             },
+    ///         })
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {}
+    pub fn is_empty(&self) -> bool {
+        self.cursor().eof()
+    }
+
+    /// Constructs a helper for peeking at the next token in this stream and
+    /// building an error message if it is not one of a set of expected tokens.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{ConstParam, Ident, Lifetime, LifetimeDef, Token, TypeParam};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    ///
+    /// // A generic parameter, a single one of the comma-separated elements inside
+    /// // angle brackets in:
+    /// //
+    /// //     fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
+    /// //
+    /// // On invalid input, lookahead gives us a reasonable error message.
+    /// //
+    /// //     error: expected one of: identifier, lifetime, `const`
+    /// //       |
+    /// //     5 |     fn f<!Sized>() {}
+    /// //       |          ^
+    /// enum GenericParam {
+    ///     Type(TypeParam),
+    ///     Lifetime(LifetimeDef),
+    ///     Const(ConstParam),
+    /// }
+    ///
+    /// impl Parse for GenericParam {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         let lookahead = input.lookahead1();
+    ///         if lookahead.peek(Ident) {
+    ///             input.parse().map(GenericParam::Type)
+    ///         } else if lookahead.peek(Lifetime) {
+    ///             input.parse().map(GenericParam::Lifetime)
+    ///         } else if lookahead.peek(Token![const]) {
+    ///             input.parse().map(GenericParam::Const)
+    ///         } else {
+    ///             Err(lookahead.error())
+    ///         }
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    pub fn lookahead1(&self) -> Lookahead1<'a> {
+        lookahead::new(self.scope, self.cursor())
+    }
+
+    /// Forks a parse stream so that parsing tokens out of either the original
+    /// or the fork does not advance the position of the other.
+    ///
+    /// # Performance
+    ///
+    /// Forking a parse stream is a cheap fixed amount of work and does not
+    /// involve copying token buffers. Where you might hit performance problems
+    /// is if your macro ends up parsing a large amount of content more than
+    /// once.
+    ///
+    /// ```
+    /// # use syn::Expr;
+    /// # use syn::parse::{ParseStream, Result};
+    /// #
+    /// # fn bad(input: ParseStream) -> Result<Expr> {
+    /// // Do not do this.
+    /// if input.fork().parse::<Expr>().is_ok() {
+    ///     return input.parse::<Expr>();
+    /// }
+    /// # unimplemented!()
+    /// # }
+    /// ```
+    ///
+    /// As a rule, avoid parsing an unbounded amount of tokens out of a forked
+    /// parse stream. Only use a fork when the amount of work performed against
+    /// the fork is small and bounded.
+    ///
+    /// For a lower level but occasionally more performant way to perform
+    /// speculative parsing, consider using [`ParseStream::step`] instead.
+    ///
+    /// [`ParseStream::step`]: #method.step
+    ///
+    /// # Example
+    ///
+    /// The parse implementation shown here parses possibly restricted `pub`
+    /// visibilities.
+    ///
+    /// - `pub`
+    /// - `pub(crate)`
+    /// - `pub(self)`
+    /// - `pub(super)`
+    /// - `pub(in some::path)`
+    ///
+    /// To handle the case of visibilities inside of tuple structs, the parser
+    /// needs to distinguish parentheses that specify visibility restrictions
+    /// from parentheses that form part of a tuple type.
+    ///
+    /// ```
+    /// # struct A;
+    /// # struct B;
+    /// # struct C;
+    /// #
+    /// struct S(pub(crate) A, pub (B, C));
+    /// ```
+    ///
+    /// In this example input the first tuple struct element of `S` has
+    /// `pub(crate)` visibility while the second tuple struct element has `pub`
+    /// visibility; the parentheses around `(B, C)` are part of the type rather
+    /// than part of a visibility restriction.
+    ///
+    /// The parser uses a forked parse stream to check the first token inside of
+    /// parentheses after the `pub` keyword. This is a small bounded amount of
+    /// work performed against the forked parse stream.
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{parenthesized, token, Ident, Path, Token};
+    /// use syn::ext::IdentExt;
+    /// use syn::parse::{Parse, ParseStream, Result};
+    ///
+    /// struct PubVisibility {
+    ///     pub_token: Token![pub],
+    ///     restricted: Option<Restricted>,
+    /// }
+    ///
+    /// struct Restricted {
+    ///     paren_token: token::Paren,
+    ///     in_token: Option<Token![in]>,
+    ///     path: Path,
+    /// }
+    ///
+    /// impl Parse for PubVisibility {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         let pub_token: Token![pub] = input.parse()?;
+    ///
+    ///         if input.peek(token::Paren) {
+    ///             let ahead = input.fork();
+    ///             let mut content;
+    ///             parenthesized!(content in ahead);
+    ///
+    ///             if content.peek(Token![crate])
+    ///                 || content.peek(Token![self])
+    ///                 || content.peek(Token![super])
+    ///             {
+    ///                 return Ok(PubVisibility {
+    ///                     pub_token: pub_token,
+    ///                     restricted: Some(Restricted {
+    ///                         paren_token: parenthesized!(content in input),
+    ///                         in_token: None,
+    ///                         path: Path::from(content.call(Ident::parse_any)?),
+    ///                     }),
+    ///                 });
+    ///             } else if content.peek(Token![in]) {
+    ///                 return Ok(PubVisibility {
+    ///                     pub_token: pub_token,
+    ///                     restricted: Some(Restricted {
+    ///                         paren_token: parenthesized!(content in input),
+    ///                         in_token: Some(content.parse()?),
+    ///                         path: content.call(Path::parse_mod_style)?,
+    ///                     }),
+    ///                 });
+    ///             }
+    ///         }
+    ///
+    ///         Ok(PubVisibility {
+    ///             pub_token: pub_token,
+    ///             restricted: None,
+    ///         })
+    ///     }
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    pub fn fork(&self) -> Self {
+        ParseBuffer {
+            scope: self.scope,
+            cell: self.cell.clone(),
+            marker: PhantomData,
+            // Not the parent's unexpected. Nothing cares whether the clone
+            // parses all the way.
+            unexpected: Rc::new(Cell::new(None)),
+        }
+    }
+
+    /// Triggers an error at the current position of the parse stream.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate syn;
+    /// #
+    /// use syn::{Expr, Token};
+    /// use syn::parse::{Parse, ParseStream, Result};
+    ///
+    /// // Some kind of loop: `while` or `for` or `loop`.
+    /// struct Loop {
+    ///     expr: Expr,
+    /// }
+    ///
+    /// impl Parse for Loop {
+    ///     fn parse(input: ParseStream) -> Result<Self> {
+    ///         if input.peek(Token![while])
+    ///             || input.peek(Token![for])
+    ///             || input.peek(Token![loop])
+    ///         {
+    ///             Ok(Loop {
+    ///                 expr: input.parse()?,
+    ///             })
+    ///         } else {
+    ///             Err(input.error("expected some kind of loop"))
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    pub fn error<T: Display>(&self, message: T) -> Error {
+        error::new_at(self.scope, self.cursor(), message)
+    }
+
+    /// Speculatively parses tokens from this parse stream, advancing the
+    /// position of this stream only if parsing succeeds.
+    ///
+    /// This is a powerful low-level API used for defining the `Parse` impls of
+    /// the basic built-in token types. It is not something that will be used
+    /// widely outside of the Syn codebase.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # extern crate proc_macro2;
+    /// # extern crate syn;
+    /// #
+    /// use proc_macro2::TokenTree;
+    /// use syn::parse::{ParseStream, Result};
+    ///
+    /// // This function advances the stream past the next occurrence of `@`. If
+    /// // no `@` is present in the stream, the stream position is unchanged and
+    /// // an error is returned.
+    /// fn skip_past_next_at(input: ParseStream) -> Result<()> {
+    ///     input.step(|cursor| {
+    ///         let mut rest = *cursor;
+    ///         while let Some((tt, next)) = cursor.token_tree() {
+    ///             match tt {
+    ///                 TokenTree::Punct(ref punct) if punct.as_char() == '@' => {
+    ///                     return Ok(((), next));
+    ///                 }
+    ///                 _ => rest = next,
+    ///             }
+    ///         }
+    ///         Err(cursor.error("no `@` was found after this point"))
+    ///     })
+    /// }
+    /// #
+    /// # fn main() {}
+    /// ```
+    pub fn step<F, R>(&self, function: F) -> Result<R>
+    where
+        F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>,
+    {
+        let (node, rest) = function(StepCursor {
+            scope: self.scope,
+            cursor: self.cell.get(),
+            marker: PhantomData,
+        })?;
+        self.cell.set(rest);
+        Ok(node)
+    }
+
+    /// Provides low-level access to the token representation underlying this
+    /// parse stream.
+    ///
+    /// Cursors are immutable so no operations you perform against the cursor
+    /// will affect the state of this parse stream.
+    pub fn cursor(&self) -> Cursor<'a> {
+        self.cell.get()
+    }
+
+    fn check_unexpected(&self) -> Result<()> {
+        match self.unexpected.get() {
+            Some(span) => Err(Error::new(span, "unexpected token")),
+            None => Ok(()),
+        }
+    }
+}
+
+impl<T: Parse> Parse for Box<T> {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.parse().map(Box::new)
+    }
+}
+
+impl<T: Parse + Token> Parse for Option<T> {
+    fn parse(input: ParseStream) -> Result<Self> {
+        if T::peek(input.cursor()) {
+            Ok(Some(input.parse()?))
+        } else {
+            Ok(None)
+        }
+    }
+}
+
+impl Parse for TokenStream {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
+    }
+}
+
+impl Parse for TokenTree {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| match cursor.token_tree() {
+            Some((tt, rest)) => Ok((tt, rest)),
+            None => Err(cursor.error("expected token tree")),
+        })
+    }
+}
+
+impl Parse for Group {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| {
+            for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
+                if let Some((inside, span, rest)) = cursor.group(*delim) {
+                    let mut group = Group::new(*delim, inside.token_stream());
+                    group.set_span(span);
+                    return Ok((group, rest));
+                }
+            }
+            Err(cursor.error("expected group token"))
+        })
+    }
+}
+
+impl Parse for Punct {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| match cursor.punct() {
+            Some((punct, rest)) => Ok((punct, rest)),
+            None => Err(cursor.error("expected punctuation token")),
+        })
+    }
+}
+
+impl Parse for Literal {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| match cursor.literal() {
+            Some((literal, rest)) => Ok((literal, rest)),
+            None => Err(cursor.error("expected literal token")),
+        })
+    }
+}
+
+/// Parser that can parse Rust tokens into a particular syntax tree node.
+///
+/// Refer to the [module documentation] for details about parsing in Syn.
+///
+/// [module documentation]: index.html
+///
+/// *This trait is available if Syn is built with the `"parsing"` feature.*
+pub trait Parser: Sized {
+    type Output;
+
+    /// Parse a proc-macro2 token stream into the chosen syntax tree node.
+    fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;
+
+    /// Parse tokens of source code into the chosen syntax tree node.
+    ///
+    /// *This method is available if Syn is built with both the `"parsing"` and
+    /// `"proc-macro"` features.*
+    #[cfg(all(
+        not(all(target_arch = "wasm32", target_os = "unknown")),
+        feature = "proc-macro"
+    ))]
+    fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
+        self.parse2(proc_macro2::TokenStream::from(tokens))
+    }
+
+    /// Parse a string of Rust code into the chosen syntax tree node.
+    ///
+    /// # Hygiene
+    ///
+    /// Every span in the resulting syntax tree will be set to resolve at the
+    /// macro call site.
+    fn parse_str(self, s: &str) -> Result<Self::Output> {
+        self.parse2(proc_macro2::TokenStream::from_str(s)?)
+    }
+}
+
+fn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer {
+    let scope = Span::call_site();
+    let cursor = tokens.begin();
+    let unexpected = Rc::new(Cell::new(None));
+    private::new_parse_buffer(scope, cursor, unexpected)
+}
+
+impl<F, T> Parser for F
+where
+    F: FnOnce(ParseStream) -> Result<T>,
+{
+    type Output = T;
+
+    fn parse2(self, tokens: TokenStream) -> Result<T> {
+        let buf = TokenBuffer::new2(tokens);
+        let state = tokens_to_parse_buffer(&buf);
+        let node = self(&state)?;
+        state.check_unexpected()?;
+        if state.is_empty() {
+            Ok(node)
+        } else {
+            Err(state.error("unexpected token"))
+        }
+    }
+}
diff --git a/src/parse_quote.rs b/src/parse_quote.rs
index ec8ef5a..0cb4565 100644
--- a/src/parse_quote.rs
+++ b/src/parse_quote.rs
@@ -1,21 +1,19 @@
 /// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses
 /// type inference to figure out a return type for those tokens.
 ///
-/// [`quote!`]: https://docs.rs/quote/0.4/quote/index.html
+/// [`quote!`]: https://docs.rs/quote/0.6/quote/index.html
 ///
-/// The return type can be any syntax tree node that implements the [`Synom`]
+/// The return type can be any syntax tree node that implements the [`Parse`]
 /// trait.
 ///
-/// [`Synom`]: synom/trait.Synom.html
+/// [`Parse`]: parse/trait.Parse.html
 ///
 /// ```
-/// #[macro_use]
-/// extern crate syn;
-///
-/// #[macro_use]
-/// extern crate quote;
-///
-/// use syn::Stmt;
+/// # extern crate syn;
+/// # extern crate quote;
+/// #
+/// use quote::quote;
+/// use syn::{parse_quote, Stmt};
 ///
 /// fn main() {
 ///     let name = quote!(v);
@@ -39,14 +37,14 @@
 /// parameter `T` in the input generics.
 ///
 /// ```
-/// # #[macro_use]
+/// # extern crate quote;
 /// # extern crate syn;
 /// #
-/// # #[macro_use]
-/// # extern crate quote;
+/// # use quote::quote;
+/// # use syn::parse_quote;
 /// #
-/// # use syn::{Generics, GenericParam};
-/// #
+/// use syn::{Generics, GenericParam};
+///
 /// // Add a bound `T: HeapSize` to every type parameter T.
 /// fn add_trait_bounds(mut generics: Generics) -> Generics {
 ///     for param in &mut generics.params {
@@ -63,7 +61,7 @@
 /// # Special cases
 ///
 /// This macro can parse the following additional types as a special case even
-/// though they do not implement the `Synom` trait.
+/// though they do not implement the `Parse` trait.
 ///
 /// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
 ///   or inner like `#![...]`
@@ -81,20 +79,15 @@
 #[macro_export]
 macro_rules! parse_quote {
     ($($tt:tt)*) => {
-        $crate::parse_quote::parse($crate::parse_quote::From::from(quote!($($tt)*)))
+        $crate::parse_quote::parse($crate::export::From::from(quote!($($tt)*)))
     };
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Can parse any type that implements Synom.
 
-use buffer::Cursor;
+use parse::{Parse, ParseStream, Parser, Result};
 use proc_macro2::TokenStream;
-use synom::{PResult, Parser, Synom};
-
-// Not public API.
-#[doc(hidden)]
-pub use std::convert::From;
 
 // Not public API.
 #[doc(hidden)]
@@ -102,30 +95,19 @@
     let parser = T::parse;
     match parser.parse2(token_stream) {
         Ok(t) => t,
-        Err(err) => match T::description() {
-            Some(s) => panic!("failed to parse {}: {}", s, err),
-            None => panic!("{}", err),
-        },
+        Err(err) => panic!("{}", err),
     }
 }
 
 // Not public API.
 #[doc(hidden)]
 pub trait ParseQuote: Sized {
-    fn parse(input: Cursor) -> PResult<Self>;
-    fn description() -> Option<&'static str>;
+    fn parse(input: ParseStream) -> Result<Self>;
 }
 
-impl<T> ParseQuote for T
-where
-    T: Synom,
-{
-    fn parse(input: Cursor) -> PResult<Self> {
-        <T as Synom>::parse(input)
-    }
-
-    fn description() -> Option<&'static str> {
-        <T as Synom>::description()
+impl<T: Parse> ParseQuote for T {
+    fn parse(input: ParseStream) -> Result<Self> {
+        <T as Parse>::parse(input)
     }
 }
 
@@ -133,31 +115,22 @@
 // Any other types that we want `parse_quote!` to be able to parse.
 
 use punctuated::Punctuated;
-
 #[cfg(any(feature = "full", feature = "derive"))]
-use Attribute;
-
-impl<T, P> ParseQuote for Punctuated<T, P>
-where
-    T: Synom,
-    P: Synom,
-{
-    named!(parse -> Self, call!(Punctuated::parse_terminated));
-
-    fn description() -> Option<&'static str> {
-        Some("punctuated sequence")
-    }
-}
+use {attr, Attribute};
 
 #[cfg(any(feature = "full", feature = "derive"))]
 impl ParseQuote for Attribute {
-    named!(parse -> Self, alt!(
-        call!(Attribute::parse_outer)
-        |
-        call!(Attribute::parse_inner)
-    ));
+    fn parse(input: ParseStream) -> Result<Self> {
+        if input.peek(Token![#]) && input.peek2(Token![!]) {
+            attr::parsing::single_parse_inner(input)
+        } else {
+            attr::parsing::single_parse_outer(input)
+        }
+    }
+}
 
-    fn description() -> Option<&'static str> {
-        Some("attribute")
+impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> {
+    fn parse(input: ParseStream) -> Result<Self> {
+        Self::parse_terminated(input)
     }
 }
diff --git a/src/parsers.rs b/src/parsers.rs
deleted file mode 100644
index 400c0ca..0000000
--- a/src/parsers.rs
+++ /dev/null
@@ -1,1428 +0,0 @@
-// Copyright 2018 Syn Developers
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use buffer::Cursor;
-use parse_error;
-use synom::PResult;
-
-/// Define a parser function with the signature expected by syn parser
-/// combinators.
-///
-/// The function may be the `parse` function of the [`Synom`] trait, or it may
-/// be a free-standing function with an arbitrary name. When implementing the
-/// `Synom` trait, the function name is `parse` and the return type is `Self`.
-///
-/// [`Synom`]: synom/trait.Synom.html
-///
-/// - **Syntax:** `named!(NAME -> TYPE, PARSER)` or `named!(pub NAME -> TYPE, PARSER)`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Type;
-/// use syn::punctuated::Punctuated;
-/// use syn::synom::Synom;
-///
-/// /// Parses one or more Rust types separated by commas.
-/// ///
-/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
-/// named!(pub comma_separated_types -> Punctuated<Type, Token![,]>,
-///     call!(Punctuated::parse_separated_nonempty)
-/// );
-///
-/// /// The same function as a `Synom` implementation.
-/// struct CommaSeparatedTypes {
-///     types: Punctuated<Type, Token![,]>,
-/// }
-///
-/// impl Synom for CommaSeparatedTypes {
-///     /// As the default behavior, we want there to be at least 1 type.
-///     named!(parse -> Self, do_parse!(
-///         types: call!(Punctuated::parse_separated_nonempty) >>
-///         (CommaSeparatedTypes { types })
-///     ));
-/// }
-///
-/// impl CommaSeparatedTypes {
-///     /// A separate parser that the user can invoke explicitly which allows
-///     /// for parsing 0 or more types, rather than the default 1 or more.
-///     named!(pub parse0 -> Self, do_parse!(
-///         types: call!(Punctuated::parse_separated) >>
-///         (CommaSeparatedTypes { types })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! named {
-    ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
-        fn $name(i: $crate::buffer::Cursor) -> $crate::synom::PResult<$o> {
-            $submac!(i, $($args)*)
-        }
-    };
-
-    (pub $name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
-        pub fn $name(i: $crate::buffer::Cursor) -> $crate::synom::PResult<$o> {
-            $submac!(i, $($args)*)
-        }
-    };
-
-    // These two variants are for defining named parsers which have custom
-    // arguments, and are called with `call!()`
-    ($name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
-        fn $name(i: $crate::buffer::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
-            $submac!(i, $($args)*)
-        }
-    };
-
-    (pub $name:ident($($params:tt)*) -> $o:ty, $submac:ident!( $($args:tt)* )) => {
-        pub fn $name(i: $crate::buffer::Cursor, $($params)*) -> $crate::synom::PResult<$o> {
-            $submac!(i, $($args)*)
-        }
-    };
-}
-
-#[cfg(synom_verbose_trace)]
-#[macro_export]
-macro_rules! call {
-    ($i:expr, $fun:expr $(, $args:expr)*) => {{
-        #[allow(unused_imports)]
-        use $crate::synom::ext::*;
-        let i = $i;
-        eprintln!(concat!(" -> ", stringify!($fun), " @ {:?}"), i);
-        let r = $fun(i $(, $args)*);
-        match r {
-            Ok((_, i)) => eprintln!(concat!("OK  ", stringify!($fun), " @ {:?}"), i),
-            Err(_) => eprintln!(concat!("ERR ", stringify!($fun), " @ {:?}"), i),
-        }
-        r
-    }};
-}
-
-/// Invoke the given parser function with zero or more arguments.
-///
-/// - **Syntax:** `call!(FN, ARGS...)`
-///
-///   where the signature of the function is `fn(Cursor, ARGS...) -> PResult<T>`
-///
-/// - **Output:** `T`, the result of invoking the function `FN`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Type;
-/// use syn::punctuated::Punctuated;
-/// use syn::synom::Synom;
-///
-/// /// Parses one or more Rust types separated by commas.
-/// ///
-/// /// Example: `String, Vec<T>, [u8; LEN + 1]`
-/// struct CommaSeparatedTypes {
-///     types: Punctuated<Type, Token![,]>,
-/// }
-///
-/// impl Synom for CommaSeparatedTypes {
-///     named!(parse -> Self, do_parse!(
-///         types: call!(Punctuated::parse_separated_nonempty) >>
-///         (CommaSeparatedTypes { types })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[cfg(not(synom_verbose_trace))]
-#[macro_export]
-macro_rules! call {
-    ($i:expr, $fun:expr $(, $args:expr)*) => {{
-        #[allow(unused_imports)]
-        use $crate::synom::ext::*;
-        $fun($i $(, $args)*)
-    }};
-}
-
-/// Transform the result of a parser by applying a function or closure.
-///
-/// - **Syntax:** `map!(THING, FN)`
-/// - **Output:** the return type of function FN applied to THING
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::{Expr, ExprIf};
-///
-/// /// Extracts the branch condition of an `if`-expression.
-/// fn get_cond(if_: ExprIf) -> Expr {
-///     *if_.cond
-/// }
-///
-/// /// Parses a full `if`-expression but returns the condition part only.
-/// ///
-/// /// Example: `if x > 0xFF { "big" } else { "small" }`
-/// /// The return would be the expression `x > 0xFF`.
-/// named!(if_condition -> Expr,
-///     map!(syn!(ExprIf), get_cond)
-/// );
-///
-/// /// Equivalent using a closure.
-/// named!(if_condition2 -> Expr,
-///     map!(syn!(ExprIf), |if_| *if_.cond)
-/// );
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! map {
-    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((o, i)) =>
-                ::std::result::Result::Ok(($crate::parsers::invoke($g, o), i)),
-        }
-    };
-
-    ($i:expr, $f:expr, $g:expr) => {
-        map!($i, call!($f), $g)
-    };
-}
-
-// Somehow this helps with type inference in `map!` and `alt!`.
-//
-// Not public API.
-#[doc(hidden)]
-pub fn invoke<T, R, F: FnOnce(T) -> R>(f: F, t: T) -> R {
-    f(t)
-}
-
-/// Invert the result of a parser by parsing successfully if the given parser
-/// fails to parse and vice versa.
-///
-/// Does not consume any of the input.
-///
-/// - **Syntax:** `not!(THING)`
-/// - **Output:** `()`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Expr;
-///
-/// /// Parses any expression that does not begin with a `-` minus sign.
-/// named!(not_negative_expr -> Expr, do_parse!(
-///     not!(punct!(-)) >>
-///     e: syn!(Expr) >>
-///     (e)
-/// ));
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! not {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Ok(_) => $crate::parse_error(),
-            ::std::result::Result::Err(_) =>
-                ::std::result::Result::Ok(((), $i)),
-        }
-    };
-}
-
-/// Execute a parser only if a condition is met, otherwise return None.
-///
-/// If you are familiar with nom, this is nom's `cond_with_error` parser.
-///
-/// - **Syntax:** `cond!(CONDITION, THING)`
-/// - **Output:** `Some(THING)` if the condition is true, else `None`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::{Ident, MacroDelimiter};
-/// use syn::token::{Paren, Bracket, Brace};
-/// use syn::synom::Synom;
-///
-/// /// Parses a macro call with empty input. If the macro is written with
-/// /// parentheses or brackets, a trailing semicolon is required.
-/// ///
-/// /// Example: `my_macro!{}` or `my_macro!();` or `my_macro![];`
-/// struct EmptyMacroCall {
-///     name: Ident,
-///     bang_token: Token![!],
-///     empty_body: MacroDelimiter,
-///     semi_token: Option<Token![;]>,
-/// }
-///
-/// fn requires_semi(delimiter: &MacroDelimiter) -> bool {
-///     match *delimiter {
-///         MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => true,
-///         MacroDelimiter::Brace(_) => false,
-///     }
-/// }
-///
-/// impl Synom for EmptyMacroCall {
-///     named!(parse -> Self, do_parse!(
-///         name: syn!(Ident) >>
-///         bang_token: punct!(!) >>
-///         empty_body: alt!(
-///             parens!(epsilon!()) => { |d| MacroDelimiter::Paren(d.0) }
-///             |
-///             brackets!(epsilon!()) => { |d| MacroDelimiter::Bracket(d.0) }
-///             |
-///             braces!(epsilon!()) => { |d| MacroDelimiter::Brace(d.0) }
-///         ) >>
-///         semi_token: cond!(requires_semi(&empty_body), punct!(;)) >>
-///         (EmptyMacroCall {
-///             name,
-///             bang_token,
-///             empty_body,
-///             semi_token,
-///         })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! cond {
-    ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
-        if $cond {
-            match $submac!($i, $($args)*) {
-                ::std::result::Result::Ok((o, i)) =>
-                    ::std::result::Result::Ok((::std::option::Option::Some(o), i)),
-                ::std::result::Result::Err(x) => ::std::result::Result::Err(x),
-            }
-        } else {
-            ::std::result::Result::Ok((::std::option::Option::None, $i))
-        }
-    };
-
-    ($i:expr, $cond:expr, $f:expr) => {
-        cond!($i, $cond, call!($f))
-    };
-}
-
-/// Execute a parser only if a condition is met, otherwise fail to parse.
-///
-/// This is typically used inside of [`option!`] or [`alt!`].
-///
-/// [`option!`]: macro.option.html
-/// [`alt!`]: macro.alt.html
-///
-/// - **Syntax:** `cond_reduce!(CONDITION, THING)`
-/// - **Output:** `THING`
-///
-/// The subparser may be omitted in which case it defaults to [`epsilon!`].
-///
-/// [`epsilon!`]: macro.epsilon.html
-///
-/// - **Syntax:** `cond_reduce!(CONDITION)`
-/// - **Output:** `()`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Type;
-/// use syn::token::Paren;
-/// use syn::punctuated::Punctuated;
-/// use syn::synom::Synom;
-///
-/// /// Parses a possibly variadic function signature.
-/// ///
-/// /// Example: `fn(A) or `fn(A, B, C, ...)` or `fn(...)`
-/// /// Rejected: `fn(A, B...)`
-/// struct VariadicFn {
-///     fn_token: Token![fn],
-///     paren_token: Paren,
-///     types: Punctuated<Type, Token![,]>,
-///     variadic: Option<Token![...]>,
-/// }
-///
-/// // Example of using `cond_reduce!` inside of `option!`.
-/// impl Synom for VariadicFn {
-///     named!(parse -> Self, do_parse!(
-///         fn_token: keyword!(fn) >>
-///         params: parens!(do_parse!(
-///             types: call!(Punctuated::parse_terminated) >>
-///             // Allow, but do not require, an ending `...` but only if the
-///             // preceding list of types is empty or ends with a trailing comma.
-///             variadic: option!(cond_reduce!(types.empty_or_trailing(), punct!(...))) >>
-///             (types, variadic)
-///         )) >>
-///         ({
-///             let (paren_token, (types, variadic)) = params;
-///             VariadicFn {
-///                 fn_token,
-///                 paren_token,
-///                 types,
-///                 variadic,
-///             }
-///         })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! cond_reduce {
-    ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => {
-        if $cond {
-            $submac!($i, $($args)*)
-        } else {
-            $crate::parse_error()
-        }
-    };
-
-    ($i:expr, $cond:expr) => {
-        cond_reduce!($i, $cond, epsilon!())
-    };
-
-    ($i:expr, $cond:expr, $f:expr) => {
-        cond_reduce!($i, $cond, call!($f))
-    };
-}
-
-/// Parse zero or more values using the given parser.
-///
-/// - **Syntax:** `many0!(THING)`
-/// - **Output:** `Vec<THING>`
-///
-/// You may also be looking for:
-///
-/// - `call!(Punctuated::parse_separated)` - zero or more values with separator
-/// - `call!(Punctuated::parse_separated_nonempty)` - one or more values
-/// - `call!(Punctuated::parse_terminated)` - zero or more, allows trailing separator
-/// - `call!(Punctuated::parse_terminated_nonempty)` - one or more
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::{Ident, Item};
-/// use syn::token::Brace;
-/// use syn::synom::Synom;
-///
-/// /// Parses a module containing zero or more Rust items.
-/// ///
-/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
-/// struct SimpleMod {
-///     mod_token: Token![mod],
-///     name: Ident,
-///     brace_token: Brace,
-///     items: Vec<Item>,
-/// }
-///
-/// impl Synom for SimpleMod {
-///     named!(parse -> Self, do_parse!(
-///         mod_token: keyword!(mod) >>
-///         name: syn!(Ident) >>
-///         body: braces!(many0!(syn!(Item))) >>
-///         (SimpleMod {
-///             mod_token,
-///             name,
-///             brace_token: body.0,
-///             items: body.1,
-///         })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! many0 {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {{
-        let ret;
-        let mut res   = ::std::vec::Vec::new();
-        let mut input = $i;
-
-        loop {
-            if input.eof() {
-                ret = ::std::result::Result::Ok((res, input));
-                break;
-            }
-
-            match $submac!(input, $($args)*) {
-                ::std::result::Result::Err(_) => {
-                    ret = ::std::result::Result::Ok((res, input));
-                    break;
-                }
-                ::std::result::Result::Ok((o, i)) => {
-                    // loop trip must always consume (otherwise infinite loops)
-                    if i == input {
-                        ret = $crate::parse_error();
-                        break;
-                    }
-
-                    res.push(o);
-                    input = i;
-                }
-            }
-        }
-
-        ret
-    }};
-
-    ($i:expr, $f:expr) => {
-        $crate::parsers::many0($i, $f)
-    };
-}
-
-// Improve compile time by compiling this loop only once per type it is used
-// with.
-//
-// Not public API.
-#[doc(hidden)]
-pub fn many0<T>(mut input: Cursor, f: fn(Cursor) -> PResult<T>) -> PResult<Vec<T>> {
-    let mut res = Vec::new();
-
-    loop {
-        if input.eof() {
-            return Ok((res, input));
-        }
-
-        match f(input) {
-            Err(_) => {
-                return Ok((res, input));
-            }
-            Ok((o, i)) => {
-                // loop trip must always consume (otherwise infinite loops)
-                if i == input {
-                    return parse_error();
-                }
-
-                res.push(o);
-                input = i;
-            }
-        }
-    }
-}
-
-/// Pattern-match the result of a parser to select which other parser to run.
-///
-/// - **Syntax:** `switch!(TARGET, PAT1 => THEN1 | PAT2 => THEN2 | ...)`
-/// - **Output:** `T`, the return type of `THEN1` and `THEN2` and ...
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Ident;
-/// use syn::token::Brace;
-/// use syn::synom::Synom;
-///
-/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
-/// enum UnitType {
-///     Struct {
-///         struct_token: Token![struct],
-///         name: Ident,
-///         semi_token: Token![;],
-///     },
-///     Enum {
-///         enum_token: Token![enum],
-///         name: Ident,
-///         brace_token: Brace,
-///         variant: Ident,
-///     },
-/// }
-///
-/// enum StructOrEnum {
-///     Struct(Token![struct]),
-///     Enum(Token![enum]),
-/// }
-///
-/// impl Synom for StructOrEnum {
-///     named!(parse -> Self, alt!(
-///         keyword!(struct) => { StructOrEnum::Struct }
-///         |
-///         keyword!(enum) => { StructOrEnum::Enum }
-///     ));
-/// }
-///
-/// impl Synom for UnitType {
-///     named!(parse -> Self, do_parse!(
-///         which: syn!(StructOrEnum) >>
-///         name: syn!(Ident) >>
-///         item: switch!(value!(which),
-///             StructOrEnum::Struct(struct_token) => map!(
-///                 punct!(;),
-///                 |semi_token| UnitType::Struct {
-///                     struct_token,
-///                     name,
-///                     semi_token,
-///                 }
-///             )
-///             |
-///             StructOrEnum::Enum(enum_token) => map!(
-///                 braces!(syn!(Ident)),
-///                 |(brace_token, variant)| UnitType::Enum {
-///                     enum_token,
-///                     name,
-///                     brace_token,
-///                     variant,
-///                 }
-///             )
-///         ) >>
-///         (item)
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! switch {
-    ($i:expr, $submac:ident!( $($args:tt)* ), $($p:pat => $subrule:ident!( $($args2:tt)* ))|* ) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((o, i)) => match o {
-                $(
-                    $p => $subrule!(i, $($args2)*),
-                )*
-            }
-        }
-    };
-}
-
-/// Produce the given value without parsing anything.
-///
-/// This can be needed where you have an existing parsed value but a parser
-/// macro's syntax expects you to provide a submacro, such as in the first
-/// argument of [`switch!`] or one of the branches of [`alt!`].
-///
-/// [`switch!`]: macro.switch.html
-/// [`alt!`]: macro.alt.html
-///
-/// - **Syntax:** `value!(VALUE)`
-/// - **Output:** `VALUE`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Ident;
-/// use syn::token::Brace;
-/// use syn::synom::Synom;
-///
-/// /// Parse a unit struct or enum: either `struct S;` or `enum E { V }`.
-/// enum UnitType {
-///     Struct {
-///         struct_token: Token![struct],
-///         name: Ident,
-///         semi_token: Token![;],
-///     },
-///     Enum {
-///         enum_token: Token![enum],
-///         name: Ident,
-///         brace_token: Brace,
-///         variant: Ident,
-///     },
-/// }
-///
-/// enum StructOrEnum {
-///     Struct(Token![struct]),
-///     Enum(Token![enum]),
-/// }
-///
-/// impl Synom for StructOrEnum {
-///     named!(parse -> Self, alt!(
-///         keyword!(struct) => { StructOrEnum::Struct }
-///         |
-///         keyword!(enum) => { StructOrEnum::Enum }
-///     ));
-/// }
-///
-/// impl Synom for UnitType {
-///     named!(parse -> Self, do_parse!(
-///         which: syn!(StructOrEnum) >>
-///         name: syn!(Ident) >>
-///         item: switch!(value!(which),
-///             StructOrEnum::Struct(struct_token) => map!(
-///                 punct!(;),
-///                 |semi_token| UnitType::Struct {
-///                     struct_token,
-///                     name,
-///                     semi_token,
-///                 }
-///             )
-///             |
-///             StructOrEnum::Enum(enum_token) => map!(
-///                 braces!(syn!(Ident)),
-///                 |(brace_token, variant)| UnitType::Enum {
-///                     enum_token,
-///                     name,
-///                     brace_token,
-///                     variant,
-///                 }
-///             )
-///         ) >>
-///         (item)
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! value {
-    ($i:expr, $res:expr) => {
-        ::std::result::Result::Ok(($res, $i))
-    };
-}
-
-/// Unconditionally fail to parse anything.
-///
-/// This may be useful in rejecting some arms of a `switch!` parser.
-///
-/// - **Syntax:** `reject!()`
-/// - **Output:** never succeeds
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Item;
-///
-/// // Parse any item, except for a module.
-/// named!(almost_any_item -> Item,
-///     switch!(syn!(Item),
-///         Item::Mod(_) => reject!()
-///         |
-///         ok => value!(ok)
-///     )
-/// );
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! reject {
-    ($i:expr,) => {{
-        let _ = $i;
-        $crate::parse_error()
-    }};
-}
-
-/// Run a series of parsers and produce all of the results in a tuple.
-///
-/// - **Syntax:** `tuple!(A, B, C, ...)`
-/// - **Output:** `(A, B, C, ...)`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Type;
-///
-/// named!(two_types -> (Type, Type), tuple!(syn!(Type), syn!(Type)));
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! tuple {
-    ($i:expr, $($rest:tt)+) => {
-        tuple_parser!($i, (), $($rest)+)
-    };
-}
-
-// Internal parser, do not use directly.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! tuple_parser {
-    ($i:expr, ($($parsed:ident,)*), $e:ident) => {
-        tuple_parser!($i, ($($parsed,)*), call!($e))
-    };
-
-    ($i:expr, ($($parsed:ident,)*), $e:ident, $($rest:tt)*) => {
-        tuple_parser!($i, ($($parsed,)*), call!($e), $($rest)*)
-    };
-
-    ($i:expr, ($($parsed:ident,)*), $submac:ident!( $($args:tt)* )) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((o, i)) =>
-                ::std::result::Result::Ok((($($parsed,)* o,), i)),
-        }
-    };
-
-    ($i:expr, ($($parsed:ident,)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((o, i)) =>
-                tuple_parser!(i, ($($parsed,)* o,), $($rest)*),
-        }
-    };
-
-    ($i:expr, ($($parsed:ident,)*),) => {
-        ::std::result::Result::Ok((($($parsed,)*), $i))
-    };
-}
-
-/// Run a series of parsers, returning the result of the first one which
-/// succeeds.
-///
-/// Optionally allows for the result to be transformed.
-///
-/// - **Syntax:** `alt!(THING1 | THING2 => { FUNC } | ...)`
-/// - **Output:** `T`, the return type of `THING1` and `FUNC(THING2)` and ...
-///
-/// # Example
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-/// extern crate proc_macro2;
-///
-/// use proc_macro2::{Ident, Span};
-///
-/// // Parse any identifier token, or the `!` token in which case the
-/// // identifier is treated as `"BANG"`.
-/// named!(ident_or_bang -> Ident, alt!(
-///     syn!(Ident)
-///     |
-///     punct!(!) => { |_| Ident::new("BANG", Span::call_site()) }
-/// ));
-/// #
-/// # fn main() {}
-/// ```
-///
-/// The `alt!` macro is most commonly seen when parsing a syntax tree enum such
-/// as the [`Item`] enum.
-///
-/// [`Item`]: enum.Item.html
-///
-/// ```
-/// # #[macro_use]
-/// # extern crate syn;
-/// #
-/// # use syn::synom::Synom;
-/// #
-/// # struct Item;
-/// #
-/// impl Synom for Item {
-///     named!(parse -> Self, alt!(
-/// #       epsilon!() => { |_| unimplemented!() }
-/// #   ));
-/// # }
-/// #
-/// # mod example {
-/// #   use syn::*;
-/// #
-/// #   named!(parse -> Item, alt!(
-///         syn!(ItemExternCrate) => { Item::ExternCrate }
-///         |
-///         syn!(ItemUse) => { Item::Use }
-///         |
-///         syn!(ItemStatic) => { Item::Static }
-///         |
-///         syn!(ItemConst) => { Item::Const }
-///         |
-///         /* ... */
-/// #       syn!(ItemFn) => { Item::Fn }
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! alt {
-    ($i:expr, $e:ident | $($rest:tt)*) => {
-        alt!($i, call!($e) | $($rest)*)
-    };
-
-    ($i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => {
-        match $subrule!($i, $($args)*) {
-            res @ ::std::result::Result::Ok(_) => res,
-            _ => alt!($i, $($rest)*)
-        }
-    };
-
-    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
-        match $subrule!($i, $($args)*) {
-            ::std::result::Result::Ok((o, i)) =>
-                ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
-            ::std::result::Result::Err(_) => alt!($i, $($rest)*),
-        }
-    };
-
-    ($i:expr, $e:ident => { $gen:expr } | $($rest:tt)*) => {
-        alt!($i, call!($e) => { $gen } | $($rest)*)
-    };
-
-    ($i:expr, $e:ident => { $gen:expr }) => {
-        alt!($i, call!($e) => { $gen })
-    };
-
-    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr }) => {
-        match $subrule!($i, $($args)*) {
-            ::std::result::Result::Ok((o, i)) =>
-                ::std::result::Result::Ok(($crate::parsers::invoke($gen, o), i)),
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-        }
-    };
-
-    ($i:expr, $e:ident) => {
-        alt!($i, call!($e))
-    };
-
-    ($i:expr, $subrule:ident!( $($args:tt)*)) => {
-        $subrule!($i, $($args)*)
-    };
-}
-
-/// Run a series of parsers, optionally naming each intermediate result,
-/// followed by a step to combine the intermediate results.
-///
-/// Produces the result of evaluating the final expression in parentheses with
-/// all of the previously named results bound.
-///
-/// - **Syntax:** `do_parse!(name: THING1 >> THING2 >> (RESULT))`
-/// - **Output:** `RESULT`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-/// extern crate proc_macro2;
-///
-/// use proc_macro2::Ident;
-/// use proc_macro2::TokenStream;
-/// use syn::token::Paren;
-/// use syn::synom::Synom;
-///
-/// /// Parse a macro invocation that uses `(` `)` parentheses.
-/// ///
-/// /// Example: `stringify!($args)`.
-/// struct Macro {
-///     name: Ident,
-///     bang_token: Token![!],
-///     paren_token: Paren,
-///     tts: TokenStream,
-/// }
-///
-/// impl Synom for Macro {
-///     named!(parse -> Self, do_parse!(
-///         name: syn!(Ident) >>
-///         bang_token: punct!(!) >>
-///         body: parens!(syn!(TokenStream)) >>
-///         (Macro {
-///             name,
-///             bang_token,
-///             paren_token: body.0,
-///             tts: body.1,
-///         })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! do_parse {
-    ($i:expr, ( $($rest:expr),* )) => {
-        ::std::result::Result::Ok((( $($rest),* ), $i))
-    };
-
-    ($i:expr, $e:ident >> $($rest:tt)*) => {
-        do_parse!($i, call!($e) >> $($rest)*)
-    };
-
-    ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((_, i)) =>
-                do_parse!(i, $($rest)*),
-        }
-    };
-
-    ($i:expr, $field:ident : $e:ident >> $($rest:tt)*) => {
-        do_parse!($i, $field: call!($e) >> $($rest)*)
-    };
-
-    ($i:expr, $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((o, i)) => {
-                let $field = o;
-                do_parse!(i, $($rest)*)
-            },
-        }
-    };
-
-    ($i:expr, mut $field:ident : $e:ident >> $($rest:tt)*) => {
-        do_parse!($i, mut $field: call!($e) >> $($rest)*)
-    };
-
-    ($i:expr, mut $field:ident : $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((o, i)) => {
-                let mut $field = o;
-                do_parse!(i, $($rest)*)
-            },
-        }
-    };
-}
-
-/// Parse nothing and succeed only if the end of the enclosing block has been
-/// reached.
-///
-/// The enclosing block may be the full input if we are parsing at the top
-/// level, or the surrounding parenthesis/bracket/brace if we are parsing within
-/// those.
-///
-/// - **Syntax:** `input_end!()`
-/// - **Output:** `()`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Expr;
-/// use syn::synom::Synom;
-///
-/// /// Parses any Rust expression followed either by a semicolon or by the end
-/// /// of the input.
-/// ///
-/// /// For example `many0!(syn!(TerminatedExpr))` would successfully parse the
-/// /// following input into three expressions.
-/// ///
-/// ///     1 + 1; second.two(); third!()
-/// ///
-/// /// Similarly within a block, `braced!(many0!(syn!(TerminatedExpr)))` would
-/// /// successfully parse three expressions.
-/// ///
-/// ///     { 1 + 1; second.two(); third!() }
-/// struct TerminatedExpr {
-///     expr: Expr,
-///     semi_token: Option<Token![;]>,
-/// }
-///
-/// impl Synom for TerminatedExpr {
-///     named!(parse -> Self, do_parse!(
-///         expr: syn!(Expr) >>
-///         semi_token: alt!(
-///             input_end!() => { |_| None }
-///             |
-///             punct!(;) => { Some }
-///         ) >>
-///         (TerminatedExpr {
-///             expr,
-///             semi_token,
-///         })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! input_end {
-    ($i:expr,) => {
-        $crate::parsers::input_end($i)
-    };
-}
-
-// Not a public API
-#[doc(hidden)]
-pub fn input_end(input: Cursor) -> PResult<'static, ()> {
-    if input.eof() {
-        Ok(((), Cursor::empty()))
-    } else {
-        parse_error()
-    }
-}
-
-/// Turn a failed parse into `None` and a successful parse into `Some`.
-///
-/// A failed parse consumes none of the input.
-///
-/// - **Syntax:** `option!(THING)`
-/// - **Output:** `Option<THING>`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::{Label, Block};
-/// use syn::synom::Synom;
-///
-/// /// Parses a Rust loop. Equivalent to syn::ExprLoop.
-/// ///
-/// /// Examples:
-/// ///     loop { println!("y"); }
-/// ///     'x: loop { break 'x; }
-/// struct ExprLoop {
-///     label: Option<Label>,
-///     loop_token: Token![loop],
-///     body: Block,
-/// }
-///
-/// impl Synom for ExprLoop {
-///     named!(parse -> Self, do_parse!(
-///         // Loop may or may not have a label.
-///         label: option!(syn!(Label)) >>
-///         loop_token: keyword!(loop) >>
-///         body: syn!(Block) >>
-///         (ExprLoop {
-///             label,
-///             loop_token,
-///             body,
-///         })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! option {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Ok((o, i)) =>
-                ::std::result::Result::Ok((Some(o), i)),
-            ::std::result::Result::Err(_) =>
-                ::std::result::Result::Ok((None, $i)),
-        }
-    };
-
-    ($i:expr, $f:expr) => {
-        option!($i, call!($f));
-    };
-}
-
-/// Parses nothing and always succeeds.
-///
-/// This can be useful as a fallthrough case in [`alt!`], as shown below. Also
-/// useful for parsing empty delimiters using [`parens!`] or [`brackets!`] or
-/// [`braces!`] by parsing for example `braces!(epsilon!())` for an empty `{}`.
-///
-/// [`alt!`]: macro.alt.html
-/// [`parens!`]: macro.parens.html
-/// [`brackets!`]: macro.brackets.html
-/// [`braces!`]: macro.braces.html
-///
-/// - **Syntax:** `epsilon!()`
-/// - **Output:** `()`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::synom::Synom;
-///
-/// enum Mutability {
-///     Mutable(Token![mut]),
-///     Immutable,
-/// }
-///
-/// impl Synom for Mutability {
-///     named!(parse -> Self, alt!(
-///         keyword!(mut) => { Mutability::Mutable }
-///         |
-///         epsilon!() => { |_| Mutability::Immutable }
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! epsilon {
-    ($i:expr,) => {
-        ::std::result::Result::Ok(((), $i))
-    };
-}
-
-/// Run a parser, binding the result to a name, and then evaluating an
-/// expression.
-///
-/// Discards the result of the expression and parser.
-///
-/// - **Syntax:** `tap!(NAME : THING => EXPR)`
-/// - **Output:** `()`
-#[doc(hidden)]
-#[macro_export]
-macro_rules! tap {
-    ($i:expr, $name:ident : $submac:ident!( $($args:tt)* ) => $e:expr) => {
-        match $submac!($i, $($args)*) {
-            ::std::result::Result::Ok((o, i)) => {
-                let $name = o;
-                $e;
-                ::std::result::Result::Ok(((), i))
-            }
-            ::std::result::Result::Err(err) =>
-                ::std::result::Result::Err(err),
-        }
-    };
-
-    ($i:expr, $name:ident : $f:expr => $e:expr) => {
-        tap!($i, $name: call!($f) => $e);
-    };
-}
-
-/// Parse any type that implements the `Synom` trait.
-///
-/// Any type implementing [`Synom`] can be used with this parser, whether the
-/// implementation is provided by Syn or is one that you write.
-///
-/// [`Synom`]: synom/trait.Synom.html
-///
-/// - **Syntax:** `syn!(TYPE)`
-/// - **Output:** `TYPE`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::{Ident, Item};
-/// use syn::token::Brace;
-/// use syn::synom::Synom;
-///
-/// /// Parses a module containing zero or more Rust items.
-/// ///
-/// /// Example: `mod m { type Result<T> = ::std::result::Result<T, MyError>; }`
-/// struct SimpleMod {
-///     mod_token: Token![mod],
-///     name: Ident,
-///     brace_token: Brace,
-///     items: Vec<Item>,
-/// }
-///
-/// impl Synom for SimpleMod {
-///     named!(parse -> Self, do_parse!(
-///         mod_token: keyword!(mod) >>
-///         name: syn!(Ident) >>
-///         body: braces!(many0!(syn!(Item))) >>
-///         (SimpleMod {
-///             mod_token,
-///             name,
-///             brace_token: body.0,
-///             items: body.1,
-///         })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! syn {
-    ($i:expr, $t:ty) => {
-        <$t as $crate::synom::Synom>::parse($i)
-    };
-}
-
-/// Parse the given word as a keyword.
-///
-/// For words that are keywords in the Rust language, it is better to use the
-/// [`keyword!`] parser which returns a unique type for each keyword.
-///
-/// [`keyword!`]: macro.keyword.html
-///
-/// - **Syntax:** `custom_keyword!(KEYWORD)`
-/// - **Output:** `Ident`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Ident;
-/// use syn::synom::Synom;
-///
-/// struct Flag {
-///     name: Ident,
-/// }
-///
-/// // Parses the custom keyword `flag` followed by any name for a flag.
-/// //
-/// // Example: `flag Verbose`
-/// impl Synom for Flag {
-///     named!(parse -> Flag, do_parse!(
-///         custom_keyword!(flag) >>
-///         name: syn!(Ident) >>
-///         (Flag { name })
-///     ));
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! custom_keyword {
-    ($i:expr, $keyword:ident) => {
-        match <$crate::Ident as $crate::synom::Synom>::parse($i) {
-            ::std::result::Result::Err(err) => ::std::result::Result::Err(err),
-            ::std::result::Result::Ok((token, i)) => {
-                if token == stringify!($keyword) {
-                    ::std::result::Result::Ok((token, i))
-                } else {
-                    $crate::parse_error()
-                }
-            }
-        }
-    };
-}
-
-/// Parse inside of `(` `)` parentheses.
-///
-/// This macro parses a set of balanced parentheses and invokes a sub-parser on
-/// the content inside. The sub-parser is required to consume all tokens within
-/// the parentheses in order for this parser to return successfully.
-///
-/// - **Syntax:** `parens!(CONTENT)`
-/// - **Output:** `(token::Paren, CONTENT)`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Expr;
-/// use syn::token::Paren;
-///
-/// /// Parses an expression inside of parentheses.
-/// ///
-/// /// Example: `(1 + 1)`
-/// named!(expr_paren -> (Paren, Expr), parens!(syn!(Expr)));
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! parens {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        $crate::token::Paren::parse($i, |i| $submac!(i, $($args)*))
-    };
-
-    ($i:expr, $f:expr) => {
-        parens!($i, call!($f));
-    };
-}
-
-/// Parse inside of `[` `]` square brackets.
-///
-/// This macro parses a set of balanced brackets and invokes a sub-parser on the
-/// content inside. The sub-parser is required to consume all tokens within the
-/// brackets in order for this parser to return successfully.
-///
-/// - **Syntax:** `brackets!(CONTENT)`
-/// - **Output:** `(token::Bracket, CONTENT)`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Expr;
-/// use syn::token::Bracket;
-///
-/// /// Parses an expression inside of brackets.
-/// ///
-/// /// Example: `[1 + 1]`
-/// named!(expr_paren -> (Bracket, Expr), brackets!(syn!(Expr)));
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! brackets {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        $crate::token::Bracket::parse($i, |i| $submac!(i, $($args)*))
-    };
-
-    ($i:expr, $f:expr) => {
-        brackets!($i, call!($f));
-    };
-}
-
-/// Parse inside of `{` `}` curly braces.
-///
-/// This macro parses a set of balanced braces and invokes a sub-parser on the
-/// content inside. The sub-parser is required to consume all tokens within the
-/// braces in order for this parser to return successfully.
-///
-/// - **Syntax:** `braces!(CONTENT)`
-/// - **Output:** `(token::Brace, CONTENT)`
-///
-/// ```rust
-/// #[macro_use]
-/// extern crate syn;
-///
-/// use syn::Expr;
-/// use syn::token::Brace;
-///
-/// /// Parses an expression inside of braces.
-/// ///
-/// /// Example: `{1 + 1}`
-/// named!(expr_paren -> (Brace, Expr), braces!(syn!(Expr)));
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[macro_export]
-macro_rules! braces {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        $crate::token::Brace::parse($i, |i| $submac!(i, $($args)*))
-    };
-
-    ($i:expr, $f:expr) => {
-        braces!($i, call!($f));
-    };
-}
-
-// Not public API.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! grouped {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        $crate::token::Group::parse($i, |i| $submac!(i, $($args)*))
-    };
-
-    ($i:expr, $f:expr) => {
-        grouped!($i, call!($f));
-    };
-}
diff --git a/src/path.rs b/src/path.rs
index a848944..443bac6 100644
--- a/src/path.rs
+++ b/src/path.rs
@@ -20,44 +20,6 @@
     }
 }
 
-impl Path {
-    pub fn global(&self) -> bool {
-        self.leading_colon.is_some()
-    }
-}
-
-/// A helper for printing a self-type qualified path as tokens.
-///
-/// ```rust
-/// extern crate syn;
-/// extern crate quote;
-/// extern crate proc_macro2;
-///
-/// use syn::{QSelf, Path, PathTokens};
-/// use proc_macro2::TokenStream;
-/// use quote::ToTokens;
-///
-/// struct MyNode {
-///     qself: Option<QSelf>,
-///     path: Path,
-/// }
-///
-/// impl ToTokens for MyNode {
-///     fn to_tokens(&self, tokens: &mut TokenStream) {
-///         PathTokens(&self.qself, &self.path).to_tokens(tokens);
-///     }
-/// }
-/// #
-/// # fn main() {}
-/// ```
-///
-/// *This type is available if Syn is built with the `"derive"` or `"full"`
-/// feature and the `"printing"` feature.*
-#[cfg(feature = "printing")]
-#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
-#[cfg_attr(feature = "clone-impls", derive(Clone))]
-pub struct PathTokens<'a>(pub &'a Option<QSelf>, pub &'a Path);
-
 impl<T> From<T> for Path
 where
     T: Into<PathSegment>,
@@ -227,202 +189,280 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use synom::Synom;
-
-    impl Synom for Path {
-        named!(parse -> Self, do_parse!(
-            colon: option!(punct!(::)) >>
-            segments: call!(Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty) >>
-            cond_reduce!(segments.first().map_or(true, |seg| seg.value().ident != "dyn")) >>
-            (Path {
-                leading_colon: colon,
-                segments: segments,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("path")
-        }
-    }
-
-    #[cfg(not(feature = "full"))]
-    impl Synom for GenericArgument {
-        named!(parse -> Self, alt!(
-            call!(ty_no_eq_after) => { GenericArgument::Type }
-            |
-            syn!(Lifetime) => { GenericArgument::Lifetime }
-            |
-            syn!(Binding) => { GenericArgument::Binding }
-        ));
-    }
 
     #[cfg(feature = "full")]
-    impl Synom for GenericArgument {
-        named!(parse -> Self, alt!(
-            call!(ty_no_eq_after) => { GenericArgument::Type }
-            |
-            syn!(Lifetime) => { GenericArgument::Lifetime }
-            |
-            syn!(Binding) => { GenericArgument::Binding }
-            |
-            syn!(ExprLit) => { |l| GenericArgument::Const(Expr::Lit(l)) }
-            |
-            syn!(ExprBlock) => { |b| GenericArgument::Const(Expr::Block(b)) }
-        ));
+    use expr;
+    use ext::IdentExt;
+    use parse::{Parse, ParseStream, Result};
 
-        fn description() -> Option<&'static str> {
-            Some("generic argument")
+    impl Parse for Path {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse_helper(input, false)
         }
     }
 
-    impl Synom for AngleBracketedGenericArguments {
-        named!(parse -> Self, do_parse!(
-            colon2: option!(punct!(::)) >>
-            lt: punct!(<) >>
-            args: call!(Punctuated::parse_terminated) >>
-            gt: punct!(>) >>
-            (AngleBracketedGenericArguments {
-                colon2_token: colon2,
-                lt_token: lt,
-                args: args,
-                gt_token: gt,
+    impl Parse for GenericArgument {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Lifetime) && !input.peek2(Token![+]) {
+                return Ok(GenericArgument::Lifetime(input.parse()?));
+            }
+
+            if input.peek(Ident) && input.peek2(Token![=]) {
+                return Ok(GenericArgument::Binding(input.parse()?));
+            }
+
+            #[cfg(feature = "full")]
+            {
+                if input.peek(Lit) {
+                    let lit = input.call(expr::parsing::expr_lit)?;
+                    return Ok(GenericArgument::Const(Expr::Lit(lit)));
+                }
+
+                if input.peek(token::Brace) {
+                    let block = input.call(expr::parsing::expr_block)?;
+                    return Ok(GenericArgument::Const(Expr::Block(block)));
+                }
+            }
+
+            input.parse().map(GenericArgument::Type)
+        }
+    }
+
+    impl Parse for AngleBracketedGenericArguments {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(AngleBracketedGenericArguments {
+                colon2_token: input.parse()?,
+                lt_token: input.parse()?,
+                args: {
+                    let mut args = Punctuated::new();
+                    loop {
+                        if input.peek(Token![>]) {
+                            break;
+                        }
+                        let value = input.parse()?;
+                        args.push_value(value);
+                        if input.peek(Token![>]) {
+                            break;
+                        }
+                        let punct = input.parse()?;
+                        args.push_punct(punct);
+                    }
+                    args
+                },
+                gt_token: input.parse()?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("angle bracketed generic arguments")
         }
     }
 
-    impl Synom for ParenthesizedGenericArguments {
-        named!(parse -> Self, do_parse!(
-            data: parens!(Punctuated::parse_terminated) >>
-            output: call!(ReturnType::without_plus) >>
-            (ParenthesizedGenericArguments {
-                paren_token: data.0,
-                inputs: data.1,
-                output: output,
+    impl Parse for ParenthesizedGenericArguments {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(ParenthesizedGenericArguments {
+                paren_token: parenthesized!(content in input),
+                inputs: content.parse_terminated(Type::parse)?,
+                output: input.call(ReturnType::without_plus)?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("parenthesized generic arguments: `Foo(A, B, ..) -> T`")
         }
     }
 
-    impl Synom for PathSegment {
-        named!(parse -> Self, alt!(
-            do_parse!(
-                ident: syn!(Ident) >>
-                arguments: syn!(AngleBracketedGenericArguments) >>
-                (PathSegment {
+    impl Parse for PathSegment {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse_helper(input, false)
+        }
+    }
+
+    impl PathSegment {
+        fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
+            if input.peek(Token![super])
+                || input.peek(Token![self])
+                || input.peek(Token![Self])
+                || input.peek(Token![crate])
+                || input.peek(Token![extern])
+            {
+                let ident = input.call(Ident::parse_any)?;
+                return Ok(PathSegment::from(ident));
+            }
+
+            let ident = input.parse()?;
+            if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=])
+                || input.peek(Token![::]) && input.peek3(Token![<])
+            {
+                Ok(PathSegment {
                     ident: ident,
-                    arguments: PathArguments::AngleBracketed(arguments),
+                    arguments: PathArguments::AngleBracketed(input.parse()?),
                 })
-            )
-            |
-            mod_style_path_segment
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("path segment")
+            } else {
+                Ok(PathSegment::from(ident))
+            }
         }
     }
 
-    impl Synom for Binding {
-        named!(parse -> Self, do_parse!(
-            id: syn!(Ident) >>
-            eq: punct!(=) >>
-            ty: syn!(Type) >>
-            (Binding {
-                ident: id,
-                eq_token: eq,
-                ty: ty,
+    impl Parse for Binding {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(Binding {
+                ident: input.parse()?,
+                eq_token: input.parse()?,
+                ty: input.parse()?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("associated type binding")
         }
     }
 
     impl Path {
-        named!(pub parse_mod_style -> Self, do_parse!(
-            colon: option!(punct!(::)) >>
-            segments: call!(Punctuated::parse_separated_nonempty_with,
-                            mod_style_path_segment) >>
-            (Path {
-                leading_colon: colon,
-                segments: segments,
+        /// Parse a `Path` containing no path arguments on any of its segments.
+        ///
+        /// *This function is available if Syn is built with the `"parsing"`
+        /// feature.*
+        ///
+        /// # Example
+        ///
+        /// ```
+        /// # extern crate syn;
+        /// #
+        /// use syn::{Path, Token};
+        /// use syn::parse::{Parse, ParseStream, Result};
+        ///
+        /// // A simplified single `use` statement like:
+        /// //
+        /// //     use std::collections::HashMap;
+        /// //
+        /// // Note that generic parameters are not allowed in a `use` statement
+        /// // so the following must not be accepted.
+        /// //
+        /// //     use a::<b>::c;
+        /// struct SingleUse {
+        ///     use_token: Token![use],
+        ///     path: Path,
+        /// }
+        ///
+        /// impl Parse for SingleUse {
+        ///     fn parse(input: ParseStream) -> Result<Self> {
+        ///         Ok(SingleUse {
+        ///             use_token: input.parse()?,
+        ///             path: input.call(Path::parse_mod_style)?,
+        ///         })
+        ///     }
+        /// }
+        /// #
+        /// # fn main() {}
+        /// ```
+        pub fn parse_mod_style(input: ParseStream) -> Result<Self> {
+            Ok(Path {
+                leading_colon: input.parse()?,
+                segments: {
+                    let mut segments = Punctuated::new();
+                    loop {
+                        if !input.peek(Ident)
+                            && !input.peek(Token![super])
+                            && !input.peek(Token![self])
+                            && !input.peek(Token![Self])
+                            && !input.peek(Token![crate])
+                            && !input.peek(Token![extern])
+                        {
+                            break;
+                        }
+                        let ident = Ident::parse_any(input)?;
+                        segments.push_value(PathSegment::from(ident));
+                        if !input.peek(Token![::]) {
+                            break;
+                        }
+                        let punct = input.parse()?;
+                        segments.push_punct(punct);
+                    }
+                    if segments.is_empty() {
+                        return Err(input.error("expected path"));
+                    } else if segments.trailing_punct() {
+                        return Err(input.error("expected path segment"));
+                    }
+                    segments
+                },
             })
-        ));
+        }
+
+        fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
+            if input.peek(Token![dyn]) {
+                return Err(input.error("expected path"));
+            }
+
+            Ok(Path {
+                leading_colon: input.parse()?,
+                segments: {
+                    let mut segments = Punctuated::new();
+                    let value = PathSegment::parse_helper(input, expr_style)?;
+                    segments.push_value(value);
+                    while input.peek(Token![::]) {
+                        let punct: Token![::] = input.parse()?;
+                        segments.push_punct(punct);
+                        let value = PathSegment::parse_helper(input, expr_style)?;
+                        segments.push_value(value);
+                    }
+                    segments
+                },
+            })
+        }
     }
 
-    named!(pub mod_style_path_segment -> PathSegment, alt!(
-        syn!(Ident) => { Into::into }
-        |
-        keyword!(super) => { Into::into }
-        |
-        keyword!(self) => { Into::into }
-        |
-        keyword!(Self) => { Into::into }
-        |
-        keyword!(crate) => { Into::into }
-        |
-        keyword!(extern) => { Into::into }
-    ));
-
-    named!(pub qpath -> (Option<QSelf>, Path), alt!(
-        map!(syn!(Path), |p| (None, p))
-        |
-        do_parse!(
-            lt: punct!(<) >>
-            this: syn!(Type) >>
-            path: option!(tuple!(keyword!(as), syn!(Path))) >>
-            gt: punct!(>) >>
-            colon2: punct!(::) >>
-            rest: call!(Punctuated::parse_separated_nonempty) >>
-            ({
-                let (pos, as_, path) = match path {
-                    Some((as_, mut path)) => {
-                        let pos = path.segments.len();
-                        path.segments.push_punct(colon2);
-                        path.segments.extend(rest.into_pairs());
-                        (pos, Some(as_), path)
-                    }
-                    None => {
-                        (0, None, Path {
-                            leading_colon: Some(colon2),
-                            segments: rest,
-                        })
-                    }
-                };
-                (Some(QSelf {
-                    lt_token: lt,
-                    ty: Box::new(this),
-                    position: pos,
-                    as_token: as_,
-                    gt_token: gt,
-                }), path)
-            })
-        )
-        |
-        map!(keyword!(self), |s| (None, s.into()))
-    ));
-
-    named!(pub ty_no_eq_after -> Type, do_parse!(
-        ty: syn!(Type) >>
-        not!(punct!(=)) >>
-        (ty)
-    ));
+    pub fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> {
+        if input.peek(Token![<]) {
+            let lt_token: Token![<] = input.parse()?;
+            let this: Type = input.parse()?;
+            let path = if input.peek(Token![as]) {
+                let as_token: Token![as] = input.parse()?;
+                let path: Path = input.parse()?;
+                Some((as_token, path))
+            } else {
+                None
+            };
+            let gt_token: Token![>] = input.parse()?;
+            let colon2_token: Token![::] = input.parse()?;
+            let mut rest = Punctuated::new();
+            loop {
+                let path = PathSegment::parse_helper(input, expr_style)?;
+                rest.push_value(path);
+                if !input.peek(Token![::]) {
+                    break;
+                }
+                let punct: Token![::] = input.parse()?;
+                rest.push_punct(punct);
+            }
+            let (position, as_token, path) = match path {
+                Some((as_token, mut path)) => {
+                    let pos = path.segments.len();
+                    path.segments.push_punct(colon2_token);
+                    path.segments.extend(rest.into_pairs());
+                    (pos, Some(as_token), path)
+                }
+                None => {
+                    let path = Path {
+                        leading_colon: Some(colon2_token),
+                        segments: rest,
+                    };
+                    (0, None, path)
+                }
+            };
+            let qself = QSelf {
+                lt_token: lt_token,
+                ty: Box::new(this),
+                position: position,
+                as_token: as_token,
+                gt_token: gt_token,
+            };
+            Ok((Some(qself), path))
+        } else {
+            let path = Path::parse_helper(input, expr_style)?;
+            Ok((None, path))
+        }
+    }
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
+
     use proc_macro2::TokenStream;
     use quote::ToTokens;
 
+    use print::TokensOrDefault;
+
     impl ToTokens for Path {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             self.leading_colon.to_tokens(tokens);
@@ -537,25 +577,27 @@
         }
     }
 
-    impl<'a> ToTokens for PathTokens<'a> {
-        fn to_tokens(&self, tokens: &mut TokenStream) {
-            let qself = match *self.0 {
+    impl private {
+        pub fn print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path) {
+            let qself = match *qself {
                 Some(ref qself) => qself,
-                None => return self.1.to_tokens(tokens),
+                None => {
+                    path.to_tokens(tokens);
+                    return;
+                }
             };
             qself.lt_token.to_tokens(tokens);
             qself.ty.to_tokens(tokens);
 
-            // XXX: Gross.
-            let pos = if qself.position > 0 && qself.position >= self.1.segments.len() {
-                self.1.segments.len() - 1
+            let pos = if qself.position > 0 && qself.position >= path.segments.len() {
+                path.segments.len() - 1
             } else {
                 qself.position
             };
-            let mut segments = self.1.segments.pairs();
+            let mut segments = path.segments.pairs();
             if pos > 0 {
                 TokensOrDefault(&qself.as_token).to_tokens(tokens);
-                self.1.leading_colon.to_tokens(tokens);
+                path.leading_colon.to_tokens(tokens);
                 for (i, segment) in segments.by_ref().take(pos).enumerate() {
                     if i + 1 == pos {
                         segment.value().to_tokens(tokens);
@@ -567,7 +609,7 @@
                 }
             } else {
                 qself.gt_token.to_tokens(tokens);
-                self.1.leading_colon.to_tokens(tokens);
+                path.leading_colon.to_tokens(tokens);
             }
             for segment in segments {
                 segment.to_tokens(tokens);
diff --git a/src/print.rs b/src/print.rs
new file mode 100644
index 0000000..90570a0
--- /dev/null
+++ b/src/print.rs
@@ -0,0 +1,16 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+
+pub struct TokensOrDefault<'a, T: 'a>(pub &'a Option<T>);
+
+impl<'a, T> ToTokens for TokensOrDefault<'a, T>
+where
+    T: ToTokens + Default,
+{
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        match *self.0 {
+            Some(ref t) => t.to_tokens(tokens),
+            None => T::default().to_tokens(tokens),
+        }
+    }
+}
diff --git a/src/punctuated.rs b/src/punctuated.rs
index b4a0b3f..7bb7368 100644
--- a/src/punctuated.rs
+++ b/src/punctuated.rs
@@ -38,11 +38,11 @@
 use std::vec;
 
 #[cfg(feature = "parsing")]
-use buffer::Cursor;
+use parse::{Parse, ParseStream, Result};
+#[cfg(any(feature = "full", feature = "derive"))]
+use private;
 #[cfg(feature = "parsing")]
-use parse_error;
-#[cfg(feature = "parsing")]
-use synom::{PResult, Synom};
+use token::Token;
 
 /// A punctuated sequence of syntax tree nodes of type `T` separated by
 /// punctuation of type `P`.
@@ -208,18 +208,16 @@
     pub fn empty_or_trailing(&self) -> bool {
         self.last.is_none()
     }
-}
 
-impl<T, P> Punctuated<T, P>
-where
-    P: Default,
-{
     /// Appends a syntax tree node onto the end of this punctuated sequence.
     ///
     /// If there is not a trailing punctuation in this sequence when this method
     /// is called, the default value of punctuation type `P` is inserted before
     /// the given value of type `T`.
-    pub fn push(&mut self, value: T) {
+    pub fn push(&mut self, value: T)
+    where
+        P: Default,
+    {
         if !self.empty_or_trailing() {
             self.push_punct(Default::default());
         }
@@ -232,7 +230,10 @@
     ///
     /// Panics if `index` is greater than the number of elements previously in
     /// this punctuated sequence.
-    pub fn insert(&mut self, index: usize, value: T) {
+    pub fn insert(&mut self, index: usize, value: T)
+    where
+        P: Default,
+    {
         assert!(index <= self.len());
 
         if index == self.len() {
@@ -241,6 +242,113 @@
             self.inner.insert(index, (value, Default::default()));
         }
     }
+
+    /// Parses zero or more occurrences of `T` separated by punctuation of type
+    /// `P`, with optional trailing punctuation.
+    ///
+    /// Parsing continues until the end of this parse stream. The entire content
+    /// of this parse stream must consist of `T` and `P`.
+    ///
+    /// *This function is available if Syn is built with the `"parsing"`
+    /// feature.*
+    #[cfg(feature = "parsing")]
+    pub fn parse_terminated(input: ParseStream) -> Result<Self>
+    where
+        T: Parse,
+        P: Parse,
+    {
+        Self::parse_terminated_with(input, T::parse)
+    }
+
+    /// Parses zero or more occurrences of `T` using the given parse function,
+    /// separated by punctuation of type `P`, with optional trailing
+    /// punctuation.
+    ///
+    /// Like [`parse_terminated`], the entire content of this stream is expected
+    /// to be parsed.
+    ///
+    /// [`parse_terminated`]: #method.parse_terminated
+    ///
+    /// *This function is available if Syn is built with the `"parsing"`
+    /// feature.*
+    #[cfg(feature = "parsing")]
+    pub fn parse_terminated_with(
+        input: ParseStream,
+        parser: fn(ParseStream) -> Result<T>,
+    ) -> Result<Self>
+    where
+        P: Parse,
+    {
+        let mut punctuated = Punctuated::new();
+
+        loop {
+            if input.is_empty() {
+                break;
+            }
+            let value = parser(input)?;
+            punctuated.push_value(value);
+            if input.is_empty() {
+                break;
+            }
+            let punct = input.parse()?;
+            punctuated.push_punct(punct);
+        }
+
+        Ok(punctuated)
+    }
+
+    /// Parses one or more occurrences of `T` separated by punctuation of type
+    /// `P`, not accepting trailing punctuation.
+    ///
+    /// Parsing continues as long as punctuation `P` is present at the head of
+    /// the stream. This method returns upon parsing a `T` and observing that it
+    /// is not followed by a `P`, even if there are remaining tokens in the
+    /// stream.
+    ///
+    /// *This function is available if Syn is built with the `"parsing"`
+    /// feature.*
+    #[cfg(feature = "parsing")]
+    pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
+    where
+        T: Parse,
+        P: Token + Parse,
+    {
+        Self::parse_separated_nonempty_with(input, T::parse)
+    }
+
+    /// Parses one or more occurrences of `T` using the given parse function,
+    /// separated by punctuation of type `P`, not accepting trailing
+    /// punctuation.
+    ///
+    /// Like [`parse_separated_nonempty`], may complete early without parsing
+    /// the entire content of this stream.
+    ///
+    /// [`parse_separated_nonempty`]: #method.parse_separated_nonempty
+    ///
+    /// *This function is available if Syn is built with the `"parsing"`
+    /// feature.*
+    #[cfg(feature = "parsing")]
+    pub fn parse_separated_nonempty_with(
+        input: ParseStream,
+        parser: fn(ParseStream) -> Result<T>,
+    ) -> Result<Self>
+    where
+        P: Token + Parse,
+    {
+        let mut punctuated = Punctuated::new();
+
+        loop {
+            let value = parser(input)?;
+            punctuated.push_value(value);
+            if !P::peek(input.cursor()) {
+                break;
+            }
+            let punct = input.parse()?;
+            punctuated.push_punct(punct);
+        }
+
+        Ok(punctuated)
+    }
 }
 
 #[cfg(feature = "extra-traits")]
@@ -466,10 +574,8 @@
 }
 
 #[cfg(any(feature = "full", feature = "derive"))]
-impl<'a, T> Iter<'a, T> {
-    // Not public API.
-    #[doc(hidden)]
-    pub fn private_empty() -> Self {
+impl private {
+    pub fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
         Iter {
             inner: Box::new(iter::empty()),
         }
@@ -522,10 +628,8 @@
 }
 
 #[cfg(any(feature = "full", feature = "derive"))]
-impl<'a, T> IterMut<'a, T> {
-    // Not public API.
-    #[doc(hidden)]
-    pub fn private_empty() -> Self {
+impl private {
+    pub fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
         IterMut {
             inner: Box::new(iter::empty()),
         }
@@ -653,126 +757,6 @@
     }
 }
 
-#[cfg(feature = "parsing")]
-impl<T, P> Punctuated<T, P>
-where
-    T: Synom,
-    P: Synom,
-{
-    /// Parse **zero or more** syntax tree nodes with punctuation in between and
-    /// **no trailing** punctuation.
-    pub fn parse_separated(input: Cursor) -> PResult<Self> {
-        Self::parse_separated_with(input, T::parse)
-    }
-
-    /// Parse **one or more** syntax tree nodes with punctuation in bewteen and
-    /// **no trailing** punctuation.
-    /// allowing trailing punctuation.
-    pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self> {
-        Self::parse_separated_nonempty_with(input, T::parse)
-    }
-
-    /// Parse **zero or more** syntax tree nodes with punctuation in between and
-    /// **optional trailing** punctuation.
-    pub fn parse_terminated(input: Cursor) -> PResult<Self> {
-        Self::parse_terminated_with(input, T::parse)
-    }
-
-    /// Parse **one or more** syntax tree nodes with punctuation in between and
-    /// **optional trailing** punctuation.
-    pub fn parse_terminated_nonempty(input: Cursor) -> PResult<Self> {
-        Self::parse_terminated_nonempty_with(input, T::parse)
-    }
-}
-
-#[cfg(feature = "parsing")]
-impl<T, P> Punctuated<T, P>
-where
-    P: Synom,
-{
-    /// Parse **zero or more** syntax tree nodes using the given parser with
-    /// punctuation in between and **no trailing** punctuation.
-    pub fn parse_separated_with(input: Cursor, parse: fn(Cursor) -> PResult<T>) -> PResult<Self> {
-        Self::parse(input, parse, false)
-    }
-
-    /// Parse **one or more** syntax tree nodes using the given parser with
-    /// punctuation in between and **no trailing** punctuation.
-    pub fn parse_separated_nonempty_with(
-        input: Cursor,
-        parse: fn(Cursor) -> PResult<T>,
-    ) -> PResult<Self> {
-        match Self::parse(input, parse, false) {
-            Ok((ref b, _)) if b.is_empty() => parse_error(),
-            other => other,
-        }
-    }
-
-    /// Parse **zero or more** syntax tree nodes using the given parser with
-    /// punctuation in between and **optional trailing** punctuation.
-    pub fn parse_terminated_with(input: Cursor, parse: fn(Cursor) -> PResult<T>) -> PResult<Self> {
-        Self::parse(input, parse, true)
-    }
-
-    /// Parse **one or more** syntax tree nodes using the given parser with
-    /// punctuation in between and **optional trailing** punctuation.
-    pub fn parse_terminated_nonempty_with(
-        input: Cursor,
-        parse: fn(Cursor) -> PResult<T>,
-    ) -> PResult<Self> {
-        match Self::parse(input, parse, true) {
-            Ok((ref b, _)) if b.is_empty() => parse_error(),
-            other => other,
-        }
-    }
-
-    fn parse(
-        mut input: Cursor,
-        parse: fn(Cursor) -> PResult<T>,
-        terminated: bool,
-    ) -> PResult<Self> {
-        let mut res = Punctuated::new();
-
-        // get the first element
-        match parse(input) {
-            Err(_) => Ok((res, input)),
-            Ok((o, i)) => {
-                if i == input {
-                    return parse_error();
-                }
-                input = i;
-                res.push_value(o);
-
-                // get the separator first
-                while let Ok((s, i2)) = P::parse(input) {
-                    if i2 == input {
-                        break;
-                    }
-
-                    // get the element next
-                    if let Ok((o3, i3)) = parse(i2) {
-                        if i3 == i2 {
-                            break;
-                        }
-                        res.push_punct(s);
-                        res.push_value(o3);
-                        input = i3;
-                    } else {
-                        break;
-                    }
-                }
-                if terminated {
-                    if let Ok((sep, after)) = P::parse(input) {
-                        res.push_punct(sep);
-                        input = after;
-                    }
-                }
-                Ok((res, input))
-            }
-        }
-    }
-}
-
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
diff --git a/src/span.rs b/src/span.rs
new file mode 100644
index 0000000..27a7fe8
--- /dev/null
+++ b/src/span.rs
@@ -0,0 +1,67 @@
+use proc_macro2::Span;
+
+pub trait IntoSpans<S> {
+    fn into_spans(self) -> S;
+}
+
+impl IntoSpans<[Span; 1]> for Span {
+    fn into_spans(self) -> [Span; 1] {
+        [self]
+    }
+}
+
+impl IntoSpans<[Span; 2]> for Span {
+    fn into_spans(self) -> [Span; 2] {
+        [self, self]
+    }
+}
+
+impl IntoSpans<[Span; 3]> for Span {
+    fn into_spans(self) -> [Span; 3] {
+        [self, self, self]
+    }
+}
+
+impl IntoSpans<[Span; 1]> for [Span; 1] {
+    fn into_spans(self) -> [Span; 1] {
+        self
+    }
+}
+
+impl IntoSpans<[Span; 2]> for [Span; 2] {
+    fn into_spans(self) -> [Span; 2] {
+        self
+    }
+}
+
+impl IntoSpans<[Span; 3]> for [Span; 3] {
+    fn into_spans(self) -> [Span; 3] {
+        self
+    }
+}
+
+#[cfg(feature = "parsing")]
+pub trait FromSpans: Sized {
+    fn from_spans(spans: &[Span]) -> Self;
+}
+
+#[cfg(feature = "parsing")]
+impl FromSpans for [Span; 1] {
+    fn from_spans(spans: &[Span]) -> Self {
+        [spans[0]]
+    }
+}
+
+#[cfg(feature = "parsing")]
+impl FromSpans for [Span; 2] {
+    fn from_spans(spans: &[Span]) -> Self {
+        [spans[0], spans[1]]
+    }
+}
+
+#[cfg(feature = "parsing")]
+impl FromSpans for [Span; 3] {
+    fn from_spans(spans: &[Span]) -> Self {
+        [spans[0], spans[1], spans[2]]
+    }
+}
diff --git a/src/spanned.rs b/src/spanned.rs
index 9372dce..6dd50cb 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -29,17 +29,16 @@
 //! static assertion that `Sync` is implemented for that type.
 //!
 //! ```
-//! #[macro_use]
-//! extern crate quote;
-//!
-//! extern crate syn;
-//! extern crate proc_macro;
-//! extern crate proc_macro2;
-//!
-//! use syn::Type;
-//! use syn::spanned::Spanned;
+//! # extern crate proc_macro;
+//! # extern crate proc_macro2;
+//! # extern crate quote;
+//! # extern crate syn;
+//! #
 //! use proc_macro::TokenStream;
 //! use proc_macro2::Span;
+//! use quote::quote_spanned;
+//! use syn::Type;
+//! use syn::spanned::Spanned;
 //!
 //! # const IGNORE_TOKENS: &str = stringify! {
 //! #[proc_macro_derive(MyMacro)]
@@ -85,9 +84,10 @@
 /// tree node.
 ///
 /// This trait is automatically implemented for all types that implement
-/// [`ToTokens`] from the `quote` crate.
+/// [`ToTokens`] from the `quote` crate. It is sealed and cannot be implemented
+/// outside of the Syn crate other than by implementing `ToTokens`.
 ///
-/// [`ToTokens`]: https://docs.rs/quote/0.4/quote/trait.ToTokens.html
+/// [`ToTokens`]: https://docs.rs/quote/0.6/quote/trait.ToTokens.html
 ///
 /// See the [module documentation] for an example.
 ///
@@ -95,14 +95,20 @@
 ///
 /// *This trait is available if Syn is built with both the `"parsing"` and
 /// `"printing"` features.*
-pub trait Spanned {
+pub trait Spanned: private::Sealed {
     /// Returns a `Span` covering the complete contents of this syntax tree
     /// node, or [`Span::call_site()`] if this node is empty.
     ///
-    /// [`Span::call_site()`]: https://docs.rs/proc-macro2/0.2/proc_macro2/struct.Span.html#method.call_site
+    /// [`Span::call_site()`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html#method.call_site
     fn span(&self) -> Span;
 }
 
+mod private {
+    use quote::ToTokens;
+    pub trait Sealed {}
+    impl<T: ToTokens> Sealed for T {}
+}
+
 impl<T> Spanned for T
 where
     T: ToTokens,
diff --git a/src/synom.rs b/src/synom.rs
index f3454eb..e69de29 100644
--- a/src/synom.rs
+++ b/src/synom.rs
@@ -1,419 +0,0 @@
-// Copyright 2018 Syn Developers
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Parsing interface for parsing a token stream into a syntax tree node.
-//!
-//! Parsing in Syn is built on parser functions that take in a [`Cursor`] and
-//! produce a [`PResult<T>`] where `T` is some syntax tree node. `Cursor` is a
-//! cheaply copyable cursor over a range of tokens in a token stream, and
-//! `PResult` is a result that packages together a parsed syntax tree node `T`
-//! with a stream of remaining unparsed tokens after `T` represented as another
-//! `Cursor`, or a [`ParseError`] if parsing failed.
-//!
-//! [`Cursor`]: ../buffer/index.html
-//! [`PResult<T>`]: type.PResult.html
-//! [`ParseError`]: struct.ParseError.html
-//!
-//! This `Cursor`- and `PResult`-based interface is convenient for parser
-//! combinators and parser implementations, but not necessarily when you just
-//! have some tokens that you want to parse. For that we expose the following
-//! two entry points.
-//!
-//! ## The `syn::parse*` functions
-//!
-//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
-//! as an entry point for parsing syntax tree nodes that can be parsed in an
-//! obvious default way. These functions can return any syntax tree node that
-//! implements the [`Synom`] trait, which includes most types in Syn.
-//!
-//! [`syn::parse`]: ../fn.parse.html
-//! [`syn::parse2`]: ../fn.parse2.html
-//! [`syn::parse_str`]: ../fn.parse_str.html
-//! [`Synom`]: trait.Synom.html
-//!
-//! ```
-//! use syn::Type;
-//!
-//! # fn run_parser() -> Result<(), syn::synom::ParseError> {
-//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
-//! #     Ok(())
-//! # }
-//! #
-//! # fn main() {
-//! #     run_parser().unwrap();
-//! # }
-//! ```
-//!
-//! The [`parse_quote!`] macro also uses this approach.
-//!
-//! [`parse_quote!`]: ../macro.parse_quote.html
-//!
-//! ## The `Parser` trait
-//!
-//! Some types can be parsed in several ways depending on context. For example
-//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
-//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
-//! may or may not allow trailing punctuation, and parsing it the wrong way
-//! would either reject valid input or accept invalid input.
-//!
-//! [`Attribute`]: ../struct.Attribute.html
-//! [`Punctuated`]: ../punctuated/index.html
-//!
-//! The `Synom` trait is not implemented in these cases because there is no good
-//! behavior to consider the default.
-//!
-//! ```ignore
-//! // Can't parse `Punctuated` without knowing whether trailing punctuation
-//! // should be allowed in this context.
-//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
-//! ```
-//!
-//! In these cases the types provide a choice of parser functions rather than a
-//! single `Synom` implementation, and those parser functions can be invoked
-//! through the [`Parser`] trait.
-//!
-//! [`Parser`]: trait.Parser.html
-//!
-//! ```
-//! # #[macro_use]
-//! # extern crate syn;
-//! #
-//! # extern crate proc_macro2;
-//! # use proc_macro2::TokenStream;
-//! #
-//! use syn::synom::Parser;
-//! use syn::punctuated::Punctuated;
-//! use syn::{PathSegment, Expr, Attribute};
-//!
-//! # fn run_parsers() -> Result<(), syn::synom::ParseError> {
-//! #     let tokens = TokenStream::new().into();
-//! // Parse a nonempty sequence of path segments separated by `::` punctuation
-//! // with no trailing punctuation.
-//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
-//! let path = parser.parse(tokens)?;
-//!
-//! #     let tokens = TokenStream::new().into();
-//! // Parse a possibly empty sequence of expressions terminated by commas with
-//! // an optional trailing punctuation.
-//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
-//! let args = parser.parse(tokens)?;
-//!
-//! #     let tokens = TokenStream::new().into();
-//! // Parse zero or more outer attributes but not inner attributes.
-//! named!(outer_attrs -> Vec<Attribute>, many0!(Attribute::parse_outer));
-//! let attrs = outer_attrs.parse(tokens)?;
-//! #
-//! #     Ok(())
-//! # }
-//! #
-//! # fn main() {}
-//! ```
-//!
-//! # Implementing a parser function
-//!
-//! Parser functions are usually implemented using the [`nom`]-style parser
-//! combinator macros provided by Syn, but may also be implemented without
-//! macros be using the low-level [`Cursor`] API directly.
-//!
-//! [`nom`]: https://github.com/Geal/nom
-//!
-//! The following parser combinator macros are available and a `Synom` parsing
-//! example is provided for each one.
-//!
-//! - [`alt!`](../macro.alt.html)
-//! - [`braces!`](../macro.braces.html)
-//! - [`brackets!`](../macro.brackets.html)
-//! - [`call!`](../macro.call.html)
-//! - [`cond!`](../macro.cond.html)
-//! - [`cond_reduce!`](../macro.cond_reduce.html)
-//! - [`custom_keyword!`](../macro.custom_keyword.html)
-//! - [`do_parse!`](../macro.do_parse.html)
-//! - [`epsilon!`](../macro.epsilon.html)
-//! - [`input_end!`](../macro.input_end.html)
-//! - [`keyword!`](../macro.keyword.html)
-//! - [`many0!`](../macro.many0.html)
-//! - [`map!`](../macro.map.html)
-//! - [`not!`](../macro.not.html)
-//! - [`option!`](../macro.option.html)
-//! - [`parens!`](../macro.parens.html)
-//! - [`punct!`](../macro.punct.html)
-//! - [`reject!`](../macro.reject.html)
-//! - [`switch!`](../macro.switch.html)
-//! - [`syn!`](../macro.syn.html)
-//! - [`tuple!`](../macro.tuple.html)
-//! - [`value!`](../macro.value.html)
-//!
-//! *This module is available if Syn is built with the `"parsing"` feature.*
-
-#[cfg(all(
-    not(all(target_arch = "wasm32", target_os = "unknown")),
-    feature = "proc-macro"
-))]
-use proc_macro;
-use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, TokenStream, TokenTree};
-
-use error::parse_error;
-pub use error::{PResult, ParseError};
-
-use buffer::{Cursor, TokenBuffer};
-
-/// Parsing interface implemented by all types that can be parsed in a default
-/// way from a token stream.
-///
-/// Refer to the [module documentation] for details about parsing in Syn.
-///
-/// [module documentation]: index.html
-///
-/// *This trait is available if Syn is built with the `"parsing"` feature.*
-pub trait Synom: Sized {
-    fn parse(input: Cursor) -> PResult<Self>;
-
-    /// A short name of the type being parsed.
-    ///
-    /// The description should only be used for a simple name.  It should not
-    /// contain newlines or sentence-ending punctuation, to facilitate embedding in
-    /// larger user-facing strings.  Syn will use this description when building
-    /// error messages about parse failures.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # use syn::buffer::Cursor;
-    /// # use syn::synom::{Synom, PResult};
-    /// #
-    /// struct ExprMacro {
-    ///     // ...
-    /// }
-    ///
-    /// impl Synom for ExprMacro {
-    /// #   fn parse(input: Cursor) -> PResult<Self> { unimplemented!() }
-    ///     // fn parse(...) -> ... { ... }
-    ///
-    ///     fn description() -> Option<&'static str> {
-    ///         // Will result in messages like
-    ///         //
-    ///         //     "failed to parse macro invocation expression: $reason"
-    ///         Some("macro invocation expression")
-    ///     }
-    /// }
-    /// ```
-    fn description() -> Option<&'static str> {
-        None
-    }
-}
-
-impl Synom for TokenStream {
-    fn parse(input: Cursor) -> PResult<Self> {
-        Ok((input.token_stream(), Cursor::empty()))
-    }
-
-    fn description() -> Option<&'static str> {
-        Some("arbitrary token stream")
-    }
-}
-
-impl Synom for TokenTree {
-    fn parse(input: Cursor) -> PResult<Self> {
-        match input.token_tree() {
-            Some((tt, rest)) => Ok((tt, rest)),
-            None => parse_error(),
-        }
-    }
-
-    fn description() -> Option<&'static str> {
-        Some("token tree")
-    }
-}
-
-impl Synom for Group {
-    fn parse(input: Cursor) -> PResult<Self> {
-        for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
-            if let Some((inside, span, rest)) = input.group(*delim) {
-                let mut group = Group::new(*delim, inside.token_stream());
-                group.set_span(span);
-                return Ok((group, rest));
-            }
-        }
-        parse_error()
-    }
-
-    fn description() -> Option<&'static str> {
-        Some("group token")
-    }
-}
-
-impl Synom for Ident {
-    fn parse(input: Cursor) -> PResult<Self> {
-        let (ident, rest) = match input.ident() {
-            Some(ident) => ident,
-            _ => return parse_error(),
-        };
-        match &ident.to_string()[..] {
-            "_"
-            // Based on https://doc.rust-lang.org/grammar.html#keywords
-            // and https://github.com/rust-lang/rfcs/blob/master/text/2421-unreservations-2018.md
-            | "abstract" | "as" | "become" | "box" | "break" | "const"
-            | "continue" | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final"
-            | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match"
-            | "mod" | "move" | "mut" | "override" | "priv" | "proc" | "pub"
-            | "ref" | "return" | "Self" | "self" | "static" | "struct"
-            | "super" | "trait" | "true" | "type" | "typeof" | "unsafe" | "unsized" | "use"
-            | "virtual" | "where" | "while" | "yield" => return parse_error(),
-            _ => {}
-        }
-
-        Ok((ident, rest))
-    }
-
-    fn description() -> Option<&'static str> {
-        Some("identifier")
-    }
-}
-
-impl Synom for Punct {
-    fn parse(input: Cursor) -> PResult<Self> {
-        match input.punct() {
-            Some((punct, rest)) => Ok((punct, rest)),
-            None => parse_error(),
-        }
-    }
-
-    fn description() -> Option<&'static str> {
-        Some("punctuation token")
-    }
-}
-
-impl Synom for Literal {
-    fn parse(input: Cursor) -> PResult<Self> {
-        match input.literal() {
-            Some((literal, rest)) => Ok((literal, rest)),
-            None => parse_error(),
-        }
-    }
-
-    fn description() -> Option<&'static str> {
-        Some("literal token")
-    }
-}
-
-/// Parser that can parse Rust tokens into a particular syntax tree node.
-///
-/// Refer to the [module documentation] for details about parsing in Syn.
-///
-/// [module documentation]: index.html
-///
-/// *This trait is available if Syn is built with the `"parsing"` feature.*
-pub trait Parser: Sized {
-    type Output;
-
-    /// Parse a proc-macro2 token stream into the chosen syntax tree node.
-    fn parse2(self, tokens: TokenStream) -> Result<Self::Output, ParseError>;
-
-    /// Parse tokens of source code into the chosen syntax tree node.
-    ///
-    /// *This method is available if Syn is built with both the `"parsing"` and
-    /// `"proc-macro"` features.*
-    #[cfg(all(
-        not(all(target_arch = "wasm32", target_os = "unknown")),
-        feature = "proc-macro"
-    ))]
-    fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output, ParseError> {
-        self.parse2(tokens.into())
-    }
-
-    /// Parse a string of Rust code into the chosen syntax tree node.
-    ///
-    /// # Hygiene
-    ///
-    /// Every span in the resulting syntax tree will be set to resolve at the
-    /// macro call site.
-    fn parse_str(self, s: &str) -> Result<Self::Output, ParseError> {
-        match s.parse() {
-            Ok(tts) => self.parse2(tts),
-            Err(_) => Err(ParseError::new("error while lexing input string")),
-        }
-    }
-}
-
-impl<F, T> Parser for F
-where
-    F: FnOnce(Cursor) -> PResult<T>,
-{
-    type Output = T;
-
-    fn parse2(self, tokens: TokenStream) -> Result<T, ParseError> {
-        let buf = TokenBuffer::new2(tokens);
-        let (t, rest) = self(buf.begin())?;
-        if rest.eof() {
-            Ok(t)
-        } else if rest == buf.begin() {
-            // parsed nothing
-            Err(ParseError::new("failed to parse anything"))
-        } else {
-            Err(ParseError::new("failed to parse all tokens"))
-        }
-    }
-}
-
-/// Extension traits that are made available within the `call!` parser.
-///
-/// *This module is available if Syn is built with the `"parsing"` feature.*
-pub mod ext {
-    use super::*;
-    use proc_macro2::Ident;
-
-    /// Additional parsing methods for `Ident`.
-    ///
-    /// This trait is sealed and cannot be implemented for types outside of Syn.
-    ///
-    /// *This trait is available if Syn is built with the `"parsing"` feature.*
-    pub trait IdentExt: Sized + private::Sealed {
-        /// Parses any identifier including keywords.
-        ///
-        /// This is useful when parsing a DSL which allows Rust keywords as
-        /// identifiers.
-        ///
-        /// ```rust
-        /// #[macro_use]
-        /// extern crate syn;
-        ///
-        /// use syn::Ident;
-        ///
-        /// // Parses input that looks like `name = NAME` where `NAME` can be
-        /// // any identifier.
-        /// //
-        /// // Examples:
-        /// //
-        /// //     name = anything
-        /// //     name = impl
-        /// named!(parse_dsl -> Ident, do_parse!(
-        ///     custom_keyword!(name) >>
-        ///     punct!(=) >>
-        ///     name: call!(Ident::parse_any) >>
-        ///     (name)
-        /// ));
-        /// #
-        /// # fn main() {}
-        /// ```
-        fn parse_any(input: Cursor) -> PResult<Self>;
-    }
-
-    impl IdentExt for Ident {
-        fn parse_any(input: Cursor) -> PResult<Self> {
-            input.ident().map_or_else(parse_error, Ok)
-        }
-    }
-
-    mod private {
-        use proc_macro2::Ident;
-
-        pub trait Sealed {}
-
-        impl Sealed for Ident {}
-    }
-}
diff --git a/src/token.rs b/src/token.rs
index 0fe8c4d..a95bdc2 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -21,10 +21,9 @@
 //! [`ItemStatic`]: ../struct.ItemStatic.html
 //!
 //! ```
-//! # #[macro_use]
 //! # extern crate syn;
 //! #
-//! # use syn::{Attribute, Visibility, Ident, Type, Expr};
+//! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};
 //! #
 //! pub struct ItemStatic {
 //!     pub attrs: Vec<Attribute>,
@@ -44,471 +43,544 @@
 //!
 //! # Parsing
 //!
-//! These tokens can be parsed using the [`Synom`] trait and the parser
-//! combinator macros [`punct!`], [`keyword!`], [`parens!`], [`braces!`], and
-//! [`brackets!`].
+//! Keywords and punctuation can be parsed through the [`ParseStream::parse`]
+//! method. Delimiter tokens are parsed using the [`parenthesized!`],
+//! [`bracketed!`] and [`braced!`] macros.
 //!
-//! [`Synom`]: ../synom/trait.Synom.html
-//! [`punct!`]: ../macro.punct.html
-//! [`keyword!`]: ../macro.keyword.html
-//! [`parens!`]: ../macro.parens.html
-//! [`braces!`]: ../macro.braces.html
-//! [`brackets!`]: ../macro.brackets.html
+//! [`ParseStream::parse`]: ../parse/struct.ParseBuffer.html#method.parse
+//! [`parenthesized!`]: ../macro.parenthesized.html
+//! [`bracketed!`]: ../macro.bracketed.html
+//! [`braced!`]: ../macro.braced.html
 //!
 //! ```
-//! #[macro_use]
-//! extern crate syn;
-//!
-//! use syn::synom::Synom;
-//! use syn::{Attribute, Visibility, Ident, Type, Expr};
+//! # extern crate syn;
 //! #
-//! # struct ItemStatic;
-//! # use syn::ItemStatic as SynItemStatic;
+//! use syn::Attribute;
+//! use syn::parse::{Parse, ParseStream, Result};
+//! #
+//! # enum ItemStatic {}
 //!
 //! // Parse the ItemStatic struct shown above.
-//! impl Synom for ItemStatic {
-//!     named!(parse -> Self, do_parse!(
-//! #       (ItemStatic)
-//! #   ));
-//! # }
-//! #
-//! # mod example {
-//! #   use super::*;
-//! #   use super::SynItemStatic as ItemStatic;
-//! #
-//! #   named!(parse -> ItemStatic, do_parse!(
-//!         attrs: many0!(Attribute::parse_outer) >>
-//!         vis: syn!(Visibility) >>
-//!         static_token: keyword!(static) >>
-//!         mutability: option!(keyword!(mut)) >>
-//!         ident: syn!(Ident) >>
-//!         colon_token: punct!(:) >>
-//!         ty: syn!(Type) >>
-//!         eq_token: punct!(=) >>
-//!         expr: syn!(Expr) >>
-//!         semi_token: punct!(;) >>
-//!         (ItemStatic {
-//!             attrs, vis, static_token, mutability, ident, colon_token,
-//!             ty: Box::new(ty), eq_token, expr: Box::new(expr), semi_token,
+//! impl Parse for ItemStatic {
+//!     fn parse(input: ParseStream) -> Result<Self> {
+//!         # use syn::ItemStatic;
+//!         # fn parse(input: ParseStream) -> Result<ItemStatic> {
+//!         Ok(ItemStatic {
+//!             attrs: input.call(Attribute::parse_outer)?,
+//!             vis: input.parse()?,
+//!             static_token: input.parse()?,
+//!             mutability: input.parse()?,
+//!             ident: input.parse()?,
+//!             colon_token: input.parse()?,
+//!             ty: input.parse()?,
+//!             eq_token: input.parse()?,
+//!             expr: input.parse()?,
+//!             semi_token: input.parse()?,
 //!         })
-//!     ));
+//!         # }
+//!         # unimplemented!()
+//!     }
 //! }
 //! #
 //! # fn main() {}
 //! ```
 
+use std;
+#[cfg(feature = "parsing")]
+use std::cell::Cell;
+#[cfg(feature = "extra-traits")]
+use std::cmp;
+#[cfg(feature = "extra-traits")]
+use std::fmt::{self, Debug};
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+#[cfg(feature = "parsing")]
+use std::rc::Rc;
+
+#[cfg(feature = "parsing")]
+use proc_macro2::Delimiter;
+#[cfg(feature = "printing")]
+use proc_macro2::TokenStream;
 use proc_macro2::{Ident, Span};
+#[cfg(feature = "printing")]
+use quote::{ToTokens, TokenStreamExt};
 
-macro_rules! tokens {
-    (
-        punct: {
-            $($punct:tt pub struct $punct_name:ident/$len:tt #[$punct_doc:meta])*
-        }
-        delimiter: {
-            $($delimiter:tt pub struct $delimiter_name:ident #[$delimiter_doc:meta])*
-        }
-        keyword: {
-            $($keyword:tt pub struct $keyword_name:ident #[$keyword_doc:meta])*
-        }
-    ) => (
-        $(token_punct_def! { #[$punct_doc] pub struct $punct_name/$len })*
-        $(token_punct_parser! { $punct pub struct $punct_name })*
-        $(token_delimiter! { #[$delimiter_doc] $delimiter pub struct $delimiter_name })*
-        $(token_keyword! { #[$keyword_doc] $keyword pub struct $keyword_name })*
-    )
+#[cfg(feature = "parsing")]
+use buffer::Cursor;
+#[cfg(feature = "parsing")]
+use error::Result;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "parsing")]
+use lifetime::Lifetime;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "parsing")]
+use lit::{Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr};
+#[cfg(feature = "parsing")]
+use lookahead;
+#[cfg(feature = "parsing")]
+use parse::{Parse, ParseStream};
+use span::IntoSpans;
+
+/// Marker trait for types that represent single tokens.
+///
+/// This trait is sealed and cannot be implemented for types outside of Syn.
+#[cfg(feature = "parsing")]
+pub trait Token: private::Sealed {
+    // Not public API.
+    #[doc(hidden)]
+    fn peek(cursor: Cursor) -> bool;
+
+    // Not public API.
+    #[doc(hidden)]
+    fn display() -> &'static str;
 }
 
-macro_rules! token_punct_def {
-    (#[$doc:meta]pub struct $name:ident / $len:tt) => {
-        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
-        #[$doc]
-        ///
-        /// Don't try to remember the name of this type -- use the [`Token!`]
-        /// macro instead.
-        ///
-        /// [`Token!`]: index.html
-        pub struct $name(pub [Span; $len]);
-
-        impl $name {
-            pub fn new(span: Span) -> Self {
-                $name([span; $len])
-            }
-        }
-
-        impl ::std::default::Default for $name {
-            fn default() -> Self {
-                $name([Span::call_site(); $len])
-            }
-        }
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::fmt::Debug for $name {
-            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-                f.write_str(stringify!($name))
-            }
-        }
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::cmp::Eq for $name {}
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::cmp::PartialEq for $name {
-            fn eq(&self, _other: &$name) -> bool {
-                true
-            }
-        }
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::hash::Hash for $name {
-            fn hash<H>(&self, _state: &mut H)
-            where
-                H: ::std::hash::Hasher,
-            {
-            }
-        }
-
-        impl From<Span> for $name {
-            fn from(span: Span) -> Self {
-                $name([span; $len])
-            }
-        }
-    };
+#[cfg(feature = "parsing")]
+mod private {
+    pub trait Sealed {}
 }
 
-macro_rules! token_punct_parser {
-    ($s:tt pub struct $name:ident) => {
-        #[cfg(feature = "printing")]
-        impl ::quote::ToTokens for $name {
-            fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
-                printing::punct($s, &self.0, tokens);
+#[cfg(feature = "parsing")]
+fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
+    let scope = Span::call_site();
+    let unexpected = Rc::new(Cell::new(None));
+    let buffer = ::private::new_parse_buffer(scope, cursor, unexpected);
+    peek(&buffer)
+}
+
+macro_rules! impl_token {
+    ($name:ident $display:expr) => {
+        #[cfg(feature = "parsing")]
+        impl Token for $name {
+            fn peek(cursor: Cursor) -> bool {
+                fn peek(input: ParseStream) -> bool {
+                    <$name as Parse>::parse(input).is_ok()
+                }
+                peek_impl(cursor, peek)
+            }
+
+            fn display() -> &'static str {
+                $display
             }
         }
 
         #[cfg(feature = "parsing")]
-        impl ::Synom for $name {
-            fn parse(tokens: $crate::buffer::Cursor) -> $crate::synom::PResult<$name> {
-                parsing::punct($s, tokens, $name)
-            }
-
-            fn description() -> Option<&'static str> {
-                Some(concat!("`", $s, "`"))
-            }
-        }
+        impl private::Sealed for $name {}
     };
 }
 
-macro_rules! token_keyword {
-    (#[$doc:meta] $s:tt pub struct $name:ident) => {
-        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
-        #[$doc]
-        ///
-        /// Don't try to remember the name of this type -- use the [`Token!`]
-        /// macro instead.
-        ///
-        /// [`Token!`]: index.html
-        pub struct $name(pub Span);
+impl_token!(Ident "identifier");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(Lifetime "lifetime");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(Lit "literal");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(LitStr "string literal");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(LitByteStr "byte string literal");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(LitByte "byte literal");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(LitChar "character literal");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(LitInt "integer literal");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(LitFloat "floating point literal");
+#[cfg(any(feature = "full", feature = "derive"))]
+impl_token!(LitBool "boolean literal");
 
-        impl ::std::default::Default for $name {
-            fn default() -> Self {
-                $name(Span::call_site())
-            }
-        }
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::fmt::Debug for $name {
-            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-                f.write_str(stringify!($name))
-            }
-        }
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::cmp::Eq for $name {}
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::cmp::PartialEq for $name {
-            fn eq(&self, _other: &$name) -> bool {
-                true
-            }
-        }
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::hash::Hash for $name {
-            fn hash<H>(&self, _state: &mut H)
-            where
-                H: ::std::hash::Hasher,
-            {
-            }
-        }
-
-        #[cfg(feature = "printing")]
-        impl ::quote::ToTokens for $name {
-            fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
-                printing::keyword($s, &self.0, tokens);
-            }
-        }
-
-        #[cfg(feature = "parsing")]
-        impl ::Synom for $name {
-            fn parse(tokens: $crate::buffer::Cursor) -> $crate::synom::PResult<$name> {
-                parsing::keyword($s, tokens, $name)
+macro_rules! define_keywords {
+    ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
+        $(
+            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
+            #[$doc]
+            ///
+            /// Don't try to remember the name of this type -- use the [`Token!`]
+            /// macro instead.
+            ///
+            /// [`Token!`]: index.html
+            pub struct $name {
+                pub span: Span,
             }
 
-            fn description() -> Option<&'static str> {
-                Some(concat!("`", $s, "`"))
+            #[doc(hidden)]
+            #[allow(non_snake_case)]
+            pub fn $name<S: IntoSpans<[Span; 1]>>(span: S) -> $name {
+                $name {
+                    span: span.into_spans()[0],
+                }
             }
-        }
 
-        impl From<Span> for $name {
-            fn from(span: Span) -> Self {
-                $name(span)
+            impl_token!($name concat!("`", $token, "`"));
+
+            impl std::default::Default for $name {
+                fn default() -> Self {
+                    $name {
+                        span: Span::call_site(),
+                    }
+                }
             }
-        }
-    };
-}
 
-macro_rules! token_delimiter {
-    (#[$doc:meta] $s:tt pub struct $name:ident) => {
-        #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
-        #[$doc]
-        pub struct $name(pub Span);
-
-        impl ::std::default::Default for $name {
-            fn default() -> Self {
-                $name(Span::call_site())
+            #[cfg(feature = "extra-traits")]
+            impl Debug for $name {
+                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                    f.write_str(stringify!($name))
+                }
             }
-        }
 
-        #[cfg(feature = "extra-traits")]
-        impl ::std::fmt::Debug for $name {
-            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-                f.write_str(stringify!($name))
+            #[cfg(feature = "extra-traits")]
+            impl cmp::Eq for $name {}
+
+            #[cfg(feature = "extra-traits")]
+            impl PartialEq for $name {
+                fn eq(&self, _other: &$name) -> bool {
+                    true
+                }
             }
-        }
 
-        #[cfg(feature = "extra-traits")]
-        impl ::std::cmp::Eq for $name {}
-
-        #[cfg(feature = "extra-traits")]
-        impl ::std::cmp::PartialEq for $name {
-            fn eq(&self, _other: &$name) -> bool {
-                true
+            #[cfg(feature = "extra-traits")]
+            impl Hash for $name {
+                fn hash<H: Hasher>(&self, _state: &mut H) {}
             }
-        }
 
-        #[cfg(feature = "extra-traits")]
-        impl ::std::hash::Hash for $name {
-            fn hash<H>(&self, _state: &mut H)
-            where
-                H: ::std::hash::Hasher,
-            {
-            }
-        }
-
-        impl $name {
             #[cfg(feature = "printing")]
-            pub fn surround<F>(&self, tokens: &mut ::proc_macro2::TokenStream, f: F)
-            where
-                F: FnOnce(&mut ::proc_macro2::TokenStream),
-            {
-                printing::delim($s, &self.0, tokens, f);
+            impl ToTokens for $name {
+                fn to_tokens(&self, tokens: &mut TokenStream) {
+                    printing::keyword($token, &self.span, tokens);
+                }
             }
 
             #[cfg(feature = "parsing")]
-            pub fn parse<F, R>(
-                tokens: $crate::buffer::Cursor,
-                f: F,
-            ) -> $crate::synom::PResult<($name, R)>
-            where
-                F: FnOnce($crate::buffer::Cursor) -> $crate::synom::PResult<R>,
-            {
-                parsing::delim($s, tokens, $name, f)
+            impl Parse for $name {
+                fn parse(input: ParseStream) -> Result<Self> {
+                    Ok($name {
+                        span: parsing::keyword(input, $token)?,
+                    })
+                }
             }
-        }
-
-        impl From<Span> for $name {
-            fn from(span: Span) -> Self {
-                $name(span)
-            }
-        }
+        )*
     };
 }
 
-token_punct_def! {
-    /// `_`
-    pub struct Underscore/1
+macro_rules! define_punctuation_structs {
+    ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
+        $(
+            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
+            #[$doc]
+            ///
+            /// Don't try to remember the name of this type -- use the [`Token!`]
+            /// macro instead.
+            ///
+            /// [`Token!`]: index.html
+            pub struct $name {
+                pub spans: [Span; $len],
+            }
+
+            #[doc(hidden)]
+            #[allow(non_snake_case)]
+            pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {
+                $name {
+                    spans: spans.into_spans(),
+                }
+            }
+
+            impl_token!($name concat!("`", $token, "`"));
+
+            impl std::default::Default for $name {
+                fn default() -> Self {
+                    $name {
+                        spans: [Span::call_site(); $len],
+                    }
+                }
+            }
+
+            #[cfg(feature = "extra-traits")]
+            impl Debug for $name {
+                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                    f.write_str(stringify!($name))
+                }
+            }
+
+            #[cfg(feature = "extra-traits")]
+            impl cmp::Eq for $name {}
+
+            #[cfg(feature = "extra-traits")]
+            impl PartialEq for $name {
+                fn eq(&self, _other: &$name) -> bool {
+                    true
+                }
+            }
+
+            #[cfg(feature = "extra-traits")]
+            impl Hash for $name {
+                fn hash<H: Hasher>(&self, _state: &mut H) {}
+            }
+        )*
+    };
+}
+
+macro_rules! define_punctuation {
+    ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
+        $(
+            define_punctuation_structs! {
+                $token pub struct $name/$len #[$doc]
+            }
+
+            #[cfg(feature = "printing")]
+            impl ToTokens for $name {
+                fn to_tokens(&self, tokens: &mut TokenStream) {
+                    printing::punct($token, &self.spans, tokens);
+                }
+            }
+
+            #[cfg(feature = "parsing")]
+            impl Parse for $name {
+                fn parse(input: ParseStream) -> Result<Self> {
+                    Ok($name {
+                        spans: parsing::punct(input, $token)?,
+                    })
+                }
+            }
+        )*
+    };
+}
+
+macro_rules! define_delimiters {
+    ($($token:tt pub struct $name:ident #[$doc:meta])*) => {
+        $(
+            #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
+            #[$doc]
+            pub struct $name {
+                pub span: Span,
+            }
+
+            #[doc(hidden)]
+            #[allow(non_snake_case)]
+            pub fn $name<S: IntoSpans<[Span; 1]>>(span: S) -> $name {
+                $name {
+                    span: span.into_spans()[0],
+                }
+            }
+
+            impl std::default::Default for $name {
+                fn default() -> Self {
+                    $name {
+                        span: Span::call_site(),
+                    }
+                }
+            }
+
+            #[cfg(feature = "extra-traits")]
+            impl Debug for $name {
+                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                    f.write_str(stringify!($name))
+                }
+            }
+
+            #[cfg(feature = "extra-traits")]
+            impl cmp::Eq for $name {}
+
+            #[cfg(feature = "extra-traits")]
+            impl PartialEq for $name {
+                fn eq(&self, _other: &$name) -> bool {
+                    true
+                }
+            }
+
+            #[cfg(feature = "extra-traits")]
+            impl Hash for $name {
+                fn hash<H: Hasher>(&self, _state: &mut H) {}
+            }
+
+            impl $name {
+                #[cfg(feature = "printing")]
+                pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
+                where
+                    F: FnOnce(&mut TokenStream),
+                {
+                    printing::delim($token, &self.span, tokens, f);
+                }
+            }
+
+            #[cfg(feature = "parsing")]
+            impl private::Sealed for $name {}
+        )*
+    };
+}
+
+define_punctuation_structs! {
+    "_" pub struct Underscore/1 /// `_`
 }
 
 #[cfg(feature = "printing")]
-impl ::quote::ToTokens for Underscore {
-    fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
-        use quote::TokenStreamExt;
-        tokens.append(::proc_macro2::Ident::new("_", self.0[0]));
+impl ToTokens for Underscore {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.append(Ident::new("_", self.spans[0]));
     }
 }
 
 #[cfg(feature = "parsing")]
-impl ::Synom for Underscore {
-    fn parse(input: ::buffer::Cursor) -> ::synom::PResult<Underscore> {
-        match input.ident() {
-            Some((ident, rest)) => {
+impl Parse for Underscore {
+    fn parse(input: ParseStream) -> Result<Self> {
+        input.step(|cursor| {
+            if let Some((ident, rest)) = cursor.ident() {
                 if ident == "_" {
-                    Ok((Underscore([ident.span()]), rest))
-                } else {
-                    ::parse_error()
+                    return Ok((Underscore(ident.span()), rest));
                 }
             }
-            None => parsing::punct("_", input, Underscore),
-        }
-    }
-
-    fn description() -> Option<&'static str> {
-        Some("`_`")
-    }
-}
-
-token_punct_def! {
-    /// `'`
-    pub struct Apostrophe/1
-}
-
-// Implement Clone anyway because it is required for cloning Lifetime.
-#[cfg(not(feature = "clone-impls"))]
-impl Clone for Apostrophe {
-    fn clone(&self) -> Self {
-        Apostrophe(self.0)
-    }
-}
-
-#[cfg(feature = "printing")]
-impl ::quote::ToTokens for Apostrophe {
-    fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
-        use quote::TokenStreamExt;
-        let mut token = ::proc_macro2::Punct::new('\'', ::proc_macro2::Spacing::Joint);
-        token.set_span(self.0[0]);
-        tokens.append(token);
+            if let Some((punct, rest)) = cursor.punct() {
+                if punct.as_char() == '_' {
+                    return Ok((Underscore(punct.span()), rest));
+                }
+            }
+            Err(cursor.error("expected `_`"))
+        })
     }
 }
 
 #[cfg(feature = "parsing")]
-impl ::Synom for Apostrophe {
-    fn parse(input: ::buffer::Cursor) -> ::synom::PResult<Apostrophe> {
-        match input.punct() {
-            Some((op, rest)) => {
-                if op.as_char() == '\'' && op.spacing() == ::proc_macro2::Spacing::Joint {
-                    Ok((Apostrophe([op.span()]), rest))
-                } else {
-                    ::parse_error()
-                }
-            }
-            None => ::parse_error(),
-        }
+impl Token for Paren {
+    fn peek(cursor: Cursor) -> bool {
+        lookahead::is_delimiter(cursor, Delimiter::Parenthesis)
     }
 
-    fn description() -> Option<&'static str> {
-        Some("`'`")
+    fn display() -> &'static str {
+        "parentheses"
     }
 }
 
-tokens! {
-    punct: {
-        "+"        pub struct Add/1        /// `+`
-        "+="       pub struct AddEq/2      /// `+=`
-        "&"        pub struct And/1        /// `&`
-        "&&"       pub struct AndAnd/2     /// `&&`
-        "&="       pub struct AndEq/2      /// `&=`
-        "@"        pub struct At/1         /// `@`
-        "!"        pub struct Bang/1       /// `!`
-        "^"        pub struct Caret/1      /// `^`
-        "^="       pub struct CaretEq/2    /// `^=`
-        ":"        pub struct Colon/1      /// `:`
-        "::"       pub struct Colon2/2     /// `::`
-        ","        pub struct Comma/1      /// `,`
-        "/"        pub struct Div/1        /// `/`
-        "/="       pub struct DivEq/2      /// `/=`
-        "$"        pub struct Dollar/1     /// `$`
-        "."        pub struct Dot/1        /// `.`
-        ".."       pub struct Dot2/2       /// `..`
-        "..."      pub struct Dot3/3       /// `...`
-        "..="      pub struct DotDotEq/3   /// `..=`
-        "="        pub struct Eq/1         /// `=`
-        "=="       pub struct EqEq/2       /// `==`
-        ">="       pub struct Ge/2         /// `>=`
-        ">"        pub struct Gt/1         /// `>`
-        "<="       pub struct Le/2         /// `<=`
-        "<"        pub struct Lt/1         /// `<`
-        "*="       pub struct MulEq/2      /// `*=`
-        "!="       pub struct Ne/2         /// `!=`
-        "|"        pub struct Or/1         /// `|`
-        "|="       pub struct OrEq/2       /// `|=`
-        "||"       pub struct OrOr/2       /// `||`
-        "#"        pub struct Pound/1      /// `#`
-        "?"        pub struct Question/1   /// `?`
-        "->"       pub struct RArrow/2     /// `->`
-        "<-"       pub struct LArrow/2     /// `<-`
-        "%"        pub struct Rem/1        /// `%`
-        "%="       pub struct RemEq/2      /// `%=`
-        "=>"       pub struct FatArrow/2   /// `=>`
-        ";"        pub struct Semi/1       /// `;`
-        "<<"       pub struct Shl/2        /// `<<`
-        "<<="      pub struct ShlEq/3      /// `<<=`
-        ">>"       pub struct Shr/2        /// `>>`
-        ">>="      pub struct ShrEq/3      /// `>>=`
-        "*"        pub struct Star/1       /// `*`
-        "-"        pub struct Sub/1        /// `-`
-        "-="       pub struct SubEq/2      /// `-=`
+#[cfg(feature = "parsing")]
+impl Token for Brace {
+    fn peek(cursor: Cursor) -> bool {
+        lookahead::is_delimiter(cursor, Delimiter::Brace)
     }
-    delimiter: {
-        "{"        pub struct Brace        /// `{...}`
-        "["        pub struct Bracket      /// `[...]`
-        "("        pub struct Paren        /// `(...)`
-        " "        pub struct Group        /// None-delimited group
+
+    fn display() -> &'static str {
+        "curly braces"
     }
-    keyword: {
-        "as"       pub struct As           /// `as`
-        "async"    pub struct Async        /// `async`
-        "auto"     pub struct Auto         /// `auto`
-        "box"      pub struct Box          /// `box`
-        "break"    pub struct Break        /// `break`
-        "Self"     pub struct CapSelf      /// `Self`
-        "catch"    pub struct Catch        /// `catch`
-        "const"    pub struct Const        /// `const`
-        "continue" pub struct Continue     /// `continue`
-        "crate"    pub struct Crate        /// `crate`
-        "default"  pub struct Default      /// `default`
-        "do"       pub struct Do           /// `do`
-        "dyn"      pub struct Dyn          /// `dyn`
-        "else"     pub struct Else         /// `else`
-        "enum"     pub struct Enum         /// `enum`
-        "extern"   pub struct Extern       /// `extern`
-        "fn"       pub struct Fn           /// `fn`
-        "for"      pub struct For          /// `for`
-        "if"       pub struct If           /// `if`
-        "impl"     pub struct Impl         /// `impl`
-        "in"       pub struct In           /// `in`
-        "let"      pub struct Let          /// `let`
-        "loop"     pub struct Loop         /// `loop`
-        "macro"    pub struct Macro        /// `macro`
-        "match"    pub struct Match        /// `match`
-        "mod"      pub struct Mod          /// `mod`
-        "move"     pub struct Move         /// `move`
-        "mut"      pub struct Mut          /// `mut`
-        "pub"      pub struct Pub          /// `pub`
-        "ref"      pub struct Ref          /// `ref`
-        "return"   pub struct Return       /// `return`
-        "self"     pub struct Self_        /// `self`
-        "static"   pub struct Static       /// `static`
-        "struct"   pub struct Struct       /// `struct`
-        "super"    pub struct Super        /// `super`
-        "trait"    pub struct Trait        /// `trait`
-        "try"      pub struct Try          /// `try`
-        "type"     pub struct Type         /// `type`
-        "union"    pub struct Union        /// `union`
-        "unsafe"   pub struct Unsafe       /// `unsafe`
-        "use"      pub struct Use          /// `use`
-        "where"    pub struct Where        /// `where`
-        "while"    pub struct While        /// `while`
-        "yield"    pub struct Yield        /// `yield`
+}
+
+#[cfg(feature = "parsing")]
+impl Token for Bracket {
+    fn peek(cursor: Cursor) -> bool {
+        lookahead::is_delimiter(cursor, Delimiter::Bracket)
     }
+
+    fn display() -> &'static str {
+        "square brackets"
+    }
+}
+
+#[cfg(feature = "parsing")]
+impl Token for Group {
+    fn peek(cursor: Cursor) -> bool {
+        lookahead::is_delimiter(cursor, Delimiter::None)
+    }
+
+    fn display() -> &'static str {
+        "invisible group"
+    }
+}
+
+define_keywords! {
+    "as"          pub struct As           /// `as`
+    "async"       pub struct Async        /// `async`
+    "auto"        pub struct Auto         /// `auto`
+    "box"         pub struct Box          /// `box`
+    "break"       pub struct Break        /// `break`
+    "Self"        pub struct CapSelf      /// `Self`
+    "const"       pub struct Const        /// `const`
+    "continue"    pub struct Continue     /// `continue`
+    "crate"       pub struct Crate        /// `crate`
+    "default"     pub struct Default      /// `default`
+    "dyn"         pub struct Dyn          /// `dyn`
+    "else"        pub struct Else         /// `else`
+    "enum"        pub struct Enum         /// `enum`
+    "existential" pub struct Existential  /// `existential`
+    "extern"      pub struct Extern       /// `extern`
+    "fn"          pub struct Fn           /// `fn`
+    "for"         pub struct For          /// `for`
+    "if"          pub struct If           /// `if`
+    "impl"        pub struct Impl         /// `impl`
+    "in"          pub struct In           /// `in`
+    "let"         pub struct Let          /// `let`
+    "loop"        pub struct Loop         /// `loop`
+    "macro"       pub struct Macro        /// `macro`
+    "match"       pub struct Match        /// `match`
+    "mod"         pub struct Mod          /// `mod`
+    "move"        pub struct Move         /// `move`
+    "mut"         pub struct Mut          /// `mut`
+    "pub"         pub struct Pub          /// `pub`
+    "ref"         pub struct Ref          /// `ref`
+    "return"      pub struct Return       /// `return`
+    "self"        pub struct Self_        /// `self`
+    "static"      pub struct Static       /// `static`
+    "struct"      pub struct Struct       /// `struct`
+    "super"       pub struct Super        /// `super`
+    "trait"       pub struct Trait        /// `trait`
+    "try"         pub struct Try          /// `try`
+    "type"        pub struct Type         /// `type`
+    "union"       pub struct Union        /// `union`
+    "unsafe"      pub struct Unsafe       /// `unsafe`
+    "use"         pub struct Use          /// `use`
+    "where"       pub struct Where        /// `where`
+    "while"       pub struct While        /// `while`
+    "yield"       pub struct Yield        /// `yield`
+}
+
+define_punctuation! {
+    "+"           pub struct Add/1        /// `+`
+    "+="          pub struct AddEq/2      /// `+=`
+    "&"           pub struct And/1        /// `&`
+    "&&"          pub struct AndAnd/2     /// `&&`
+    "&="          pub struct AndEq/2      /// `&=`
+    "@"           pub struct At/1         /// `@`
+    "!"           pub struct Bang/1       /// `!`
+    "^"           pub struct Caret/1      /// `^`
+    "^="          pub struct CaretEq/2    /// `^=`
+    ":"           pub struct Colon/1      /// `:`
+    "::"          pub struct Colon2/2     /// `::`
+    ","           pub struct Comma/1      /// `,`
+    "/"           pub struct Div/1        /// `/`
+    "/="          pub struct DivEq/2      /// `/=`
+    "$"           pub struct Dollar/1     /// `$`
+    "."           pub struct Dot/1        /// `.`
+    ".."          pub struct Dot2/2       /// `..`
+    "..."         pub struct Dot3/3       /// `...`
+    "..="         pub struct DotDotEq/3   /// `..=`
+    "="           pub struct Eq/1         /// `=`
+    "=="          pub struct EqEq/2       /// `==`
+    ">="          pub struct Ge/2         /// `>=`
+    ">"           pub struct Gt/1         /// `>`
+    "<="          pub struct Le/2         /// `<=`
+    "<"           pub struct Lt/1         /// `<`
+    "*="          pub struct MulEq/2      /// `*=`
+    "!="          pub struct Ne/2         /// `!=`
+    "|"           pub struct Or/1         /// `|`
+    "|="          pub struct OrEq/2       /// `|=`
+    "||"          pub struct OrOr/2       /// `||`
+    "#"           pub struct Pound/1      /// `#`
+    "?"           pub struct Question/1   /// `?`
+    "->"          pub struct RArrow/2     /// `->`
+    "<-"          pub struct LArrow/2     /// `<-`
+    "%"           pub struct Rem/1        /// `%`
+    "%="          pub struct RemEq/2      /// `%=`
+    "=>"          pub struct FatArrow/2   /// `=>`
+    ";"           pub struct Semi/1       /// `;`
+    "<<"          pub struct Shl/2        /// `<<`
+    "<<="         pub struct ShlEq/3      /// `<<=`
+    ">>"          pub struct Shr/2        /// `>>`
+    ">>="         pub struct ShrEq/3      /// `>>=`
+    "*"           pub struct Star/1       /// `*`
+    "-"           pub struct Sub/1        /// `-`
+    "-="          pub struct SubEq/2      /// `-=`
+}
+
+define_delimiters! {
+    "{"           pub struct Brace        /// `{...}`
+    "["           pub struct Bracket      /// `[...]`
+    "("           pub struct Paren        /// `(...)`
+    " "           pub struct Group        /// None-delimited group
 }
 
 /// A type-macro that expands to the name of the Rust type representation of a
@@ -522,217 +594,101 @@
 #[macro_export]
 #[cfg_attr(rustfmt, rustfmt_skip)]
 macro_rules! Token {
-    (+)        => { $crate::token::Add };
-    (+=)       => { $crate::token::AddEq };
-    (&)        => { $crate::token::And };
-    (&&)       => { $crate::token::AndAnd };
-    (&=)       => { $crate::token::AndEq };
-    (@)        => { $crate::token::At };
-    (!)        => { $crate::token::Bang };
-    (^)        => { $crate::token::Caret };
-    (^=)       => { $crate::token::CaretEq };
-    (:)        => { $crate::token::Colon };
-    (::)       => { $crate::token::Colon2 };
-    (,)        => { $crate::token::Comma };
-    (/)        => { $crate::token::Div };
-    (/=)       => { $crate::token::DivEq };
-    (.)        => { $crate::token::Dot };
-    (..)       => { $crate::token::Dot2 };
-    (...)      => { $crate::token::Dot3 };
-    (..=)      => { $crate::token::DotDotEq };
-    (=)        => { $crate::token::Eq };
-    (==)       => { $crate::token::EqEq };
-    (>=)       => { $crate::token::Ge };
-    (>)        => { $crate::token::Gt };
-    (<=)       => { $crate::token::Le };
-    (<)        => { $crate::token::Lt };
-    (*=)       => { $crate::token::MulEq };
-    (!=)       => { $crate::token::Ne };
-    (|)        => { $crate::token::Or };
-    (|=)       => { $crate::token::OrEq };
-    (||)       => { $crate::token::OrOr };
-    (#)        => { $crate::token::Pound };
-    (?)        => { $crate::token::Question };
-    (->)       => { $crate::token::RArrow };
-    (<-)       => { $crate::token::LArrow };
-    (%)        => { $crate::token::Rem };
-    (%=)       => { $crate::token::RemEq };
-    (=>)       => { $crate::token::FatArrow };
-    (;)        => { $crate::token::Semi };
-    (<<)       => { $crate::token::Shl };
-    (<<=)      => { $crate::token::ShlEq };
-    (>>)       => { $crate::token::Shr };
-    (>>=)      => { $crate::token::ShrEq };
-    (*)        => { $crate::token::Star };
-    (-)        => { $crate::token::Sub };
-    (-=)       => { $crate::token::SubEq };
-    (_)        => { $crate::token::Underscore };
-    (as)       => { $crate::token::As };
-    (async)    => { $crate::token::Async };
-    (auto)     => { $crate::token::Auto };
-    (box)      => { $crate::token::Box };
-    (break)    => { $crate::token::Break };
-    (Self)     => { $crate::token::CapSelf };
-    (catch)    => { $crate::token::Catch };
-    (const)    => { $crate::token::Const };
-    (continue) => { $crate::token::Continue };
-    (crate)    => { $crate::token::Crate };
-    (default)  => { $crate::token::Default };
-    (do)       => { $crate::token::Do };
-    (dyn)      => { $crate::token::Dyn };
-    (else)     => { $crate::token::Else };
-    (enum)     => { $crate::token::Enum };
-    (extern)   => { $crate::token::Extern };
-    (fn)       => { $crate::token::Fn };
-    (for)      => { $crate::token::For };
-    (if)       => { $crate::token::If };
-    (impl)     => { $crate::token::Impl };
-    (in)       => { $crate::token::In };
-    (let)      => { $crate::token::Let };
-    (loop)     => { $crate::token::Loop };
-    (macro)    => { $crate::token::Macro };
-    (match)    => { $crate::token::Match };
-    (mod)      => { $crate::token::Mod };
-    (move)     => { $crate::token::Move };
-    (mut)      => { $crate::token::Mut };
-    (pub)      => { $crate::token::Pub };
-    (ref)      => { $crate::token::Ref };
-    (return)   => { $crate::token::Return };
-    (self)     => { $crate::token::Self_ };
-    (static)   => { $crate::token::Static };
-    (struct)   => { $crate::token::Struct };
-    (super)    => { $crate::token::Super };
-    (trait)    => { $crate::token::Trait };
-    (try)      => { $crate::token::Try };
-    (type)     => { $crate::token::Type };
-    (union)    => { $crate::token::Union };
-    (unsafe)   => { $crate::token::Unsafe };
-    (use)      => { $crate::token::Use };
-    (where)    => { $crate::token::Where };
-    (while)    => { $crate::token::While };
-    (yield)    => { $crate::token::Yield };
-}
-
-/// Parse a single Rust punctuation token.
-///
-/// See the [token module] documentation for details and examples.
-///
-/// [token module]: token/index.html
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[cfg(feature = "parsing")]
-#[macro_export]
-#[cfg_attr(rustfmt, rustfmt_skip)]
-macro_rules! punct {
-    ($i:expr, +)   => { call!($i, <$crate::token::Add as $crate::synom::Synom>::parse) };
-    ($i:expr, +=)  => { call!($i, <$crate::token::AddEq as $crate::synom::Synom>::parse) };
-    ($i:expr, &)   => { call!($i, <$crate::token::And as $crate::synom::Synom>::parse) };
-    ($i:expr, &&)  => { call!($i, <$crate::token::AndAnd as $crate::synom::Synom>::parse) };
-    ($i:expr, &=)  => { call!($i, <$crate::token::AndEq as $crate::synom::Synom>::parse) };
-    ($i:expr, @)   => { call!($i, <$crate::token::At as $crate::synom::Synom>::parse) };
-    ($i:expr, !)   => { call!($i, <$crate::token::Bang as $crate::synom::Synom>::parse) };
-    ($i:expr, ^)   => { call!($i, <$crate::token::Caret as $crate::synom::Synom>::parse) };
-    ($i:expr, ^=)  => { call!($i, <$crate::token::CaretEq as $crate::synom::Synom>::parse) };
-    ($i:expr, :)   => { call!($i, <$crate::token::Colon as $crate::synom::Synom>::parse) };
-    ($i:expr, ::)  => { call!($i, <$crate::token::Colon2 as $crate::synom::Synom>::parse) };
-    ($i:expr, ,)   => { call!($i, <$crate::token::Comma as $crate::synom::Synom>::parse) };
-    ($i:expr, /)   => { call!($i, <$crate::token::Div as $crate::synom::Synom>::parse) };
-    ($i:expr, /=)  => { call!($i, <$crate::token::DivEq as $crate::synom::Synom>::parse) };
-    ($i:expr, .)   => { call!($i, <$crate::token::Dot as $crate::synom::Synom>::parse) };
-    ($i:expr, ..)  => { call!($i, <$crate::token::Dot2 as $crate::synom::Synom>::parse) };
-    ($i:expr, ...) => { call!($i, <$crate::token::Dot3 as $crate::synom::Synom>::parse) };
-    ($i:expr, ..=) => { call!($i, <$crate::token::DotDotEq as $crate::synom::Synom>::parse) };
-    ($i:expr, =)   => { call!($i, <$crate::token::Eq as $crate::synom::Synom>::parse) };
-    ($i:expr, ==)  => { call!($i, <$crate::token::EqEq as $crate::synom::Synom>::parse) };
-    ($i:expr, >=)  => { call!($i, <$crate::token::Ge as $crate::synom::Synom>::parse) };
-    ($i:expr, >)   => { call!($i, <$crate::token::Gt as $crate::synom::Synom>::parse) };
-    ($i:expr, <=)  => { call!($i, <$crate::token::Le as $crate::synom::Synom>::parse) };
-    ($i:expr, <)   => { call!($i, <$crate::token::Lt as $crate::synom::Synom>::parse) };
-    ($i:expr, *=)  => { call!($i, <$crate::token::MulEq as $crate::synom::Synom>::parse) };
-    ($i:expr, !=)  => { call!($i, <$crate::token::Ne as $crate::synom::Synom>::parse) };
-    ($i:expr, |)   => { call!($i, <$crate::token::Or as $crate::synom::Synom>::parse) };
-    ($i:expr, |=)  => { call!($i, <$crate::token::OrEq as $crate::synom::Synom>::parse) };
-    ($i:expr, ||)  => { call!($i, <$crate::token::OrOr as $crate::synom::Synom>::parse) };
-    ($i:expr, #)   => { call!($i, <$crate::token::Pound as $crate::synom::Synom>::parse) };
-    ($i:expr, ?)   => { call!($i, <$crate::token::Question as $crate::synom::Synom>::parse) };
-    ($i:expr, ->)  => { call!($i, <$crate::token::RArrow as $crate::synom::Synom>::parse) };
-    ($i:expr, <-)  => { call!($i, <$crate::token::LArrow as $crate::synom::Synom>::parse) };
-    ($i:expr, %)   => { call!($i, <$crate::token::Rem as $crate::synom::Synom>::parse) };
-    ($i:expr, %=)  => { call!($i, <$crate::token::RemEq as $crate::synom::Synom>::parse) };
-    ($i:expr, =>)  => { call!($i, <$crate::token::FatArrow as $crate::synom::Synom>::parse) };
-    ($i:expr, ;)   => { call!($i, <$crate::token::Semi as $crate::synom::Synom>::parse) };
-    ($i:expr, <<)  => { call!($i, <$crate::token::Shl as $crate::synom::Synom>::parse) };
-    ($i:expr, <<=) => { call!($i, <$crate::token::ShlEq as $crate::synom::Synom>::parse) };
-    ($i:expr, >>)  => { call!($i, <$crate::token::Shr as $crate::synom::Synom>::parse) };
-    ($i:expr, >>=) => { call!($i, <$crate::token::ShrEq as $crate::synom::Synom>::parse) };
-    ($i:expr, *)   => { call!($i, <$crate::token::Star as $crate::synom::Synom>::parse) };
-    ($i:expr, -)   => { call!($i, <$crate::token::Sub as $crate::synom::Synom>::parse) };
-    ($i:expr, -=)  => { call!($i, <$crate::token::SubEq as $crate::synom::Synom>::parse) };
-    ($i:expr, _)   => { call!($i, <$crate::token::Underscore as $crate::synom::Synom>::parse) };
-}
-
-/// Parse a single Rust keyword token.
-///
-/// See the [token module] documentation for details and examples.
-///
-/// [token module]: token/index.html
-///
-/// *This macro is available if Syn is built with the `"parsing"` feature.*
-#[cfg(feature = "parsing")]
-#[macro_export]
-#[cfg_attr(rustfmt, rustfmt_skip)]
-macro_rules! keyword {
-    ($i:expr, as)       => { call!($i, <$crate::token::As as $crate::synom::Synom>::parse) };
-    ($i:expr, async)    => { call!($i, <$crate::token::Async as $crate::synom::Synom>::parse) };
-    ($i:expr, auto)     => { call!($i, <$crate::token::Auto as $crate::synom::Synom>::parse) };
-    ($i:expr, box)      => { call!($i, <$crate::token::Box as $crate::synom::Synom>::parse) };
-    ($i:expr, break)    => { call!($i, <$crate::token::Break as $crate::synom::Synom>::parse) };
-    ($i:expr, Self)     => { call!($i, <$crate::token::CapSelf as $crate::synom::Synom>::parse) };
-    ($i:expr, catch)    => { call!($i, <$crate::token::Catch as $crate::synom::Synom>::parse) };
-    ($i:expr, const)    => { call!($i, <$crate::token::Const as $crate::synom::Synom>::parse) };
-    ($i:expr, continue) => { call!($i, <$crate::token::Continue as $crate::synom::Synom>::parse) };
-    ($i:expr, crate)    => { call!($i, <$crate::token::Crate as $crate::synom::Synom>::parse) };
-    ($i:expr, default)  => { call!($i, <$crate::token::Default as $crate::synom::Synom>::parse) };
-    ($i:expr, do)       => { call!($i, <$crate::token::Do as $crate::synom::Synom>::parse) };
-    ($i:expr, dyn)      => { call!($i, <$crate::token::Dyn as $crate::synom::Synom>::parse) };
-    ($i:expr, else)     => { call!($i, <$crate::token::Else as $crate::synom::Synom>::parse) };
-    ($i:expr, enum)     => { call!($i, <$crate::token::Enum as $crate::synom::Synom>::parse) };
-    ($i:expr, extern)   => { call!($i, <$crate::token::Extern as $crate::synom::Synom>::parse) };
-    ($i:expr, fn)       => { call!($i, <$crate::token::Fn as $crate::synom::Synom>::parse) };
-    ($i:expr, for)      => { call!($i, <$crate::token::For as $crate::synom::Synom>::parse) };
-    ($i:expr, if)       => { call!($i, <$crate::token::If as $crate::synom::Synom>::parse) };
-    ($i:expr, impl)     => { call!($i, <$crate::token::Impl as $crate::synom::Synom>::parse) };
-    ($i:expr, in)       => { call!($i, <$crate::token::In as $crate::synom::Synom>::parse) };
-    ($i:expr, let)      => { call!($i, <$crate::token::Let as $crate::synom::Synom>::parse) };
-    ($i:expr, loop)     => { call!($i, <$crate::token::Loop as $crate::synom::Synom>::parse) };
-    ($i:expr, macro)    => { call!($i, <$crate::token::Macro as $crate::synom::Synom>::parse) };
-    ($i:expr, match)    => { call!($i, <$crate::token::Match as $crate::synom::Synom>::parse) };
-    ($i:expr, mod)      => { call!($i, <$crate::token::Mod as $crate::synom::Synom>::parse) };
-    ($i:expr, move)     => { call!($i, <$crate::token::Move as $crate::synom::Synom>::parse) };
-    ($i:expr, mut)      => { call!($i, <$crate::token::Mut as $crate::synom::Synom>::parse) };
-    ($i:expr, pub)      => { call!($i, <$crate::token::Pub as $crate::synom::Synom>::parse) };
-    ($i:expr, ref)      => { call!($i, <$crate::token::Ref as $crate::synom::Synom>::parse) };
-    ($i:expr, return)   => { call!($i, <$crate::token::Return as $crate::synom::Synom>::parse) };
-    ($i:expr, self)     => { call!($i, <$crate::token::Self_ as $crate::synom::Synom>::parse) };
-    ($i:expr, static)   => { call!($i, <$crate::token::Static as $crate::synom::Synom>::parse) };
-    ($i:expr, struct)   => { call!($i, <$crate::token::Struct as $crate::synom::Synom>::parse) };
-    ($i:expr, super)    => { call!($i, <$crate::token::Super as $crate::synom::Synom>::parse) };
-    ($i:expr, trait)    => { call!($i, <$crate::token::Trait as $crate::synom::Synom>::parse) };
-    ($i:expr, try)      => { call!($i, <$crate::token::Try as $crate::synom::Synom>::parse) };
-    ($i:expr, type)     => { call!($i, <$crate::token::Type as $crate::synom::Synom>::parse) };
-    ($i:expr, union)    => { call!($i, <$crate::token::Union as $crate::synom::Synom>::parse) };
-    ($i:expr, unsafe)   => { call!($i, <$crate::token::Unsafe as $crate::synom::Synom>::parse) };
-    ($i:expr, use)      => { call!($i, <$crate::token::Use as $crate::synom::Synom>::parse) };
-    ($i:expr, where)    => { call!($i, <$crate::token::Where as $crate::synom::Synom>::parse) };
-    ($i:expr, while)    => { call!($i, <$crate::token::While as $crate::synom::Synom>::parse) };
-    ($i:expr, yield)    => { call!($i, <$crate::token::Yield as $crate::synom::Synom>::parse) };
+    (as)          => { $crate::token::As };
+    (async)       => { $crate::token::Async };
+    (auto)        => { $crate::token::Auto };
+    (box)         => { $crate::token::Box };
+    (break)       => { $crate::token::Break };
+    (Self)        => { $crate::token::CapSelf };
+    (const)       => { $crate::token::Const };
+    (continue)    => { $crate::token::Continue };
+    (crate)       => { $crate::token::Crate };
+    (default)     => { $crate::token::Default };
+    (dyn)         => { $crate::token::Dyn };
+    (else)        => { $crate::token::Else };
+    (enum)        => { $crate::token::Enum };
+    (existential) => { $crate::token::Existential };
+    (extern)      => { $crate::token::Extern };
+    (fn)          => { $crate::token::Fn };
+    (for)         => { $crate::token::For };
+    (if)          => { $crate::token::If };
+    (impl)        => { $crate::token::Impl };
+    (in)          => { $crate::token::In };
+    (let)         => { $crate::token::Let };
+    (loop)        => { $crate::token::Loop };
+    (macro)       => { $crate::token::Macro };
+    (match)       => { $crate::token::Match };
+    (mod)         => { $crate::token::Mod };
+    (move)        => { $crate::token::Move };
+    (mut)         => { $crate::token::Mut };
+    (pub)         => { $crate::token::Pub };
+    (ref)         => { $crate::token::Ref };
+    (return)      => { $crate::token::Return };
+    (self)        => { $crate::token::Self_ };
+    (static)      => { $crate::token::Static };
+    (struct)      => { $crate::token::Struct };
+    (super)       => { $crate::token::Super };
+    (trait)       => { $crate::token::Trait };
+    (try)         => { $crate::token::Try };
+    (type)        => { $crate::token::Type };
+    (union)       => { $crate::token::Union };
+    (unsafe)      => { $crate::token::Unsafe };
+    (use)         => { $crate::token::Use };
+    (where)       => { $crate::token::Where };
+    (while)       => { $crate::token::While };
+    (yield)       => { $crate::token::Yield };
+    (+)           => { $crate::token::Add };
+    (+=)          => { $crate::token::AddEq };
+    (&)           => { $crate::token::And };
+    (&&)          => { $crate::token::AndAnd };
+    (&=)          => { $crate::token::AndEq };
+    (@)           => { $crate::token::At };
+    (!)           => { $crate::token::Bang };
+    (^)           => { $crate::token::Caret };
+    (^=)          => { $crate::token::CaretEq };
+    (:)           => { $crate::token::Colon };
+    (::)          => { $crate::token::Colon2 };
+    (,)           => { $crate::token::Comma };
+    (/)           => { $crate::token::Div };
+    (/=)          => { $crate::token::DivEq };
+    (.)           => { $crate::token::Dot };
+    (..)          => { $crate::token::Dot2 };
+    (...)         => { $crate::token::Dot3 };
+    (..=)         => { $crate::token::DotDotEq };
+    (=)           => { $crate::token::Eq };
+    (==)          => { $crate::token::EqEq };
+    (>=)          => { $crate::token::Ge };
+    (>)           => { $crate::token::Gt };
+    (<=)          => { $crate::token::Le };
+    (<)           => { $crate::token::Lt };
+    (*=)          => { $crate::token::MulEq };
+    (!=)          => { $crate::token::Ne };
+    (|)           => { $crate::token::Or };
+    (|=)          => { $crate::token::OrEq };
+    (||)          => { $crate::token::OrOr };
+    (#)           => { $crate::token::Pound };
+    (?)           => { $crate::token::Question };
+    (->)          => { $crate::token::RArrow };
+    (<-)          => { $crate::token::LArrow };
+    (%)           => { $crate::token::Rem };
+    (%=)          => { $crate::token::RemEq };
+    (=>)          => { $crate::token::FatArrow };
+    (;)           => { $crate::token::Semi };
+    (<<)          => { $crate::token::Shl };
+    (<<=)         => { $crate::token::ShlEq };
+    (>>)          => { $crate::token::Shr };
+    (>>=)         => { $crate::token::ShrEq };
+    (*)           => { $crate::token::Star };
+    (-)           => { $crate::token::Sub };
+    (-=)          => { $crate::token::SubEq };
+    (_)           => { $crate::token::Underscore };
 }
 
 macro_rules! ident_from_token {
     ($token:ident) => {
         impl From<Token![$token]> for Ident {
             fn from(token: Token![$token]) -> Ident {
-                Ident::new(stringify!($token), token.0)
+                Ident::new(stringify!($token), token.span)
             }
         }
     };
@@ -746,102 +702,53 @@
 
 #[cfg(feature = "parsing")]
 mod parsing {
-    use proc_macro2::{Delimiter, Spacing, Span};
+    use proc_macro2::{Spacing, Span};
 
-    use buffer::Cursor;
-    use parse_error;
-    use synom::PResult;
+    use error::{Error, Result};
+    use parse::ParseStream;
+    use span::FromSpans;
 
-    pub trait FromSpans: Sized {
-        fn from_spans(spans: &[Span]) -> Self;
+    pub fn keyword(input: ParseStream, token: &str) -> Result<Span> {
+        input.step(|cursor| {
+            if let Some((ident, rest)) = cursor.ident() {
+                if ident == token {
+                    return Ok((ident.span(), rest));
+                }
+            }
+            Err(cursor.error(format!("expected `{}`", token)))
+        })
     }
 
-    impl FromSpans for [Span; 1] {
-        fn from_spans(spans: &[Span]) -> Self {
-            [spans[0]]
-        }
+    pub fn punct<S: FromSpans>(input: ParseStream, token: &str) -> Result<S> {
+        let mut spans = [input.cursor().span(); 3];
+        punct_helper(input, token, &mut spans)?;
+        Ok(S::from_spans(&spans))
     }
 
-    impl FromSpans for [Span; 2] {
-        fn from_spans(spans: &[Span]) -> Self {
-            [spans[0], spans[1]]
-        }
-    }
+    fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span; 3]) -> Result<()> {
+        input.step(|cursor| {
+            let mut cursor = *cursor;
+            assert!(token.len() <= spans.len());
 
-    impl FromSpans for [Span; 3] {
-        fn from_spans(spans: &[Span]) -> Self {
-            [spans[0], spans[1], spans[2]]
-        }
-    }
-
-    pub fn punct<'a, T, R>(s: &str, mut tokens: Cursor<'a>, new: fn(T) -> R) -> PResult<'a, R>
-    where
-        T: FromSpans,
-    {
-        let mut spans = [Span::call_site(); 3];
-        assert!(s.len() <= spans.len());
-        let chars = s.chars();
-
-        for (i, (ch, slot)) in chars.zip(&mut spans).enumerate() {
-            match tokens.punct() {
-                Some((op, rest)) => {
-                    if op.as_char() == ch {
-                        if i != s.len() - 1 {
-                            match op.spacing() {
-                                Spacing::Joint => {}
-                                _ => return parse_error(),
-                            }
+            for (i, ch) in token.chars().enumerate() {
+                match cursor.punct() {
+                    Some((punct, rest)) => {
+                        spans[i] = punct.span();
+                        if punct.as_char() != ch {
+                            break;
+                        } else if i == token.len() - 1 {
+                            return Ok(((), rest));
+                        } else if punct.spacing() != Spacing::Joint {
+                            break;
                         }
-                        *slot = op.span();
-                        tokens = rest;
-                    } else {
-                        return parse_error();
+                        cursor = rest;
                     }
+                    None => break,
                 }
-                _ => return parse_error(),
             }
-        }
-        Ok((new(T::from_spans(&spans)), tokens))
-    }
 
-    pub fn keyword<'a, T>(keyword: &str, tokens: Cursor<'a>, new: fn(Span) -> T) -> PResult<'a, T> {
-        if let Some((ident, rest)) = tokens.ident() {
-            if ident == keyword {
-                return Ok((new(ident.span()), rest));
-            }
-        }
-        parse_error()
-    }
-
-    pub fn delim<'a, F, R, T>(
-        delim: &str,
-        tokens: Cursor<'a>,
-        new: fn(Span) -> T,
-        f: F,
-    ) -> PResult<'a, (T, R)>
-    where
-        F: FnOnce(Cursor) -> PResult<R>,
-    {
-        // NOTE: We should support none-delimited sequences here.
-        let delim = match delim {
-            "(" => Delimiter::Parenthesis,
-            "{" => Delimiter::Brace,
-            "[" => Delimiter::Bracket,
-            " " => Delimiter::None,
-            _ => panic!("unknown delimiter: {}", delim),
-        };
-
-        if let Some((inside, span, rest)) = tokens.group(delim) {
-            match f(inside) {
-                Ok((ret, remaining)) => {
-                    if remaining.eof() {
-                        return Ok(((new(span), ret), rest));
-                    }
-                }
-                Err(err) => return Err(err),
-            }
-        }
-        parse_error()
+            Err(Error::new(spans[0], format!("expected `{}`", token)))
+        })
     }
 }
 
diff --git a/src/tt.rs b/src/tt.rs
index bde82dc..e4f703e 100644
--- a/src/tt.rs
+++ b/src/tt.rs
@@ -6,61 +6,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[cfg(feature = "parsing")]
-use buffer::Cursor;
-#[cfg(feature = "parsing")]
-use synom::PResult;
-#[cfg(feature = "parsing")]
-use token::{Brace, Bracket, Paren};
-#[cfg(feature = "parsing")]
-use {parse_error, MacroDelimiter};
-
-#[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
 
-#[cfg(any(feature = "parsing", feature = "extra-traits"))]
 use proc_macro2::{Delimiter, TokenStream, TokenTree};
 
-#[cfg(feature = "parsing")]
-pub fn delimited(input: Cursor) -> PResult<(MacroDelimiter, TokenStream)> {
-    if let Some((TokenTree::Group(g), rest)) = input.token_tree() {
-        let span = g.span();
-        let delimiter = match g.delimiter() {
-            Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
-            Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
-            Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
-            Delimiter::None => return parse_error(),
-        };
-
-        return Ok(((delimiter, g.stream().clone()), rest));
-    }
-    parse_error()
-}
-
-#[cfg(all(feature = "full", feature = "parsing"))]
-pub fn braced(input: Cursor) -> PResult<(Brace, TokenStream)> {
-    if let Some((TokenTree::Group(g), rest)) = input.token_tree() {
-        if g.delimiter() == Delimiter::Brace {
-            return Ok(((Brace(g.span()), g.stream().clone()), rest));
-        }
-    }
-    parse_error()
-}
-
-#[cfg(all(feature = "full", feature = "parsing"))]
-pub fn parenthesized(input: Cursor) -> PResult<(Paren, TokenStream)> {
-    if let Some((TokenTree::Group(g), rest)) = input.token_tree() {
-        if g.delimiter() == Delimiter::Parenthesis {
-            return Ok(((Paren(g.span()), g.stream().clone()), rest));
-        }
-    }
-    parse_error()
-}
-
-#[cfg(feature = "extra-traits")]
 pub struct TokenTreeHelper<'a>(pub &'a TokenTree);
 
-#[cfg(feature = "extra-traits")]
 impl<'a> PartialEq for TokenTreeHelper<'a> {
     fn eq(&self, other: &Self) -> bool {
         use proc_macro2::Spacing;
@@ -104,7 +55,6 @@
     }
 }
 
-#[cfg(feature = "extra-traits")]
 impl<'a> Hash for TokenTreeHelper<'a> {
     fn hash<H: Hasher>(&self, h: &mut H) {
         use proc_macro2::Spacing;
@@ -138,10 +88,8 @@
     }
 }
 
-#[cfg(feature = "extra-traits")]
 pub struct TokenStreamHelper<'a>(pub &'a TokenStream);
 
-#[cfg(feature = "extra-traits")]
 impl<'a> PartialEq for TokenStreamHelper<'a> {
     fn eq(&self, other: &Self) -> bool {
         let left = self.0.clone().into_iter().collect::<Vec<_>>();
@@ -158,7 +106,6 @@
     }
 }
 
-#[cfg(feature = "extra-traits")]
 impl<'a> Hash for TokenStreamHelper<'a> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let tts = self.0.clone().into_iter().collect::<Vec<_>>();
diff --git a/src/ty.rs b/src/ty.rs
index 1ee46d0..29f2311 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -73,10 +73,10 @@
         /// *This type is available if Syn is built with the `"derive"` or
         /// `"full"` feature.*
         pub BareFn(TypeBareFn {
+            pub lifetimes: Option<BoundLifetimes>,
             pub unsafety: Option<Token![unsafe]>,
             pub abi: Option<Abi>,
             pub fn_token: Token![fn],
-            pub lifetimes: Option<BoundLifetimes>,
             pub paren_token: token::Paren,
             pub inputs: Punctuated<BareFnArg, Token![,]>,
             pub variadic: Option<Token![...]>,
@@ -249,14 +249,13 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
-    use path::parsing::qpath;
-    use synom::Synom;
 
-    impl Synom for Type {
-        named!(parse -> Self, call!(ambig_ty, true));
+    use parse::{Parse, ParseStream, Result};
+    use path;
 
-        fn description() -> Option<&'static str> {
-            Some("type")
+    impl Parse for Type {
+        fn parse(input: ParseStream) -> Result<Self> {
+            ambig_ty(input, true)
         }
     }
 
@@ -266,250 +265,351 @@
         /// contain a `+` character.
         ///
         /// This parser does not allow a `+`, while the default parser does.
-        named!(pub without_plus -> Self, call!(ambig_ty, false));
-    }
-
-    named!(ambig_ty(allow_plus: bool) -> Type, alt!(
-        syn!(TypeGroup) => { Type::Group }
-        |
-        // must be before TypeTuple
-        call!(TypeParen::parse, allow_plus) => { Type::Paren }
-        |
-        // must be before TypePath
-        syn!(TypeMacro) => { Type::Macro }
-        |
-        // must be before TypePath
-        syn!(TypeBareFn) => { Type::BareFn }
-        |
-        // must be before TypeTraitObject
-        call!(TypePath::parse, allow_plus) => { Type::Path }
-        |
-        // Don't try parsing more than one trait bound if we aren't allowing it.
-        // must be before TypeTuple
-        call!(TypeTraitObject::parse, allow_plus) => { Type::TraitObject }
-        |
-        syn!(TypeSlice) => { Type::Slice }
-        |
-        syn!(TypeArray) => { Type::Array }
-        |
-        syn!(TypePtr) => { Type::Ptr }
-        |
-        syn!(TypeReference) => { Type::Reference }
-        |
-        syn!(TypeNever) => { Type::Never }
-        |
-        syn!(TypeTuple) => { Type::Tuple }
-        |
-        syn!(TypeImplTrait) => { Type::ImplTrait }
-        |
-        syn!(TypeInfer) => { Type::Infer }
-    ));
-
-    impl Synom for TypeSlice {
-        named!(parse -> Self, map!(
-            brackets!(syn!(Type)),
-            |(b, ty)| TypeSlice {
-                elem: Box::new(ty),
-                bracket_token: b,
-            }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("slice type")
+        pub fn without_plus(input: ParseStream) -> Result<Self> {
+            ambig_ty(input, false)
         }
     }
 
-    impl Synom for TypeArray {
-        named!(parse -> Self, map!(
-            brackets!(do_parse!(
-                elem: syn!(Type) >>
-                    semi: punct!(;) >>
-                    len: syn!(Expr) >>
-                    (elem, semi, len)
-            )),
-            |(brackets, (elem, semi, len))| {
-                TypeArray {
+    fn ambig_ty(input: ParseStream, allow_plus: bool) -> Result<Type> {
+        if input.peek(token::Group) {
+            return input.parse().map(Type::Group);
+        }
+
+        let mut lifetimes = None::<BoundLifetimes>;
+        let mut lookahead = input.lookahead1();
+        if lookahead.peek(Token![for]) {
+            lifetimes = input.parse()?;
+            lookahead = input.lookahead1();
+            if !lookahead.peek(Ident)
+                && !lookahead.peek(Token![fn])
+                && !lookahead.peek(Token![unsafe])
+                && !lookahead.peek(Token![extern])
+                && !lookahead.peek(Token![super])
+                && !lookahead.peek(Token![self])
+                && !lookahead.peek(Token![Self])
+                && !lookahead.peek(Token![crate])
+            {
+                return Err(lookahead.error());
+            }
+        }
+
+        if lookahead.peek(token::Paren) {
+            let content;
+            let paren_token = parenthesized!(content in input);
+            if content.is_empty() {
+                return Ok(Type::Tuple(TypeTuple {
+                    paren_token: paren_token,
+                    elems: Punctuated::new(),
+                }));
+            }
+            if content.peek(Lifetime) {
+                return Ok(Type::Paren(TypeParen {
+                    paren_token: paren_token,
+                    elem: Box::new(Type::TraitObject(content.parse()?)),
+                }));
+            }
+            let first: Type = content.parse()?;
+            if content.peek(Token![,]) {
+                Ok(Type::Tuple(TypeTuple {
+                    paren_token: paren_token,
+                    elems: {
+                        let mut elems = Punctuated::new();
+                        elems.push_value(first);
+                        elems.push_punct(content.parse()?);
+                        let rest: Punctuated<Type, Token![,]> =
+                            content.parse_terminated(Parse::parse)?;
+                        elems.extend(rest);
+                        elems
+                    },
+                }))
+            } else {
+                Ok(Type::Paren(TypeParen {
+                    paren_token: paren_token,
+                    elem: Box::new(first),
+                }))
+            }
+        } else if lookahead.peek(Token![fn])
+            || lookahead.peek(Token![unsafe])
+            || lookahead.peek(Token![extern]) && !input.peek2(Token![::])
+        {
+            let mut bare_fn: TypeBareFn = input.parse()?;
+            bare_fn.lifetimes = lifetimes;
+            Ok(Type::BareFn(bare_fn))
+        } else if lookahead.peek(Ident)
+            || input.peek(Token![super])
+            || input.peek(Token![self])
+            || input.peek(Token![Self])
+            || input.peek(Token![crate])
+            || input.peek(Token![extern])
+            || lookahead.peek(Token![::])
+            || lookahead.peek(Token![<])
+        {
+            if input.peek(Token![dyn]) {
+                let mut trait_object: TypeTraitObject = input.parse()?;
+                if lifetimes.is_some() {
+                    match *trait_object.bounds.iter_mut().next().unwrap() {
+                        TypeParamBound::Trait(ref mut trait_bound) => {
+                            trait_bound.lifetimes = lifetimes;
+                        }
+                        TypeParamBound::Lifetime(_) => unreachable!(),
+                    }
+                }
+                return Ok(Type::TraitObject(trait_object));
+            }
+
+            let ty: TypePath = input.parse()?;
+            if ty.qself.is_some() {
+                return Ok(Type::Path(ty));
+            }
+
+            if input.peek(Token![!]) && !input.peek(Token![!=]) {
+                let mut contains_arguments = false;
+                for segment in &ty.path.segments {
+                    match segment.arguments {
+                        PathArguments::None => {}
+                        PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
+                            contains_arguments = true;
+                        }
+                    }
+                }
+
+                if !contains_arguments {
+                    let bang_token: Token![!] = input.parse()?;
+                    let (delimiter, tts) = mac::parse_delimiter(input)?;
+                    return Ok(Type::Macro(TypeMacro {
+                        mac: Macro {
+                            path: ty.path,
+                            bang_token: bang_token,
+                            delimiter: delimiter,
+                            tts: tts,
+                        },
+                    }));
+                }
+            }
+
+            if lifetimes.is_some() || allow_plus && input.peek(Token![+]) {
+                let mut bounds = Punctuated::new();
+                bounds.push_value(TypeParamBound::Trait(TraitBound {
+                    paren_token: None,
+                    modifier: TraitBoundModifier::None,
+                    lifetimes: lifetimes,
+                    path: ty.path,
+                }));
+                if allow_plus {
+                    while input.peek(Token![+]) {
+                        bounds.push_punct(input.parse()?);
+                        bounds.push_value(input.parse()?);
+                    }
+                }
+                return Ok(Type::TraitObject(TypeTraitObject {
+                    dyn_token: None,
+                    bounds: bounds,
+                }));
+            }
+
+            Ok(Type::Path(ty))
+        } else if lookahead.peek(token::Bracket) {
+            let content;
+            let bracket_token = bracketed!(content in input);
+            let elem: Type = content.parse()?;
+            if content.peek(Token![;]) {
+                Ok(Type::Array(TypeArray {
+                    bracket_token: bracket_token,
                     elem: Box::new(elem),
-                    len: len,
-                    bracket_token: brackets,
-                    semi_token: semi,
-                }
+                    semi_token: content.parse()?,
+                    len: content.parse()?,
+                }))
+            } else {
+                Ok(Type::Slice(TypeSlice {
+                    bracket_token: bracket_token,
+                    elem: Box::new(elem),
+                }))
             }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("array type")
+        } else if lookahead.peek(Token![*]) {
+            input.parse().map(Type::Ptr)
+        } else if lookahead.peek(Token![&]) {
+            input.parse().map(Type::Reference)
+        } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) {
+            input.parse().map(Type::Never)
+        } else if lookahead.peek(Token![impl ]) {
+            input.parse().map(Type::ImplTrait)
+        } else if lookahead.peek(Token![_]) {
+            input.parse().map(Type::Infer)
+        } else if lookahead.peek(Lifetime) {
+            input.parse().map(Type::TraitObject)
+        } else {
+            Err(lookahead.error())
         }
     }
 
-    impl Synom for TypePtr {
-        named!(parse -> Self, do_parse!(
-            star: punct!(*) >>
-            mutability: alt!(
-                keyword!(const) => { |c| (None, Some(c)) }
-                |
-                keyword!(mut) => { |m| (Some(m), None) }
-            ) >>
-            target: call!(Type::without_plus) >>
-            (TypePtr {
-                const_token: mutability.1,
-                star_token: star,
-                mutability: mutability.0,
-                elem: Box::new(target),
+    impl Parse for TypeSlice {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(TypeSlice {
+                bracket_token: bracketed!(content in input),
+                elem: content.parse()?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("raw pointer type")
         }
     }
 
-    impl Synom for TypeReference {
-        named!(parse -> Self, do_parse!(
-            amp: punct!(&) >>
-            life: option!(syn!(Lifetime)) >>
-            mutability: option!(keyword!(mut)) >>
-            // & binds tighter than +, so we don't allow + here.
-            target: call!(Type::without_plus) >>
-            (TypeReference {
-                lifetime: life,
+    impl Parse for TypeArray {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(TypeArray {
+                bracket_token: bracketed!(content in input),
+                elem: content.parse()?,
+                semi_token: content.parse()?,
+                len: content.parse()?,
+            })
+        }
+    }
+
+    impl Parse for TypePtr {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let star_token: Token![*] = input.parse()?;
+
+            let lookahead = input.lookahead1();
+            let (const_token, mutability) = if lookahead.peek(Token![const]) {
+                (Some(input.parse()?), None)
+            } else if lookahead.peek(Token![mut]) {
+                (None, Some(input.parse()?))
+            } else {
+                return Err(lookahead.error());
+            };
+
+            Ok(TypePtr {
+                star_token: star_token,
+                const_token: const_token,
                 mutability: mutability,
-                elem: Box::new(target),
-                and_token: amp,
+                elem: Box::new(input.call(Type::without_plus)?),
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("reference type")
         }
     }
 
-    impl Synom for TypeBareFn {
-        named!(parse -> Self, do_parse!(
-            lifetimes: option!(syn!(BoundLifetimes)) >>
-            unsafety: option!(keyword!(unsafe)) >>
-            abi: option!(syn!(Abi)) >>
-            fn_: keyword!(fn) >>
-            parens: parens!(do_parse!(
-                inputs: call!(Punctuated::parse_terminated) >>
-                variadic: option!(cond_reduce!(inputs.empty_or_trailing(), punct!(...))) >>
-                (inputs, variadic)
-            )) >>
-            output: call!(ReturnType::without_plus) >>
-            (TypeBareFn {
-                unsafety: unsafety,
-                abi: abi,
-                lifetimes: lifetimes,
-                output: output,
-                variadic: (parens.1).1,
-                fn_token: fn_,
-                paren_token: parens.0,
-                inputs: (parens.1).0,
+    impl Parse for TypeReference {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeReference {
+                and_token: input.parse()?,
+                lifetime: input.parse()?,
+                mutability: input.parse()?,
+                // & binds tighter than +, so we don't allow + here.
+                elem: Box::new(input.call(Type::without_plus)?),
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`fn` type")
         }
     }
 
-    impl Synom for TypeNever {
-        named!(parse -> Self, map!(
-            punct!(!),
-            |b| TypeNever { bang_token: b }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("never type: `!`")
-        }
-    }
-
-    impl Synom for TypeInfer {
-        named!(parse -> Self, map!(
-            punct!(_),
-            |u| TypeInfer { underscore_token: u }
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("inferred type: `_`")
-        }
-    }
-
-    impl Synom for TypeTuple {
-        named!(parse -> Self, do_parse!(
-            data: parens!(Punctuated::parse_terminated) >>
-            (TypeTuple {
-                paren_token: data.0,
-                elems: data.1,
+    impl Parse for TypeBareFn {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let args;
+            let allow_variadic;
+            Ok(TypeBareFn {
+                lifetimes: input.parse()?,
+                unsafety: input.parse()?,
+                abi: input.parse()?,
+                fn_token: input.parse()?,
+                paren_token: parenthesized!(args in input),
+                inputs: {
+                    let mut inputs = Punctuated::new();
+                    while !args.is_empty() && !args.peek(Token![...]) {
+                        inputs.push_value(args.parse()?);
+                        if args.is_empty() {
+                            break;
+                        }
+                        inputs.push_punct(args.parse()?);
+                    }
+                    allow_variadic = inputs.empty_or_trailing();
+                    inputs
+                },
+                variadic: {
+                    if allow_variadic && args.peek(Token![...]) {
+                        Some(args.parse()?)
+                    } else {
+                        None
+                    }
+                },
+                output: input.call(ReturnType::without_plus)?,
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("tuple type")
         }
     }
 
-    impl Synom for TypeMacro {
-        named!(parse -> Self, map!(syn!(Macro), |mac| TypeMacro { mac: mac }));
-
-        fn description() -> Option<&'static str> {
-            Some("macro invocation")
-        }
-    }
-
-    impl Synom for TypePath {
-        named!(parse -> Self, call!(Self::parse, false));
-
-        fn description() -> Option<&'static str> {
-            Some("type path")
-        }
-    }
-
-    impl TypePath {
-        named!(parse(allow_plus: bool) -> Self, do_parse!(
-            qpath: qpath >>
-            parenthesized: option!(cond_reduce!(
-                qpath.1.segments.last().unwrap().value().arguments.is_empty(),
-                syn!(ParenthesizedGenericArguments)
-            )) >>
-            cond!(allow_plus, not!(punct!(+))) >>
-            ({
-                let (qself, mut path) = qpath;
-                if let Some(parenthesized) = parenthesized {
-                    let parenthesized = PathArguments::Parenthesized(parenthesized);
-                    path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
-                }
-                TypePath { qself: qself, path: path }
+    impl Parse for TypeNever {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeNever {
+                bang_token: input.parse()?,
             })
-        ));
+        }
+    }
+
+    impl Parse for TypeInfer {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeInfer {
+                underscore_token: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for TypeTuple {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let content;
+            Ok(TypeTuple {
+                paren_token: parenthesized!(content in input),
+                elems: content.parse_terminated(Type::parse)?,
+            })
+        }
+    }
+
+    impl Parse for TypeMacro {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeMacro {
+                mac: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for TypePath {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let (qself, mut path) = path::parsing::qpath(input, false)?;
+
+            if path.segments.last().unwrap().value().arguments.is_empty()
+                && input.peek(token::Paren)
+            {
+                let args: ParenthesizedGenericArguments = input.parse()?;
+                let parenthesized = PathArguments::Parenthesized(args);
+                path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
+            }
+
+            Ok(TypePath {
+                qself: qself,
+                path: path,
+            })
+        }
     }
 
     impl ReturnType {
-        named!(pub without_plus -> Self, call!(Self::parse, false));
-        named!(parse(allow_plus: bool) -> Self, alt!(
-            do_parse!(
-                arrow: punct!(->) >>
-                ty: call!(ambig_ty, allow_plus) >>
-                (ReturnType::Type(arrow, Box::new(ty)))
-            )
-            |
-            epsilon!() => { |_| ReturnType::Default }
-        ));
-    }
+        pub fn without_plus(input: ParseStream) -> Result<Self> {
+            Self::parse(input, false)
+        }
 
-    impl Synom for ReturnType {
-        named!(parse -> Self, call!(Self::parse, true));
-
-        fn description() -> Option<&'static str> {
-            Some("return type")
+        pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+            if input.peek(Token![->]) {
+                let arrow = input.parse()?;
+                let ty = ambig_ty(input, allow_plus)?;
+                Ok(ReturnType::Type(arrow, Box::new(ty)))
+            } else {
+                Ok(ReturnType::Default)
+            }
         }
     }
 
-    impl Synom for TypeTraitObject {
-        named!(parse -> Self, call!(Self::parse, true));
+    impl Parse for ReturnType {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse(input, true)
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("trait object type")
+    impl Parse for TypeTraitObject {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse(input, true)
         }
     }
 
@@ -523,123 +623,133 @@
     }
 
     impl TypeTraitObject {
-        named!(pub without_plus -> Self, call!(Self::parse, false));
+        pub fn without_plus(input: ParseStream) -> Result<Self> {
+            Self::parse(input, false)
+        }
 
         // Only allow multiple trait references if allow_plus is true.
-        named!(parse(allow_plus: bool) -> Self, do_parse!(
-            dyn_token: option!(keyword!(dyn)) >>
-            bounds: alt!(
-                cond_reduce!(allow_plus, Punctuated::parse_terminated_nonempty)
-                |
-                syn!(TypeParamBound) => {|x| {
+        pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+            Ok(TypeTraitObject {
+                dyn_token: input.parse()?,
+                bounds: {
                     let mut bounds = Punctuated::new();
-                    bounds.push_value(x);
+                    if allow_plus {
+                        loop {
+                            bounds.push_value(input.parse()?);
+                            if !input.peek(Token![+]) {
+                                break;
+                            }
+                            bounds.push_punct(input.parse()?);
+                        }
+                    } else {
+                        bounds.push_value(input.parse()?);
+                    }
+                    // Just lifetimes like `'a + 'b` is not a TraitObject.
+                    if !at_least_one_type(&bounds) {
+                        return Err(input.error("expected at least one type"));
+                    }
                     bounds
-                }}
-            ) >>
-            // Just lifetimes like `'a + 'b` is not a TraitObject.
-            cond_reduce!(at_least_one_type(&bounds)) >>
-            (TypeTraitObject {
-                dyn_token: dyn_token,
-                bounds: bounds,
+                },
             })
-        ));
-    }
-
-    impl Synom for TypeImplTrait {
-        named!(parse -> Self, do_parse!(
-            impl_: keyword!(impl) >>
-            // NOTE: rust-lang/rust#34511 includes discussion about whether or
-            // not + should be allowed in ImplTrait directly without ().
-            elem: call!(Punctuated::parse_terminated_nonempty) >>
-            (TypeImplTrait {
-                impl_token: impl_,
-                bounds: elem,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("`impl Trait` type")
         }
     }
 
-    impl Synom for TypeGroup {
-        named!(parse -> Self, do_parse!(
-            data: grouped!(syn!(Type)) >>
-            (TypeGroup {
-                group_token: data.0,
-                elem: Box::new(data.1),
+    impl Parse for TypeImplTrait {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(TypeImplTrait {
+                impl_token: input.parse()?,
+                // NOTE: rust-lang/rust#34511 includes discussion about whether
+                // or not + should be allowed in ImplTrait directly without ().
+                bounds: {
+                    let mut bounds = Punctuated::new();
+                    loop {
+                        bounds.push_value(input.parse()?);
+                        if !input.peek(Token![+]) {
+                            break;
+                        }
+                        bounds.push_punct(input.parse()?);
+                    }
+                    bounds
+                },
             })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("type surrounded by invisible delimiters")
         }
     }
 
-    impl Synom for TypeParen {
-        named!(parse -> Self, call!(Self::parse, false));
+    impl Parse for TypeGroup {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let group = private::parse_group(input)?;
+            Ok(TypeGroup {
+                group_token: group.token,
+                elem: group.content.parse()?,
+            })
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("parenthesized type")
+    impl Parse for TypeParen {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Self::parse(input, false)
         }
     }
 
     impl TypeParen {
-        named!(parse(allow_plus: bool) -> Self, do_parse!(
-            data: parens!(syn!(Type)) >>
-            cond!(allow_plus, not!(punct!(+))) >>
-            (TypeParen {
-                paren_token: data.0,
-                elem: Box::new(data.1),
+        fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+            let content;
+            Ok(TypeParen {
+                paren_token: parenthesized!(content in input),
+                elem: Box::new(ambig_ty(&content, allow_plus)?),
             })
-        ));
-    }
-
-    impl Synom for BareFnArg {
-        named!(parse -> Self, do_parse!(
-            name: option!(do_parse!(
-                name: syn!(BareFnArgName) >>
-                not!(punct!(::)) >>
-                colon: punct!(:) >>
-                (name, colon)
-            )) >>
-            ty: syn!(Type) >>
-            (BareFnArg {
-                name: name,
-                ty: ty,
-            })
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("function type argument")
         }
     }
 
-    impl Synom for BareFnArgName {
-        named!(parse -> Self, alt!(
-            map!(syn!(Ident), BareFnArgName::Named)
-            |
-            map!(punct!(_), BareFnArgName::Wild)
-        ));
-
-        fn description() -> Option<&'static str> {
-            Some("function argument name")
+    impl Parse for BareFnArg {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(BareFnArg {
+                name: {
+                    if (input.peek(Ident) || input.peek(Token![_]))
+                        && !input.peek2(Token![::])
+                        && input.peek2(Token![:])
+                    {
+                        let name: BareFnArgName = input.parse()?;
+                        let colon: Token![:] = input.parse()?;
+                        Some((name, colon))
+                    } else {
+                        None
+                    }
+                },
+                ty: input.parse()?,
+            })
         }
     }
 
-    impl Synom for Abi {
-        named!(parse -> Self, do_parse!(
-            extern_: keyword!(extern) >>
-            name: option!(syn!(LitStr)) >>
-            (Abi {
-                extern_token: extern_,
-                name: name,
-            })
-        ));
+    impl Parse for BareFnArgName {
+        fn parse(input: ParseStream) -> Result<Self> {
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Ident) {
+                input.parse().map(BareFnArgName::Named)
+            } else if lookahead.peek(Token![_]) {
+                input.parse().map(BareFnArgName::Wild)
+            } else {
+                Err(lookahead.error())
+            }
+        }
+    }
 
-        fn description() -> Option<&'static str> {
-            Some("`extern` ABI qualifier")
+    impl Parse for Abi {
+        fn parse(input: ParseStream) -> Result<Self> {
+            Ok(Abi {
+                extern_token: input.parse()?,
+                name: input.parse()?,
+            })
+        }
+    }
+
+    impl Parse for Option<Abi> {
+        fn parse(input: ParseStream) -> Result<Self> {
+            if input.peek(Token![extern]) {
+                input.parse().map(Some)
+            } else {
+                Ok(None)
+            }
         }
     }
 }
@@ -647,9 +757,12 @@
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
+
     use proc_macro2::TokenStream;
     use quote::ToTokens;
 
+    use print::TokensOrDefault;
+
     impl ToTokens for TypeSlice {
         fn to_tokens(&self, tokens: &mut TokenStream) {
             self.bracket_token.surround(tokens, |tokens| {
@@ -700,8 +813,8 @@
                 self.inputs.to_tokens(tokens);
                 if let Some(ref variadic) = self.variadic {
                     if !self.inputs.empty_or_trailing() {
-                        let span = variadic.0[0];
-                        <Token![,]>::new(span).to_tokens(tokens);
+                        let span = variadic.spans[0];
+                        Token![,](span).to_tokens(tokens);
                     }
                     variadic.to_tokens(tokens);
                 }
@@ -726,7 +839,7 @@
 
     impl ToTokens for TypePath {
         fn to_tokens(&self, tokens: &mut TokenStream) {
-            PathTokens(&self.qself, &self.path).to_tokens(tokens);
+            private::print_path(tokens, &self.qself, &self.path);
         }
     }
 
diff --git a/src/verbatim.rs b/src/verbatim.rs
deleted file mode 100644
index 8ab0603..0000000
--- a/src/verbatim.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::ops::Range;
-
-use buffer::Cursor;
-use proc_macro2::TokenStream;
-use synom::PResult;
-
-pub fn grab_cursor(cursor: Cursor) -> PResult<Cursor> {
-    Ok((cursor, cursor))
-}
-
-pub fn token_range(range: Range<Cursor>) -> TokenStream {
-    let mut tts = Vec::new();
-    let mut cursor = range.start;
-    while cursor != range.end {
-        let (tt, next) = cursor.token_tree().expect("malformed token range");
-        tts.push(tt);
-        cursor = next;
-    }
-    tts.into_iter().collect()
-}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
index e09544b..108019a 100644
--- a/tests/common/mod.rs
+++ b/tests/common/mod.rs
@@ -20,20 +20,6 @@
 pub mod eq;
 pub mod parse;
 
-pub fn check_min_stack() {
-    let min_stack_value = match env::var("RUST_MIN_STACK") {
-        Ok(s) => s,
-        Err(_) => {
-            env::set_var("RUST_MIN_STACK", 16000000.to_string());
-            return;
-        }
-    };
-    let min_stack_value: usize = min_stack_value
-        .parse()
-        .expect("RUST_MIN_STACK env var should be set since some tests require it.");
-    assert!(min_stack_value >= 16_000_000);
-}
-
 /// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it.
 pub fn abort_after() -> usize {
     match env::var("ABORT_AFTER_FAILURE") {
diff --git a/tests/common/parse.rs b/tests/common/parse.rs
index 0f410e6..a0cc40c 100644
--- a/tests/common/parse.rs
+++ b/tests/common/parse.rs
@@ -20,9 +20,6 @@
 
 use std::panic;
 
-use self::syn::buffer::TokenBuffer;
-use self::syn::synom::Synom;
-
 pub fn libsyntax_expr(input: &str) -> Option<P<ast::Expr>> {
     match panic::catch_unwind(|| {
         hygiene::set_default_edition(Edition::Edition2018);
@@ -59,20 +56,3 @@
         }
     }
 }
-
-pub fn syn<T: Synom>(tokens: proc_macro2::TokenStream) -> T {
-    let buf = TokenBuffer::new2(tokens);
-    let result = T::parse(buf.begin());
-    match result {
-        Ok((t, rest)) => {
-            if rest.eof() {
-                t
-            } else if rest == buf.begin() {
-                panic!("failed to parse anything")
-            } else {
-                panic!("failed to parse all tokens")
-            }
-        }
-        Err(err) => panic!("failed to parse: {}", err),
-    }
-}
diff --git a/tests/test_asyncness.rs b/tests/test_asyncness.rs
new file mode 100644
index 0000000..b73537b
--- /dev/null
+++ b/tests/test_asyncness.rs
@@ -0,0 +1,71 @@
+// Copyright 2018 Syn Developers
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg(all(feature = "extra-traits", feature = "full"))]
+
+extern crate proc_macro2;
+extern crate syn;
+
+use proc_macro2::Span;
+use syn::punctuated::Punctuated;
+use syn::{Block, Expr, ExprBlock, ExprClosure, FnDecl, Ident, ItemFn, ReturnType, Visibility};
+
+#[test]
+fn test_async_fn() {
+    let raw = "async fn process() {}";
+
+    let expected = ItemFn {
+        attrs: vec![],
+        vis: Visibility::Inherited,
+        constness: None,
+        unsafety: None,
+        asyncness: Some(Default::default()),
+        abi: None,
+        ident: Ident::new("process", Span::call_site()),
+        decl: Box::new(FnDecl {
+            fn_token: Default::default(),
+            generics: Default::default(),
+            paren_token: Default::default(),
+            inputs: Punctuated::new(),
+            variadic: None,
+            output: ReturnType::Default,
+        }),
+        block: Box::new(Block {
+            brace_token: Default::default(),
+            stmts: vec![],
+        }),
+    };
+
+    assert_eq!(expected, syn::parse_str(raw).unwrap());
+}
+
+#[test]
+fn test_async_closure() {
+    let raw = "async || {}";
+
+    let expected = Expr::Closure(ExprClosure {
+        attrs: vec![],
+        movability: None,
+        asyncness: Some(Default::default()),
+        capture: None,
+        or1_token: Default::default(),
+        inputs: Punctuated::new(),
+        or2_token: Default::default(),
+        output: ReturnType::Default,
+        body: Box::new(Expr::Block(ExprBlock {
+            attrs: vec![],
+            label: None,
+            block: Block {
+                brace_token: Default::default(),
+                stmts: vec![],
+            },
+        })),
+    });
+
+    assert_eq!(expected, syn::parse_str(raw).unwrap());
+}
diff --git a/tests/test_derive_input.rs b/tests/test_derive_input.rs
index 5ca2c72..045e506 100644
--- a/tests/test_derive_input.rs
+++ b/tests/test_derive_input.rs
@@ -84,7 +84,6 @@
                 Parenthesis,
                 vec![word("Debug"), op(','), word("Clone")],
             )]),
-            is_sugared_doc: false,
         }],
         generics: Generics::default(),
         data: Data::Struct(DataStruct {
@@ -254,7 +253,6 @@
                         " See the std::result module documentation for details.",
                     )),
                 ]),
-                is_sugared_doc: false,
             },
             Attribute {
                 bracket_token: Default::default(),
@@ -262,7 +260,6 @@
                 style: AttrStyle::Outer,
                 path: ident("must_use").into(),
                 tts: TokenStream::new(),
-                is_sugared_doc: false,
             },
         ],
         generics: Generics {
@@ -447,7 +444,6 @@
                     ],
                 ),
             ]),
-            is_sugared_doc: false,
         }],
         generics: Generics::default(),
         data: Data::Struct(DataStruct {
@@ -483,7 +479,6 @@
                 segments: punctuated![PathSegment::from(ident("inert"))],
             },
             tts: TokenStream::from_iter(vec![op('<'), word("T"), op('>')]),
-            is_sugared_doc: false,
         }],
         generics: Generics::default(),
         data: Data::Struct(DataStruct {
@@ -522,7 +517,6 @@
                 ],
             },
             tts: TokenStream::new(),
-            is_sugared_doc: false,
         }],
         generics: Generics::default(),
         data: Data::Struct(DataStruct {
diff --git a/tests/test_expr.rs b/tests/test_expr.rs
deleted file mode 100644
index 4b5bf8c..0000000
--- a/tests/test_expr.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2018 Syn Developers
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![cfg(feature = "extra-traits")]
-
-extern crate proc_macro2;
-extern crate syn;
-use proc_macro2::*;
-use syn::*;
-
-macro_rules! assert_let {
-    ($p:pat = $e:expr) => {
-        assert_let!($p = $e; {})
-    };
-
-    ($p:pat = $e:expr; $body:block) => {
-        if let $p = $e
-            $body
-        else {
-            panic!("Expected to match {} but got {:?}", stringify!($p), $e)
-        }
-    };
-}
-
-#[test]
-#[cfg(feature = "full")]
-fn test_catch_expr() {
-    // Taken from tests/rust/src/test/run-pass/catch-expr.rs
-    let raw = r#"
-        struct catch {}
-
-        pub fn main() {
-            let catch_result = do catch {
-                let x = 5;
-                x
-            };
-            assert_eq!(catch_result, 5);
-
-            let mut catch = true;
-            while catch { catch = false; }
-            assert_eq!(catch, false);
-
-            catch = if catch { false } else { true };
-            assert_eq!(catch, true);
-
-            match catch {
-                _ => {}
-            };
-
-            let catch_err = do catch {
-                Err(22)?;
-                Ok(1)
-            };
-            assert_eq!(catch_err, Err(22));
-
-            let catch_okay: Result<i32, i32> = do catch {
-                if false { Err(25)?; }
-                Ok::<(), i32>(())?;
-                Ok(28)
-            };
-            assert_eq!(catch_okay, Ok(28));
-
-            let catch_from_loop: Result<i32, i32> = do catch {
-                for i in 0..10 {
-                    if i < 5 { Ok::<i32, i32>(i)?; } else { Err(i)?; }
-                }
-                Ok(22)
-            };
-            assert_eq!(catch_from_loop, Err(5));
-
-            let cfg_init;
-            let _res: Result<(), ()> = do catch {
-                cfg_init = 5;
-                Ok(())
-            };
-            assert_eq!(cfg_init, 5);
-
-            let cfg_init_2;
-            let _res: Result<(), ()> = do catch {
-                cfg_init_2 = 6;
-                Err(())?;
-                Ok(())
-            };
-            assert_eq!(cfg_init_2, 6);
-
-            let my_string = "test".to_string();
-            let res: Result<&str, ()> = do catch {
-                Ok(&my_string)
-            };
-            assert_eq!(res, Ok("test"));
-        }
-    "#;
-
-    let actual: File = syn::parse_str(raw).unwrap();
-
-    assert_let!(Item::Struct(ItemStruct { ref ident, .. }) = actual.items[0]; {
-        assert_eq!(ident, "catch");
-    });
-
-    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::Catch(..) = **init_expr);
-            });
-        });
-
-        assert_let!(Stmt::Local(ref local) = block.stmts[2]; {
-            assert_let!(Pat::Ident(PatIdent { by_ref: None, mutability: Some(_), ref ident, .. }) = local.pats.iter().next().unwrap(); {
-                assert_eq!(ident, "catch");
-            });
-        });
-
-        assert_let!(Stmt::Expr(ref expr) = block.stmts[3]; {
-            assert_let!(Expr::While(ExprWhile { ref cond, .. }) = *expr; {
-                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
-                    let name = Ident::new("catch", Span::call_site());
-                    assert_eq!(*path, name.into());
-                });
-            });
-        });
-
-        assert_let!(Stmt::Semi(ref expr, _) = block.stmts[5]; {
-            assert_let!(Expr::Assign(ExprAssign { ref left, ref right, .. }) = *expr; {
-                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **left; {
-                    let name = Ident::new("catch", Span::call_site());
-                    assert_eq!(*path, name.into());
-                });
-
-                assert_let!(Expr::If(ExprIf { ref cond, .. }) = **right; {
-                    assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **cond; {
-                        let name = Ident::new("catch", Span::call_site());
-                        assert_eq!(*path, name.into());
-                    });
-                });
-            });
-        });
-
-        assert_let!(Stmt::Semi(ref expr, _) = block.stmts[7]; {
-            assert_let!(Expr::Match(ExprMatch { ref expr, .. }) = *expr; {
-                assert_let!(Expr::Path(ExprPath { qself: None, ref path, .. }) = **expr; {
-                    let name = Ident::new("catch", Span::call_site());
-                    assert_eq!(*path, name.into());
-                });
-            });
-        });
-    });
-}
diff --git a/tests/test_generics.rs b/tests/test_generics.rs
index fe33fbd..d3b33ed 100644
--- a/tests/test_generics.rs
+++ b/tests/test_generics.rs
@@ -54,7 +54,6 @@
                     style: AttrStyle::Outer,
                     path: ident("may_dangle").into(),
                     tts: TokenStream::new(),
-                    is_sugared_doc: false,
                 }],
                 ident: ident("T"),
                 bounds: punctuated![TypeParamBound::Lifetime(Lifetime::new(
@@ -113,18 +112,12 @@
 fn test_ty_param_bound() {
     let tokens = quote!('a);
     let expected = TypeParamBound::Lifetime(Lifetime::new("'a", Span::call_site()));
-    assert_eq!(
-        expected,
-        common::parse::syn::<TypeParamBound>(tokens.into())
-    );
+    assert_eq!(expected, syn::parse2::<TypeParamBound>(tokens).unwrap());
 
     let tokens = quote!('_);
     println!("{:?}", tokens);
     let expected = TypeParamBound::Lifetime(Lifetime::new("'_", Span::call_site()));
-    assert_eq!(
-        expected,
-        common::parse::syn::<TypeParamBound>(tokens.into())
-    );
+    assert_eq!(expected, syn::parse2::<TypeParamBound>(tokens).unwrap());
 
     let tokens = quote!(Debug);
     let expected = TypeParamBound::Trait(TraitBound {
@@ -133,10 +126,7 @@
         lifetimes: None,
         path: ident("Debug").into(),
     });
-    assert_eq!(
-        expected,
-        common::parse::syn::<TypeParamBound>(tokens.into())
-    );
+    assert_eq!(expected, syn::parse2::<TypeParamBound>(tokens).unwrap());
 
     let tokens = quote!(?Sized);
     let expected = TypeParamBound::Trait(TraitBound {
@@ -145,10 +135,7 @@
         lifetimes: None,
         path: ident("Sized").into(),
     });
-    assert_eq!(
-        expected,
-        common::parse::syn::<TypeParamBound>(tokens.into())
-    );
+    assert_eq!(expected, syn::parse2::<TypeParamBound>(tokens).unwrap());
 }
 
 #[test]
@@ -161,7 +148,7 @@
         {
         }
     };
-    let fun = common::parse::syn::<ItemFn>(sig.into());
+    let fun = syn::parse2::<ItemFn>(sig).unwrap();
     let where_clause = fun.decl.generics.where_clause.as_ref().unwrap();
     assert_eq!(where_clause.predicates.len(), 1);
     let predicate = match where_clause.predicates[0] {
diff --git a/tests/test_grouping.rs b/tests/test_grouping.rs
index 96ab164..78211ec 100644
--- a/tests/test_grouping.rs
+++ b/tests/test_grouping.rs
@@ -56,7 +56,7 @@
     assert_eq!(raw.to_string(), "1i32 +  2i32 + 3i32  * 4i32");
 
     assert_eq!(
-        common::parse::syn::<Expr>(raw),
+        syn::parse2::<syn::Expr>(raw).unwrap(),
         expr(ExprBinary {
             attrs: Vec::new(),
             left: Box::new(lit(Literal::i32_suffixed(1))),
@@ -79,45 +79,3 @@
         })
     );
 }
-
-#[test]
-fn test_invalid_grouping() {
-    let raw: TokenStream = vec![
-        TokenTree::Literal(Literal::i32_suffixed(1)),
-        TokenTree::Punct(Punct::new('+', Spacing::Alone)),
-        TokenTree::Group(proc_macro2::Group::new(
-            Delimiter::None,
-            vec![
-                TokenTree::Literal(Literal::i32_suffixed(2)),
-                TokenTree::Punct(Punct::new('+', Spacing::Alone)),
-            ].into_iter()
-            .collect(),
-        )),
-        TokenTree::Literal(Literal::i32_suffixed(3)),
-        TokenTree::Punct(Punct::new('*', Spacing::Alone)),
-        TokenTree::Literal(Literal::i32_suffixed(4)),
-    ].into_iter()
-    .collect();
-
-    assert_eq!(raw.to_string(), "1i32 +  2i32 +  3i32 * 4i32");
-
-    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_suffixed(1))),
-                op: BinOp::Add(<Token![+]>::default()),
-                right: Box::new(lit(Literal::i32_suffixed(2))),
-            })),
-            op: BinOp::Add(<Token![+]>::default()),
-            right: Box::new(expr(ExprBinary {
-                attrs: Vec::new(),
-                left: Box::new(lit(Literal::i32_suffixed(3))),
-                op: BinOp::Mul(<Token![*]>::default()),
-                right: Box::new(lit(Literal::i32_suffixed(4))),
-            })),
-        })
-    );
-}
diff --git a/tests/test_ident.rs b/tests/test_ident.rs
index 73187d3..498e8be 100644
--- a/tests/test_ident.rs
+++ b/tests/test_ident.rs
@@ -11,9 +11,9 @@
 
 use proc_macro2::{Ident, Span, TokenStream};
 use std::str::FromStr;
-use syn::synom::ParseError;
+use syn::parse::Error;
 
-fn parse(s: &str) -> Result<Ident, ParseError> {
+fn parse(s: &str) -> Result<Ident, Error> {
     syn::parse2(TokenStream::from_str(s).unwrap())
 }
 
diff --git a/tests/test_meta_item.rs b/tests/test_meta_item.rs
index a45e36e..623e5da 100644
--- a/tests/test_meta_item.rs
+++ b/tests/test_meta_item.rs
@@ -11,8 +11,8 @@
 extern crate proc_macro2;
 extern crate syn;
 
-use proc_macro2::{Ident, Literal, Span, TokenStream};
-use syn::buffer::TokenBuffer;
+use proc_macro2::{Ident, Literal, Span};
+use syn::parse::Parser;
 use syn::*;
 
 #[macro_use]
@@ -168,14 +168,8 @@
 }
 
 fn run_test<T: Into<Meta>>(input: &str, expected: T) {
-    let tokens = input.parse::<TokenStream>().unwrap();
-    let buf = TokenBuffer::new2(tokens);
-    let attr = match Attribute::parse_outer(buf.begin()) {
-        Ok((e, rest)) => {
-            assert!(rest.eof());
-            e
-        }
-        Err(err) => panic!(err),
-    };
+    let attrs = Attribute::parse_outer.parse_str(input).unwrap();
+    assert_eq!(attrs.len(), 1);
+    let attr = attrs.into_iter().next().unwrap();
     assert_eq!(expected.into(), attr.interpret_meta().unwrap());
 }
diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs
index b272d49..4d10090 100644
--- a/tests/test_precedence.rs
+++ b/tests/test_precedence.rs
@@ -92,7 +92,6 @@
 /// Test expressions from rustc, like in `test_round_trip`.
 #[test]
 fn test_rustc_precedence() {
-    common::check_min_stack();
     common::clone_rust();
     let abort_after = common::abort_after();
     if abort_after == 0 {
@@ -228,18 +227,6 @@
     impl Folder for BracketsFolder {
         fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
             e.map(|e| match e.node {
-                ExprKind::Block(_, label) if label.is_some() => Expr {
-                    id: ast::DUMMY_NODE_ID,
-                    node: ExprKind::Paren(P(e)),
-                    span: DUMMY_SP,
-                    attrs: ThinVec::new(),
-                },
-                ExprKind::TryBlock(_) => Expr {
-                    id: ast::DUMMY_NODE_ID,
-                    node: ExprKind::Paren(P(e)),
-                    span: DUMMY_SP,
-                    attrs: ThinVec::new(),
-                },
                 ExprKind::If(..) | ExprKind::Block(..) | ExprKind::IfLet(..) => {
                     fold::noop_fold_expr(e, self)
                 }
diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs
index 87c1a04..954c34d 100644
--- a/tests/test_round_trip.rs
+++ b/tests/test_round_trip.rs
@@ -42,7 +42,6 @@
 
 #[test]
 fn test_round_trip() {
-    common::check_min_stack();
     common::clone_rust();
     let abort_after = common::abort_after();
     if abort_after == 0 {
diff --git a/tests/test_token_trees.rs b/tests/test_token_trees.rs
index c385727..02d8f48 100644
--- a/tests/test_token_trees.rs
+++ b/tests/test_token_trees.rs
@@ -82,7 +82,6 @@
             bracket_token: Default::default(),
             path: Ident::new("test", Span::call_site()).into(),
             tts,
-            is_sugared_doc: false,
         }
     }