Merge syn-error-experiment
diff --git a/.gitignore b/.gitignore
index b1c7301..aba0fb5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
-/Cargo.lock
-/target
-**/*.rs.bk
+target
+Cargo.lock
+tests/rust/*
+!tests/rust/clone.sh
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..bd79341
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,64 @@
+sudo: false
+language: rust
+
+cache:
+  cargo: true
+  directories:
+    - tests/rust
+
+rust:
+  - nightly
+  - stable
+  - beta
+  - 1.15.1
+
+before_script:
+  - set -o errexit
+
+script:
+  - cargo build --no-default-features
+  - cargo build
+  - cargo build --features full
+  - cargo build --features 'fold visit visit-mut'
+  - cargo build --features 'full fold visit visit-mut'
+  - cargo build --no-default-features --features derive
+  - cargo build --no-default-features --features 'derive parsing'
+  - cargo build --no-default-features --features 'derive printing'
+  - cargo build --no-default-features --features full
+  - cargo build --no-default-features --features 'full parsing'
+  - cargo build --no-default-features --features 'full printing'
+  - cargo build --no-default-features --features 'full parsing printing'
+  - cargo build --no-default-features --features 'fold visit visit-mut parsing printing'
+  - cargo build --no-default-features --features 'full fold visit visit-mut parsing printing'
+
+matrix:
+  include:
+    - rust: nightly
+      env: ROLE=test
+      script:
+        - cargo test --all-features --release
+    - rust: nightly
+      env: ROLE=codegen
+      script:
+        - (cd codegen && cargo run)
+        - git diff --exit-code
+    - rust: nightly
+      env: ROLE=minimal
+      script:
+        - cargo update -Z minimal-versions
+        - cargo build --all-features
+    - rust: nightly
+      env: ROLE=clippy
+      script:
+        - rustup component add clippy-preview
+        - cargo clippy --all-features -- -Dclippy
+  allow_failures:
+    - rust: nightly
+      env: ROLE=clippy
+  fast_finish: true
+
+env:
+  matrix:
+    - ROLE=build
+  global:
+    - RUST_MIN_STACK=20000000
diff --git a/Cargo.toml b/Cargo.toml
index 6dd6f14..5faba2b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,21 +1,48 @@
 [package]
-name = "syn-error-experiment"
-version = "0.0.0"
+name = "syn"
+version = "0.14.9" # don't forget to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 license = "MIT/Apache-2.0"
-description = "Syn error experiment"
-repository = "https://github.com/dtolnay/syn/issues/47"
-documentation = "https://docs.rs/syn-error-experiment"
+description = "Nom parser for Rust source code"
+repository = "https://github.com/dtolnay/syn"
+documentation = "https://docs.rs/syn"
 categories = ["development-tools::procedural-macro-helpers"]
+readme = "README.md"
+include = ["/Cargo.toml", "/src/**/*.rs", "/README.md", "/LICENSE-APACHE", "/LICENSE-MIT"]
+
+[[example]]
+name = "dump-syntax"
+path = "examples/dump-syntax/main.rs"
+required-features = ["full", "parsing", "extra-traits"]
 
 [features]
-default = ["proc-macro"]
-proc-macro = ["proc-macro2/proc-macro", "syn/proc-macro"]
+default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"]
+derive = []
+full = []
+parsing = []
+printing = ["quote"]
+visit = []
+visit-mut = []
+fold = []
+clone-impls = []
+extra-traits = []
+proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"]
 
 [dependencies]
-proc-macro2 = { version = "0.4", default-features = false }
+proc-macro2 = { version = "0.4.4", default-features = false }
+quote = { version = "0.6", optional = true, default-features = false }
+unicode-xid = "0.1"
 
-[dependencies.syn]
-version = "0.14"
-default-features = false
-features = ["parsing"]
+[dev-dependencies]
+rayon = "1.0"
+regex = "1.0"
+walkdir = "2.1"
+
+[package.metadata.docs.rs]
+all-features = true
+
+[package.metadata.playground]
+all-features = true
+
+[badges]
+travis-ci = { repository = "dtolnay/syn" }
diff --git a/LICENSE-MIT b/LICENSE-MIT
index 31aa793..5767dea 100644
--- a/LICENSE-MIT
+++ b/LICENSE-MIT
@@ -1,3 +1,5 @@
+Copyright (c) 2018 Syn Developers
+
 Permission is hereby granted, free of charge, to any
 person obtaining a copy of this software and associated
 documentation files (the "Software"), to deal in the
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e7a51ab
--- /dev/null
+++ b/README.md
@@ -0,0 +1,282 @@
+Nom parser for Rust source code
+===============================
+
+[![Build Status](https://api.travis-ci.org/dtolnay/syn.svg?branch=master)](https://travis-ci.org/dtolnay/syn)
+[![Latest Version](https://img.shields.io/crates/v/syn.svg)](https://crates.io/crates/syn)
+[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/syn/0.14/syn/)
+[![Rustc Version 1.15+](https://img.shields.io/badge/rustc-1.15+-lightgray.svg)](https://blog.rust-lang.org/2017/02/02/Rust-1.15.html)
+
+Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree
+of Rust source code.
+
+Currently this library is geared toward the [custom derive] use case but
+contains some APIs that may be useful for Rust procedural macros more generally.
+
+[custom derive]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
+
+- **Data structures** — Syn provides a complete syntax tree that can represent
+  any valid Rust source code. The syntax tree is rooted at [`syn::File`] which
+  represents a full source file, but there are other entry points that may be
+  useful to procedural macros including [`syn::Item`], [`syn::Expr`] and
+  [`syn::Type`].
+
+- **Custom derives** — Of particular interest to custom derives is
+  [`syn::DeriveInput`] which is any of the three legal input items to a derive
+  macro. An example below shows using this type in a library that can derive
+  implementations of a trait of your own.
+
+- **Parser combinators** — Parsing in Syn is built on a suite of public parser
+  combinator macros that you can use for parsing any token-based syntax you
+  dream up within a `functionlike!(...)` procedural macro. Every syntax tree
+  node defined by Syn is individually parsable and may be used as a building
+  block for custom syntaxes, or you may do it all yourself working from the most
+  primitive tokens.
+
+- **Location information** — Every token parsed by Syn is associated with a
+  `Span` that tracks line and column information back to the source of that
+  token. These spans allow a procedural macro to display detailed error messages
+  pointing to all the right places in the user's code. There is an example of
+  this below.
+
+- **Feature flags** — Functionality is aggressively feature gated so your
+  procedural macros enable only what they need, and do not pay in compile time
+  for all the rest.
+
+[`syn::File`]: https://docs.rs/syn/0.14/syn/struct.File.html
+[`syn::Item`]: https://docs.rs/syn/0.14/syn/enum.Item.html
+[`syn::Expr`]: https://docs.rs/syn/0.14/syn/enum.Expr.html
+[`syn::Type`]: https://docs.rs/syn/0.14/syn/enum.Type.html
+[`syn::DeriveInput`]: https://docs.rs/syn/0.14/syn/struct.DeriveInput.html
+
+If you get stuck with anything involving procedural macros in Rust I am happy to
+provide help even if the issue is not related to Syn. Please file a ticket in
+this repo.
+
+*Version requirement: Syn supports any compiler version back to Rust's very
+first support for procedural macros in Rust 1.15.0. Some features especially
+around error reporting are only available in newer compilers or on the nightly
+channel.*
+
+[*Release notes*](https://github.com/dtolnay/syn/releases)
+
+## Example of a custom derive
+
+The canonical custom derive using Syn looks like this. We write an ordinary Rust
+function tagged with a `proc_macro_derive` attribute and the name of the trait
+we are deriving. Any time that derive appears in the user's code, the Rust
+compiler passes their data structure as tokens into our macro. We get to execute
+arbitrary Rust code to figure out what to do with those tokens, then hand some
+tokens back to the compiler to compile into the user's crate.
+
+[`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
+
+```toml
+[dependencies]
+syn = "0.14"
+quote = "0.6"
+
+[lib]
+proc-macro = true
+```
+
+```rust
+extern crate proc_macro;
+extern crate syn;
+
+#[macro_use]
+extern crate quote;
+
+use proc_macro::TokenStream;
+use syn::DeriveInput;
+
+#[proc_macro_derive(MyMacro)]
+pub fn my_macro(input: TokenStream) -> TokenStream {
+    // Parse the input tokens into a syntax tree
+    let input: DeriveInput = syn::parse(input).unwrap();
+
+    // Build the output, possibly using quasi-quotation
+    let expanded = quote! {
+        // ...
+    };
+
+    // Hand the output tokens back to the compiler
+    expanded.into()
+}
+```
+
+The [`heapsize`] example directory shows a complete working Macros 1.1
+implementation of a custom derive. It works on any Rust compiler \>=1.15.0. The
+example derives a `HeapSize` trait which computes an estimate of the amount of
+heap memory owned by a value.
+
+[`heapsize`]: examples/heapsize
+
+```rust
+pub trait HeapSize {
+    /// Total number of bytes of heap memory owned by `self`.
+    fn heap_size_of_children(&self) -> usize;
+}
+```
+
+The custom derive allows users to write `#[derive(HeapSize)]` on data structures
+in their program.
+
+```rust
+#[derive(HeapSize)]
+struct Demo<'a, T: ?Sized> {
+    a: Box<T>,
+    b: u8,
+    c: &'a str,
+    d: String,
+}
+```
+
+## Spans and error reporting
+
+The [`heapsize2`] example directory is an extension of the `heapsize` example
+that demonstrates some of the hygiene and error reporting properties of Macros
+2.0. This example currently requires a nightly Rust compiler \>=1.24.0-nightly
+but we are working to stabilize all of the APIs involved.
+
+[`heapsize2`]: examples/heapsize2
+
+The token-based procedural macro API provides great control over where the
+compiler's error messages are displayed in user code. Consider the error the
+user sees if one of their field types does not implement `HeapSize`.
+
+```rust
+#[derive(HeapSize)]
+struct Broken {
+    ok: String,
+    bad: std::thread::Thread,
+}
+```
+
+In the Macros 1.1 string-based procedural macro world, the resulting error would
+point unhelpfully to the invocation of the derive macro and not to the actual
+problematic field.
+
+```
+error[E0599]: no method named `heap_size_of_children` found for type `std::thread::Thread` in the current scope
+ --> src/main.rs:4:10
+  |
+4 | #[derive(HeapSize)]
+  |          ^^^^^^^^
+```
+
+By tracking span information all the way through the expansion of a procedural
+macro as shown in the `heapsize2` example, token-based macros in Syn are able to
+trigger errors that directly pinpoint the source of the problem.
+
+```
+error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
+ --> src/main.rs:7:5
+  |
+7 |     bad: std::thread::Thread,
+  |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
+```
+
+## Parsing a custom syntax using combinators
+
+The [`lazy-static`] example directory shows the implementation of a
+`functionlike!(...)` procedural macro in which the input tokens are parsed using
+[`nom`]-style parser combinators.
+
+[`lazy-static`]: examples/lazy-static
+[`nom`]: https://github.com/Geal/nom
+
+The example reimplements the popular `lazy_static` crate from crates.io as a
+procedural macro.
+
+```
+lazy_static! {
+    static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
+}
+```
+
+The implementation shows how to trigger custom warnings and error messages on
+the macro input.
+
+```
+warning: come on, pick a more creative name
+  --> src/main.rs:10:16
+   |
+10 |     static ref FOO: String = "lazy_static".to_owned();
+   |                ^^^
+```
+
+## Debugging
+
+When developing a procedural macro it can be helpful to look at what the
+generated code looks like. Use `cargo rustc -- -Zunstable-options
+--pretty=expanded` or the [`cargo expand`] subcommand.
+
+[`cargo expand`]: https://github.com/dtolnay/cargo-expand
+
+To show the expanded code for some crate that uses your procedural macro, run
+`cargo expand` from that crate. To show the expanded code for one of your own
+test cases, run `cargo expand --test the_test_case` where the last argument is
+the name of the test file without the `.rs` extension.
+
+This write-up by Brandon W Maister discusses debugging in more detail:
+[Debugging Rust's new Custom Derive system][debugging].
+
+[debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
+
+## Optional features
+
+Syn puts a lot of functionality behind optional features in order to optimize
+compile time for the most common use cases. The following features are
+available.
+
+- **`derive`** *(enabled by default)* — Data structures for representing the
+  possible input to a custom derive, including structs and enums and types.
+- **`full`** — Data structures for representing the syntax tree of all valid
+  Rust source code, including items and expressions.
+- **`parsing`** *(enabled by default)* — Ability to parse input tokens into a
+  syntax tree node of a chosen type.
+- **`printing`** *(enabled by default)* — Ability to print a syntax tree node as
+  tokens of Rust source code.
+- **`visit`** — Trait for traversing a syntax tree.
+- **`visit-mut`** — Trait for traversing and mutating in place a syntax tree.
+- **`fold`** — Trait for transforming an owned syntax tree.
+- **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
+  types.
+- **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
+  types.
+- **`proc-macro`** *(enabled by default)* — Runtime dependency on the dynamic
+  library libproc_macro from rustc toolchain.
+
+## Nightly features
+
+By default Syn uses the [`proc-macro2`] crate to emulate the nightly compiler's
+procedural macro API in a stable way that works all the way back to Rust 1.15.0.
+This shim makes it possible to write code without regard for whether the current
+compiler version supports the features we use.
+
+[`proc-macro2`]: https://github.com/alexcrichton/proc-macro2
+
+On a nightly compiler, to eliminate the stable shim and use the compiler's
+`proc-macro` directly, add `proc-macro2` to your Cargo.toml and set its
+`"nightly"` feature which bypasses the stable shim.
+
+```toml
+[dependencies]
+syn = "0.14"
+proc-macro2 = { version = "0.4", features = ["nightly"] }
+```
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..020c8ac
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,16 @@
+environment:
+  matrix:
+  - TARGET: x86_64-pc-windows-msvc
+
+install:
+  - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
+  - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
+  - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
+  - SET PATH=%PATH%;C:\MinGW\bin
+  - rustc -V
+  - cargo -V
+
+build: false
+
+test_script:
+  - cargo build --all-features
diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml
new file mode 100644
index 0000000..3d3c391
--- /dev/null
+++ b/codegen/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "syn_codegen"
+version = "0.1.0"
+authors = ["Nika Layzell <nika@thelayzells.com>"]
+
+publish = false # this is an internal crate which should never be published
+
+[dependencies]
+syn = { path = "..", features = ["full", "extra-traits"] }
+quote = "0.6"
+failure = "0.1"
+inflections = "1.1"
+proc-macro2 = "0.4"
+rustfmt-nightly = "0.99"
diff --git a/codegen/README.md b/codegen/README.md
new file mode 100644
index 0000000..df46bd2
--- /dev/null
+++ b/codegen/README.md
@@ -0,0 +1,12 @@
+# syn_codegen
+
+This is an internal (not published on crates.io) crate which is used to generate
+the files in the `gen/` directory of `syn`. It is used to ensure that the
+implementations for `Fold`, `Visit`, and `VisitMut` remain in sync with the
+actual AST.
+
+To run this program, run `cargo run` in this directory, and the `gen/` folder
+will be re-generated.
+
+This program is slow, and is therefore not run when building `syn` as part of
+the build script to save on compile time.
diff --git a/codegen/src/main.rs b/codegen/src/main.rs
new file mode 100644
index 0000000..0cf873e
--- /dev/null
+++ b/codegen/src/main.rs
@@ -0,0 +1,1173 @@
+//! This crate automatically generates the definition of the `Visit`,
+//! `VisitMut`, and `Fold` traits in `syn` based on the `syn` source. It
+//! discovers structs and enums declared with the `ast_*` macros and generates
+//! the functions for those types.
+//!
+//! It makes a few assumptions about the target crate:
+//! 1. All structs which are discovered must be re-exported in the root of the
+//!    crate, even if they were declared in a submodule.
+//! 2. This code cannot discover submodules which are located in subdirectories
+//!    - only submodules located in the same directory.
+//! 3. The path to `syn` is hardcoded.
+
+#![recursion_limit = "128"]
+#![cfg_attr(
+    feature = "cargo-clippy",
+    allow(
+        needless_pass_by_value,
+        redundant_closure,
+        write_with_newline,
+    )
+)]
+
+#[macro_use]
+extern crate failure;
+extern crate inflections;
+extern crate proc_macro2;
+#[macro_use]
+extern crate quote;
+#[macro_use]
+extern crate syn;
+extern crate rustfmt_nightly as rustfmt;
+
+use failure::{err_msg, Error};
+use proc_macro2::{Span, TokenStream};
+use quote::ToTokens;
+use syn::{Attribute, Data, DataStruct, DeriveInput, Ident, Item};
+
+use std::collections::BTreeMap;
+use std::fmt::{self, Debug};
+use std::fs::File;
+use std::io::{Read, Write};
+use std::path::Path;
+
+const SYN_CRATE_ROOT: &str = "../src/lib.rs";
+
+const FOLD_SRC: &str = "../src/gen/fold.rs";
+const VISIT_SRC: &str = "../src/gen/visit.rs";
+const VISIT_MUT_SRC: &str = "../src/gen/visit_mut.rs";
+
+const IGNORED_MODS: &[&str] = &["fold", "visit", "visit_mut"];
+
+const EXTRA_TYPES: &[&str] = &["Lifetime"];
+
+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
+}
+
+fn get_features(attrs: &[Attribute], mut features: TokenStream) -> TokenStream {
+    for attr in attrs {
+        if path_eq(&attr.path, "cfg") {
+            attr.to_tokens(&mut features);
+        }
+    }
+    features
+}
+
+#[derive(Clone)]
+pub struct AstItem {
+    ast: DeriveInput,
+    features: TokenStream,
+    // True if this is an ast_enum_of_structs! item with a #full annotation.
+    eos_full: bool,
+}
+
+impl Debug for AstItem {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("AstItem")
+            .field("ast", &self.ast)
+            .field("features", &self.features.to_string())
+            .finish()
+    }
+}
+
+// NOTE: BTreeMap is used here instead of HashMap to have deterministic output.
+type Lookup = BTreeMap<Ident, AstItem>;
+
+fn load_file<P: AsRef<Path>>(
+    name: P,
+    features: &TokenStream,
+    lookup: &mut Lookup,
+) -> Result<(), Error> {
+    let name = name.as_ref();
+    let parent = name.parent().ok_or_else(|| err_msg("no parent path"))?;
+
+    let mut f = File::open(name)?;
+    let mut src = String::new();
+    f.read_to_string(&mut src)?;
+
+    // Parse the file
+    let file =
+        syn::parse_file(&src).map_err(|_| format_err!("failed to parse {}", name.display()))?;
+
+    // Collect all of the interesting AstItems declared in this file or submodules.
+    'items: for item in file.items {
+        match item {
+            Item::Mod(item) => {
+                // Don't inspect inline modules.
+                if item.content.is_some() {
+                    continue;
+                }
+
+                // We don't want to try to load the generated rust files and
+                // parse them, so we ignore them here.
+                for name in IGNORED_MODS {
+                    if item.ident == name {
+                        continue 'items;
+                    }
+                }
+
+                // Lookup any #[cfg()] attributes on the module and add them to
+                // the feature set.
+                //
+                // The derive module is weird because it is built with either
+                // `full` or `derive` but exported only under `derive`.
+                let features = if item.ident == "derive" {
+                    quote!(#[cfg(feature = "derive")])
+                } else {
+                    get_features(&item.attrs, features.clone())
+                };
+
+                // Look up the submodule file, and recursively parse it.
+                // XXX: Only handles same-directory .rs file submodules.
+                let path = parent.join(&format!("{}.rs", item.ident));
+                load_file(path, &features, lookup)?;
+            }
+            Item::Macro(item) => {
+                // Lookip any #[cfg()] attributes directly on the macro
+                // invocation, and add them to the feature set.
+                let features = get_features(&item.attrs, features.clone());
+
+                // 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())
+                        .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())
+                        .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())
+                        .map_err(|_| err_msg("failed to parse ast_enum_of_structs"))?
+                        .0
+                } else {
+                    continue;
+                };
+
+                // Record our features on the parsed AstItems.
+                for mut item in found {
+                    features.to_tokens(&mut item.features);
+                    lookup.insert(item.ast.ident.clone(), item);
+                }
+            }
+            Item::Struct(item) => {
+                let ident = item.ident;
+                if EXTRA_TYPES.contains(&&ident.to_string()[..]) {
+                    lookup.insert(
+                        ident.clone(),
+                        AstItem {
+                            ast: DeriveInput {
+                                ident,
+                                vis: item.vis,
+                                attrs: item.attrs,
+                                generics: item.generics,
+                                data: Data::Struct(DataStruct {
+                                    fields: item.fields,
+                                    struct_token: item.struct_token,
+                                    semi_token: item.semi_token,
+                                }),
+                            },
+                            features: features.clone(),
+                            eos_full: false,
+                        },
+                    );
+                }
+            }
+            _ => {}
+        }
+    }
+    Ok(())
+}
+
+mod parsing {
+    use super::AstItem;
+
+    use proc_macro2::TokenStream;
+    use syn;
+    use syn::synom::*;
+    use syn::*;
+
+    // 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)
+    }));
+
+    named!(manual_extra_traits -> (), do_parse!(
+        punct!(#) >>
+        id: syn!(Ident) >>
+        cond_reduce!(id == "manual_extra_traits") >>
+        ()
+    ));
+
+    // 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,
+        })
+    ));
+
+    // 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]))
+        ));
+    }
+
+    named!(no_visit -> (), do_parse!(
+        punct!(#) >>
+        id: syn!(Ident) >>
+        cond_reduce!(id == "no_visit") >>
+        ()
+    ));
+
+    // 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() {
+                vec![]
+            } else {
+                vec![AstItem {
+                    ast: syn::parse_str(&quote! {
+                        pub enum #id #rest
+                    }.to_string())?,
+                    features: quote!(),
+                    eos_full: false,
+                }]
+            }))
+        ));
+    }
+
+    // A single variant of an ast_enum_of_structs!
+    struct EosVariant {
+        name: Ident,
+        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 {
+            name: variant,
+            member: member.clone().map(|x| x.0),
+            inner: member.map(|x| x.1).unwrap_or_default(),
+        })
+    ));
+
+    // 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),*
+                        }
+                    }
+                };
+                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)
+            })
+        ));
+    }
+}
+
+mod codegen {
+    use super::{AstItem, Lookup};
+    use inflections::Inflect;
+    use proc_macro2::{Span, TokenStream};
+    use quote::{ToTokens, TokenStreamExt};
+    use syn::punctuated::Punctuated;
+    use syn::synom::ext::IdentExt;
+    use syn::synom::Parser;
+    use syn::*;
+
+    #[derive(Default)]
+    pub struct State {
+        pub visit_trait: TokenStream,
+        pub visit_impl: TokenStream,
+        pub visit_mut_trait: TokenStream,
+        pub visit_mut_impl: TokenStream,
+        pub fold_trait: TokenStream,
+        pub fold_impl: TokenStream,
+    }
+
+    fn under_name(name: Ident) -> Ident {
+        Ident::new(&name.to_string().to_snake_case(), Span::call_site())
+    }
+
+    enum RelevantType<'a> {
+        Box(&'a Type),
+        Vec(&'a Type),
+        Punctuated(&'a Type),
+        Option(&'a Type),
+        Tuple(&'a Punctuated<Type, Token![,]>),
+        Simple(&'a AstItem),
+        TokenPunct(TokenStream),
+        TokenKeyword(TokenStream),
+        TokenGroup(Ident),
+        Pass,
+    }
+
+    fn classify<'a>(ty: &'a Type, lookup: &'a Lookup) -> RelevantType<'a> {
+        match *ty {
+            Type::Path(TypePath {
+                qself: None,
+                ref path,
+            }) => {
+                let last = path.segments.last().unwrap().into_value();
+                match &last.ident.to_string()[..] {
+                    "Box" => RelevantType::Box(first_arg(&last.arguments)),
+                    "Vec" => RelevantType::Vec(first_arg(&last.arguments)),
+                    "Punctuated" => RelevantType::Punctuated(first_arg(&last.arguments)),
+                    "Option" => RelevantType::Option(first_arg(&last.arguments)),
+                    "Brace" | "Bracket" | "Paren" | "Group" => {
+                        RelevantType::TokenGroup(last.ident.clone())
+                    }
+                    _ => {
+                        if let Some(item) = lookup.get(&last.ident) {
+                            RelevantType::Simple(item)
+                        } else {
+                            RelevantType::Pass
+                        }
+                    }
+                }
+            }
+            Type::Tuple(TypeTuple { ref elems, .. }) => RelevantType::Tuple(elems),
+            Type::Macro(TypeMacro { ref mac })
+                if mac.path.segments.last().unwrap().into_value().ident == "Token" =>
+            {
+                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,
+        }
+    }
+
+    #[derive(Debug, Eq, PartialEq, Copy, Clone)]
+    enum Kind {
+        Visit,
+        VisitMut,
+        Fold,
+    }
+
+    enum Operand {
+        Borrowed(TokenStream),
+        Owned(TokenStream),
+    }
+
+    use self::Kind::*;
+    use self::Operand::*;
+
+    impl Operand {
+        fn tokens(&self) -> &TokenStream {
+            match *self {
+                Borrowed(ref n) | Owned(ref n) => n,
+            }
+        }
+
+        fn ref_tokens(&self) -> TokenStream {
+            match *self {
+                Borrowed(ref n) => n.clone(),
+                Owned(ref n) => quote!(&#n),
+            }
+        }
+
+        fn ref_mut_tokens(&self) -> TokenStream {
+            match *self {
+                Borrowed(ref n) => n.clone(),
+                Owned(ref n) => quote!(&mut #n),
+            }
+        }
+
+        fn owned_tokens(&self) -> TokenStream {
+            match *self {
+                Borrowed(ref n) => quote!(*#n),
+                Owned(ref n) => n.clone(),
+            }
+        }
+    }
+
+    fn first_arg(params: &PathArguments) -> &Type {
+        let data = match *params {
+            PathArguments::AngleBracketed(ref data) => data,
+            _ => panic!("Expected at least 1 type argument here"),
+        };
+
+        match **data
+            .args
+            .first()
+            .expect("Expected at least 1 type argument here")
+            .value()
+        {
+            GenericArgument::Type(ref ty) => ty,
+            _ => panic!("Expected at least 1 type argument here"),
+        }
+    }
+
+    fn simple_visit(item: &AstItem, kind: Kind, name: &Operand) -> TokenStream {
+        let ident = under_name(item.ast.ident.clone());
+
+        match kind {
+            Visit => {
+                let method = Ident::new(&format!("visit_{}", ident), Span::call_site());
+                let name = name.ref_tokens();
+                quote! {
+                    _visitor.#method(#name)
+                }
+            }
+            VisitMut => {
+                let method = Ident::new(&format!("visit_{}_mut", ident), Span::call_site());
+                let name = name.ref_mut_tokens();
+                quote! {
+                    _visitor.#method(#name)
+                }
+            }
+            Fold => {
+                let method = Ident::new(&format!("fold_{}", ident), Span::call_site());
+                let name = name.owned_tokens();
+                quote! {
+                    _visitor.#method(#name)
+                }
+            }
+        }
+    }
+
+    fn box_visit(elem: &Type, lookup: &Lookup, kind: Kind, name: &Operand) -> Option<TokenStream> {
+        let name = name.owned_tokens();
+        let res = visit(elem, lookup, kind, &Owned(quote!(*#name)))?;
+        Some(match kind {
+            Fold => quote! {
+                Box::new(#res)
+            },
+            Visit | VisitMut => res,
+        })
+    }
+
+    fn vec_visit(elem: &Type, lookup: &Lookup, kind: Kind, name: &Operand) -> Option<TokenStream> {
+        let operand = match kind {
+            Visit | VisitMut => Borrowed(quote!(it)),
+            Fold => Owned(quote!(it)),
+        };
+        let val = visit(elem, lookup, kind, &operand)?;
+        Some(match kind {
+            Visit => {
+                let name = name.ref_tokens();
+                quote! {
+                    for it in #name {
+                        #val
+                    }
+                }
+            }
+            VisitMut => {
+                let name = name.ref_mut_tokens();
+                quote! {
+                    for it in #name {
+                        #val
+                    }
+                }
+            }
+            Fold => {
+                let name = name.owned_tokens();
+                quote! {
+                    FoldHelper::lift(#name, |it| { #val })
+                }
+            }
+        })
+    }
+
+    fn punctuated_visit(
+        elem: &Type,
+        lookup: &Lookup,
+        kind: Kind,
+        name: &Operand,
+    ) -> Option<TokenStream> {
+        let operand = match kind {
+            Visit | VisitMut => Borrowed(quote!(it)),
+            Fold => Owned(quote!(it)),
+        };
+        let val = visit(elem, lookup, kind, &operand)?;
+        Some(match kind {
+            Visit => {
+                let name = name.ref_tokens();
+                quote! {
+                    for el in Punctuated::pairs(#name) {
+                        let it = el.value();
+                        #val
+                    }
+                }
+            }
+            VisitMut => {
+                let name = name.ref_mut_tokens();
+                quote! {
+                    for mut el in Punctuated::pairs_mut(#name) {
+                        let it = el.value_mut();
+                        #val
+                    }
+                }
+            }
+            Fold => {
+                let name = name.owned_tokens();
+                quote! {
+                    FoldHelper::lift(#name, |it| { #val })
+                }
+            }
+        })
+    }
+
+    fn option_visit(
+        elem: &Type,
+        lookup: &Lookup,
+        kind: Kind,
+        name: &Operand,
+    ) -> Option<TokenStream> {
+        let it = match kind {
+            Visit | VisitMut => Borrowed(quote!(it)),
+            Fold => Owned(quote!(it)),
+        };
+        let val = visit(elem, lookup, kind, &it)?;
+        let name = name.owned_tokens();
+        Some(match kind {
+            Visit => quote! {
+                if let Some(ref it) = #name {
+                    #val
+                }
+            },
+            VisitMut => quote! {
+                if let Some(ref mut it) = #name {
+                    #val
+                }
+            },
+            Fold => quote! {
+                (#name).map(|it| { #val })
+            },
+        })
+    }
+
+    fn tuple_visit(
+        elems: &Punctuated<Type, Token![,]>,
+        lookup: &Lookup,
+        kind: Kind,
+        name: &Operand,
+    ) -> Option<TokenStream> {
+        if elems.is_empty() {
+            return None;
+        }
+
+        let mut code = TokenStream::new();
+        for (i, elem) in elems.iter().enumerate() {
+            let name = name.tokens();
+            let i = Index::from(i);
+            let it = Owned(quote!((#name).#i));
+            let val = visit(elem, lookup, kind, &it).unwrap_or_else(|| noop_visit(kind, &it));
+            code.append_all(val);
+            match kind {
+                Fold => code.append_all(quote!(,)),
+                Visit | VisitMut => code.append_all(quote!(;)),
+            }
+        }
+        Some(match kind {
+            Fold => quote! {
+                (#code)
+            },
+            Visit | VisitMut => code,
+        })
+    }
+
+    fn token_punct_visit(ty: TokenStream, kind: Kind, name: &Operand) -> TokenStream {
+        let name = name.tokens();
+        match kind {
+            Fold => quote! {
+                #ty(tokens_helper(_visitor, &#name.spans))
+            },
+            Visit => quote! {
+                tokens_helper(_visitor, &#name.spans)
+            },
+            VisitMut => quote! {
+                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)
+            },
+        }
+    }
+
+    fn noop_visit(kind: Kind, name: &Operand) -> TokenStream {
+        match kind {
+            Fold => name.owned_tokens(),
+            Visit | VisitMut => {
+                let name = name.tokens();
+                quote! {
+                    skip!(#name)
+                }
+            }
+        }
+    }
+
+    fn visit(ty: &Type, lookup: &Lookup, kind: Kind, name: &Operand) -> Option<TokenStream> {
+        match classify(ty, lookup) {
+            RelevantType::Box(elem) => box_visit(elem, lookup, kind, name),
+            RelevantType::Vec(elem) => vec_visit(elem, lookup, kind, name),
+            RelevantType::Punctuated(elem) => punctuated_visit(elem, lookup, kind, name),
+            RelevantType::Option(elem) => option_visit(elem, lookup, kind, name),
+            RelevantType::Tuple(elems) => tuple_visit(elems, lookup, kind, name),
+            RelevantType::Simple(item) => {
+                let mut res = simple_visit(item, kind, name);
+                Some(if item.eos_full {
+                    quote! {
+                        full!(#res)
+                    }
+                } else {
+                    res
+                })
+            }
+            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,
+        }
+    }
+
+    pub fn generate(state: &mut State, lookup: &Lookup, s: &AstItem) {
+        let features = &s.features;
+        let under_name = under_name(s.ast.ident.clone());
+        let ty = &s.ast.ident;
+        let visit_fn = Ident::new(&format!("visit_{}", under_name), Span::call_site());
+        let visit_mut_fn = Ident::new(&format!("visit_{}_mut", under_name), Span::call_site());
+        let fold_fn = Ident::new(&format!("fold_{}", under_name), Span::call_site());
+
+        let mut visit_impl = TokenStream::new();
+        let mut visit_mut_impl = TokenStream::new();
+        let mut fold_impl = TokenStream::new();
+
+        match s.ast.data {
+            Data::Enum(ref e) => {
+                let mut visit_variants = TokenStream::new();
+                let mut visit_mut_variants = TokenStream::new();
+                let mut fold_variants = TokenStream::new();
+
+                for variant in &e.variants {
+                    let variant_ident = &variant.ident;
+
+                    match variant.fields {
+                        Fields::Named(..) => panic!("Doesn't support enum struct variants"),
+                        Fields::Unnamed(ref fields) => {
+                            let mut bind_visit_fields = TokenStream::new();
+                            let mut bind_visit_mut_fields = TokenStream::new();
+                            let mut bind_fold_fields = TokenStream::new();
+
+                            let mut visit_fields = TokenStream::new();
+                            let mut visit_mut_fields = TokenStream::new();
+                            let mut fold_fields = TokenStream::new();
+
+                            for (idx, field) in fields.unnamed.iter().enumerate() {
+                                let name = format!("_binding_{}", idx);
+                                let binding = Ident::new(&name, Span::call_site());
+
+                                bind_visit_fields.append_all(quote! {
+                                    ref #binding,
+                                });
+                                bind_visit_mut_fields.append_all(quote! {
+                                    ref mut #binding,
+                                });
+                                bind_fold_fields.append_all(quote! {
+                                    #binding,
+                                });
+
+                                let borrowed_binding = Borrowed(quote!(#binding));
+                                let owned_binding = Owned(quote!(#binding));
+
+                                visit_fields.append_all(
+                                    visit(&field.ty, lookup, Visit, &borrowed_binding)
+                                        .unwrap_or_else(|| noop_visit(Visit, &borrowed_binding)),
+                                );
+                                visit_mut_fields.append_all(
+                                    visit(&field.ty, lookup, VisitMut, &borrowed_binding)
+                                        .unwrap_or_else(|| noop_visit(VisitMut, &borrowed_binding)),
+                                );
+                                fold_fields.append_all(
+                                    visit(&field.ty, lookup, Fold, &owned_binding)
+                                        .unwrap_or_else(|| noop_visit(Fold, &owned_binding)),
+                                );
+
+                                visit_fields.append_all(quote!(;));
+                                visit_mut_fields.append_all(quote!(;));
+                                fold_fields.append_all(quote!(,));
+                            }
+
+                            visit_variants.append_all(quote! {
+                                #ty::#variant_ident(#bind_visit_fields) => {
+                                    #visit_fields
+                                }
+                            });
+
+                            visit_mut_variants.append_all(quote! {
+                                #ty::#variant_ident(#bind_visit_mut_fields) => {
+                                    #visit_mut_fields
+                                }
+                            });
+
+                            fold_variants.append_all(quote! {
+                                #ty::#variant_ident(#bind_fold_fields) => {
+                                    #ty::#variant_ident(
+                                        #fold_fields
+                                    )
+                                }
+                            });
+                        }
+                        Fields::Unit => {
+                            visit_variants.append_all(quote! {
+                                #ty::#variant_ident => {}
+                            });
+                            visit_mut_variants.append_all(quote! {
+                                #ty::#variant_ident => {}
+                            });
+                            fold_variants.append_all(quote! {
+                                #ty::#variant_ident => {
+                                    #ty::#variant_ident
+                                }
+                            });
+                        }
+                    }
+                }
+
+                visit_impl.append_all(quote! {
+                    match *_i {
+                        #visit_variants
+                    }
+                });
+
+                visit_mut_impl.append_all(quote! {
+                    match *_i {
+                        #visit_mut_variants
+                    }
+                });
+
+                fold_impl.append_all(quote! {
+                    match _i {
+                        #fold_variants
+                    }
+                });
+            }
+            Data::Struct(ref v) => {
+                let mut fold_fields = TokenStream::new();
+
+                for (idx, field) in v.fields.iter().enumerate() {
+                    let id = match field.ident {
+                        Some(ref ident) => Member::Named(ident.clone()),
+                        None => Member::Unnamed(Index::from(idx)),
+                    };
+                    let ref_toks = Owned(quote!(_i.#id));
+                    let visit_field = visit(&field.ty, lookup, Visit, &ref_toks)
+                        .unwrap_or_else(|| noop_visit(Visit, &ref_toks));
+                    visit_impl.append_all(quote! {
+                        #visit_field;
+                    });
+                    let visit_mut_field = visit(&field.ty, lookup, VisitMut, &ref_toks)
+                        .unwrap_or_else(|| noop_visit(VisitMut, &ref_toks));
+                    visit_mut_impl.append_all(quote! {
+                        #visit_mut_field;
+                    });
+                    let fold = visit(&field.ty, lookup, Fold, &ref_toks)
+                        .unwrap_or_else(|| noop_visit(Fold, &ref_toks));
+                    if let Some(ref name) = field.ident {
+                        fold_fields.append_all(quote! {
+                            #name: #fold,
+                        });
+                    } else {
+                        fold_fields.append_all(quote! {
+                            #fold,
+                        });
+                    }
+                }
+
+                match v.fields {
+                    Fields::Named(..) | Fields::Unnamed(..) => fold_impl.append_all(quote! {
+                        #ty {
+                            #fold_fields
+                        }
+                    }),
+                    Fields::Unit => {
+                        if ty == "Ident" {
+                            fold_impl.append_all(quote! {
+                                let mut _i = _i;
+                                let span = _visitor.fold_span(_i.span());
+                                _i.set_span(span);
+                            });
+                        }
+                        fold_impl.append_all(quote! {
+                            _i
+                        });
+                    }
+                };
+            }
+            Data::Union(..) => panic!("Union not supported"),
+        }
+
+        let mut include_fold_impl = true;
+        if let Data::Struct(ref data) = s.ast.data {
+            if let Fields::Named(ref fields) = data.fields {
+                if fields
+                    .named
+                    .iter()
+                    .any(|field| field.vis == Visibility::Inherited)
+                {
+                    // Discard the generated impl if there are private fields.
+                    // These have to be handwritten.
+                    include_fold_impl = false;
+                }
+            }
+        }
+
+        state.visit_trait.append_all(quote! {
+            #features
+            fn #visit_fn(&mut self, i: &'ast #ty) {
+                #visit_fn(self, i)
+            }
+        });
+
+        state.visit_impl.append_all(quote! {
+            #features
+            pub fn #visit_fn<'ast, V: Visit<'ast> + ?Sized>(
+                _visitor: &mut V, _i: &'ast #ty
+            ) {
+                #visit_impl
+            }
+        });
+
+        state.visit_mut_trait.append_all(quote! {
+            #features
+            fn #visit_mut_fn(&mut self, i: &mut #ty) {
+                #visit_mut_fn(self, i)
+            }
+        });
+
+        state.visit_mut_impl.append_all(quote! {
+            #features
+            pub fn #visit_mut_fn<V: VisitMut + ?Sized>(
+                _visitor: &mut V, _i: &mut #ty
+            ) {
+                #visit_mut_impl
+            }
+        });
+
+        state.fold_trait.append_all(quote! {
+            #features
+            fn #fold_fn(&mut self, i: #ty) -> #ty {
+                #fold_fn(self, i)
+            }
+        });
+
+        if include_fold_impl {
+            state.fold_impl.append_all(quote! {
+                #features
+                pub fn #fold_fn<V: Fold + ?Sized>(
+                    _visitor: &mut V, _i: #ty
+                ) -> #ty {
+                    #fold_impl
+                }
+            });
+        }
+    }
+}
+
+fn write_file(path: &str, content: TokenStream) {
+    let mut file = File::create(path).unwrap();
+    write!(
+        file,
+        "// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT\n\n"
+    ).unwrap();
+    let mut config = rustfmt::Config::default();
+    config.set().emit_mode(rustfmt::EmitMode::Stdout);
+    config.set().verbose(rustfmt::Verbosity::Quiet);
+    config.set().format_macro_matchers(true);
+    let mut session = rustfmt::Session::new(config, Some(&mut file));
+    session
+        .format(rustfmt::Input::Text(content.to_string()))
+        .unwrap();
+}
+
+fn main() {
+    let mut lookup = BTreeMap::new();
+    load_file(SYN_CRATE_ROOT, &quote!(), &mut lookup).unwrap();
+
+    // Load in any terminal types
+    for &tt in TERMINAL_TYPES {
+        use syn::*;
+        lookup.insert(
+            Ident::new(&tt, Span::call_site()),
+            AstItem {
+                ast: DeriveInput {
+                    ident: Ident::new(tt, Span::call_site()),
+                    vis: Visibility::Public(VisPublic {
+                        pub_token: <Token![pub]>::default(),
+                    }),
+                    attrs: vec![],
+                    generics: Generics::default(),
+                    data: Data::Struct(DataStruct {
+                        fields: Fields::Unit,
+                        struct_token: <Token![struct]>::default(),
+                        semi_token: None,
+                    }),
+                },
+                features: TokenStream::new(),
+                eos_full: false,
+            },
+        );
+    }
+
+    let mut state = codegen::State::default();
+    for s in lookup.values() {
+        codegen::generate(&mut state, &lookup, s);
+    }
+
+    let full_macro = quote! {
+        #[cfg(feature = "full")]
+        macro_rules! full {
+            ($e:expr) => {
+                $e
+            };
+        }
+
+        #[cfg(all(feature = "derive", not(feature = "full")))]
+        macro_rules! full {
+            ($e:expr) => {
+                unreachable!()
+            };
+        }
+    };
+
+    let skip_macro = quote! {
+        #[cfg(any(feature = "full", feature = "derive"))]
+        macro_rules! skip {
+            ($($tt:tt)*) => {};
+        }
+    };
+
+    let fold_trait = state.fold_trait;
+    let fold_impl = state.fold_impl;
+    write_file(
+        FOLD_SRC,
+        quote! {
+            // Unreachable code is generated sometimes without the full feature.
+            #![allow(unreachable_code)]
+            #![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
+
+            use *;
+            #[cfg(any(feature = "full", feature = "derive"))]
+            use token::{Brace, Bracket, Paren, Group};
+            use proc_macro2::Span;
+            #[cfg(any(feature = "full", feature = "derive"))]
+            use gen::helper::fold::*;
+
+            #full_macro
+
+            /// Syntax tree traversal to transform the nodes of an owned syntax tree.
+            ///
+            /// See the [module documentation] for details.
+            ///
+            /// [module documentation]: index.html
+            ///
+            /// *This trait is available if Syn is built with the `"fold"` feature.*
+            pub trait Fold {
+                #fold_trait
+            }
+
+            #[cfg(any(feature = "full", feature = "derive"))]
+            macro_rules! fold_span_only {
+                ($f:ident : $t:ident) => {
+                    pub fn $f<V: Fold + ?Sized>(_visitor: &mut V, mut _i: $t) -> $t {
+                        let span = _visitor.fold_span(_i.span());
+                        _i.set_span(span);
+                        _i
+                    }
+                }
+            }
+
+            #[cfg(any(feature = "full", feature = "derive"))]
+            fold_span_only!(fold_lit_byte: LitByte);
+            #[cfg(any(feature = "full", feature = "derive"))]
+            fold_span_only!(fold_lit_byte_str: LitByteStr);
+            #[cfg(any(feature = "full", feature = "derive"))]
+            fold_span_only!(fold_lit_char: LitChar);
+            #[cfg(any(feature = "full", feature = "derive"))]
+            fold_span_only!(fold_lit_float: LitFloat);
+            #[cfg(any(feature = "full", feature = "derive"))]
+            fold_span_only!(fold_lit_int: LitInt);
+            #[cfg(any(feature = "full", feature = "derive"))]
+            fold_span_only!(fold_lit_str: LitStr);
+
+            #fold_impl
+        },
+    );
+
+    let visit_trait = state.visit_trait;
+    let visit_impl = state.visit_impl;
+    write_file(
+        VISIT_SRC,
+        quote! {
+            #![cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
+
+            use *;
+            #[cfg(any(feature = "full", feature = "derive"))]
+            use punctuated::Punctuated;
+            use proc_macro2::Span;
+            #[cfg(any(feature = "full", feature = "derive"))]
+            use gen::helper::visit::*;
+
+            #full_macro
+            #skip_macro
+
+            /// Syntax tree traversal to walk a shared borrow of a syntax tree.
+            ///
+            /// See the [module documentation] for details.
+            ///
+            /// [module documentation]: index.html
+            ///
+            /// *This trait is available if Syn is built with the `"visit"` feature.*
+            pub trait Visit<'ast> {
+                #visit_trait
+            }
+
+            #visit_impl
+        },
+    );
+
+    let visit_mut_trait = state.visit_mut_trait;
+    let visit_mut_impl = state.visit_mut_impl;
+    write_file(
+        VISIT_MUT_SRC,
+        quote! {
+            #![cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
+
+            use *;
+            #[cfg(any(feature = "full", feature = "derive"))]
+            use punctuated::Punctuated;
+            use proc_macro2::Span;
+            #[cfg(any(feature = "full", feature = "derive"))]
+            use gen::helper::visit_mut::*;
+
+            #full_macro
+            #skip_macro
+
+            /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
+            /// place.
+            ///
+            /// See the [module documentation] for details.
+            ///
+            /// [module documentation]: index.html
+            ///
+            /// *This trait is available if Syn is built with the `"visit-mut"` feature.*
+            pub trait VisitMut {
+                #visit_mut_trait
+            }
+
+            #visit_mut_impl
+        },
+    );
+}
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..75bc450
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,28 @@
+### [`dump-syntax`](dump-syntax)
+
+Little utility to parse a Rust source file into a `syn::File` and print out a
+debug representation of the syntax tree.
+
+### [`heapsize`](heapsize)
+
+A complete working Macros 1.1 implementation of a custom derive. Works on any
+Rust compiler >=1.15.0.
+
+### [`heapsize2`](heapsize2)
+
+The equivalent of the previous example but using fancy new APIs from the nightly
+compiler. It illustrates some neat features of the hygiene system of Macros 2.0
+and shows how to leverage those to provide amazing error messages to users.
+Currently requires a nightly Rust compiler >=1.24.0-nightly but we are working
+to stabilize all of the APIs involved.
+
+### [`lazy-static`](lazy-static)
+
+An example of parsing a custom syntax within a `functionlike!(...)` procedural
+macro. Demonstrates how to trigger custom warnings and error messages on
+individual tokens of the input.
+
+### [`trace-var`](trace-var)
+
+An attribute procedural macro that uses a syntax tree traversal to transform
+certain syntax tree nodes in a function body.
diff --git a/examples/dump-syntax/Cargo.toml b/examples/dump-syntax/Cargo.toml
new file mode 100644
index 0000000..aee56ff
--- /dev/null
+++ b/examples/dump-syntax/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "dump-syntax"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[dependencies.syn]
+path = "../.."
+default-features = false
+features = ["parsing", "full", "extra-traits"]
+
+[[bin]]
+name = "dump-syntax"
+path = "main.rs"
diff --git a/examples/dump-syntax/README.md b/examples/dump-syntax/README.md
new file mode 100644
index 0000000..3b23736
--- /dev/null
+++ b/examples/dump-syntax/README.md
@@ -0,0 +1,28 @@
+Parse a Rust source file into a `syn::File` and print out a debug representation
+of the syntax tree.
+
+Use the following command from this directory to test this program by running it
+on its own source code:
+
+```
+cargo run -- main.rs
+```
+
+The output will begin with:
+
+```
+File {
+    shebang: None,
+    attrs: [
+        Attribute {
+            pound_token: Pound,
+            style: Inner(
+                Bang
+            ),
+            bracket_token: Bracket,
+            path: Path {
+                leading_colon: None,
+                segments: [
+    ...
+}
+```
diff --git a/examples/dump-syntax/main.rs b/examples/dump-syntax/main.rs
new file mode 100644
index 0000000..584fe3c
--- /dev/null
+++ b/examples/dump-syntax/main.rs
@@ -0,0 +1,46 @@
+//! Parse a Rust source file into a `syn::File` and print out a debug
+//! representation of the syntax tree.
+//!
+//! Use the following command from this directory to test this program by
+//! running it on its own source code:
+//!
+//!     cargo run -- main.rs
+//!
+//! The output will begin with:
+//!
+//!     File {
+//!         shebang: None,
+//!         attrs: [
+//!             Attribute {
+//!                 pound_token: Pound,
+//!                 style: Inner(
+//!         ...
+//!     }
+
+extern crate syn;
+
+use std::env;
+use std::fs::File;
+use std::io::Read;
+use std::process;
+
+fn main() {
+    let mut args = env::args();
+    let _ = args.next(); // executable name
+
+    let filename = match (args.next(), args.next()) {
+        (Some(filename), None) => filename,
+        _ => {
+            eprintln!("Usage: dump-syntax path/to/filename.rs");
+            process::exit(1);
+        }
+    };
+
+    let mut file = File::open(&filename).expect("Unable to open file");
+
+    let mut src = String::new();
+    file.read_to_string(&mut src).expect("Unable to read file");
+
+    let syntax = syn::parse_file(&src).expect("Unable to parse file");
+    println!("{:#?}", syntax);
+}
diff --git a/examples/heapsize/README.md b/examples/heapsize/README.md
new file mode 100644
index 0000000..b3deb8d
--- /dev/null
+++ b/examples/heapsize/README.md
@@ -0,0 +1,42 @@
+A complete working Macros 1.1 implementation of a custom derive. Works on any
+Rust compiler >=1.15.0.
+
+- [`heapsize/src/lib.rs`](heapsize/src/lib.rs)
+- [`heapsize_derive/src/lib.rs`](heapsize_derive/src/lib.rs)
+- [`example/src/main.rs`](example/src/main.rs)
+
+We are deriving the `HeapSize` trait which computes an estimate of the amount of
+heap memory owned by a value.
+
+```rust
+pub trait HeapSize {
+    /// Total number of bytes of heap memory owned by `self`.
+    fn heap_size_of_children(&self) -> usize;
+}
+```
+
+The custom derive allows users to write `#[derive(HeapSize)]` on data structures
+in their program.
+
+```rust
+#[derive(HeapSize)]
+struct Demo<'a, T: ?Sized> {
+    a: Box<T>,
+    b: u8,
+    c: &'a str,
+    d: String,
+}
+```
+
+The trait impl generated by the custom derive here would look like:
+
+```rust
+impl<'a, T: ?Sized + ::heapsize::HeapSize> ::heapsize::HeapSize for Demo<'a, T> {
+    fn heap_size_of_children(&self) -> usize {
+        0 + ::heapsize::HeapSize::heap_size_of_children(&self.a)
+            + ::heapsize::HeapSize::heap_size_of_children(&self.b)
+            + ::heapsize::HeapSize::heap_size_of_children(&self.c)
+            + ::heapsize::HeapSize::heap_size_of_children(&self.d)
+    }
+}
+```
diff --git a/examples/heapsize/example/Cargo.toml b/examples/heapsize/example/Cargo.toml
new file mode 100644
index 0000000..0384d16
--- /dev/null
+++ b/examples/heapsize/example/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "heapsize_example"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[dependencies]
+heapsize = { path = "../heapsize" }
+heapsize_derive = { path = "../heapsize_derive" }
diff --git a/examples/heapsize/example/src/main.rs b/examples/heapsize/example/src/main.rs
new file mode 100644
index 0000000..9c9d88a
--- /dev/null
+++ b/examples/heapsize/example/src/main.rs
@@ -0,0 +1,30 @@
+#[macro_use]
+extern crate heapsize_derive;
+
+extern crate heapsize;
+use heapsize::HeapSize;
+
+#[derive(HeapSize)]
+struct Demo<'a, T: ?Sized> {
+    a: Box<T>,
+    b: u8,
+    c: &'a str,
+    d: String,
+}
+
+fn main() {
+    let demo = Demo {
+        a: b"bytestring".to_vec().into_boxed_slice(),
+        b: 255,
+        c: "&'static str",
+        d: "String".to_owned(),
+    };
+
+    // 10 + 0 + 0 + 6 = 16
+    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());
+}
diff --git a/examples/heapsize/heapsize/Cargo.toml b/examples/heapsize/heapsize/Cargo.toml
new file mode 100644
index 0000000..7f321b5
--- /dev/null
+++ b/examples/heapsize/heapsize/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "heapsize"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[dependencies]
diff --git a/examples/heapsize/heapsize/src/lib.rs b/examples/heapsize/heapsize/src/lib.rs
new file mode 100644
index 0000000..8b4ce03
--- /dev/null
+++ b/examples/heapsize/heapsize/src/lib.rs
@@ -0,0 +1,62 @@
+use std::mem;
+
+pub trait HeapSize {
+    /// Total number of bytes of heap memory owned by `self`.
+    ///
+    /// Does not include the size of `self` itself, which may or may not be on
+    /// the heap. Includes only children of `self`, meaning things pointed to by
+    /// `self`.
+    fn heap_size_of_children(&self) -> usize;
+}
+
+//
+// In a real version of this library there would be lots more impls here, but
+// here are some interesting ones.
+//
+
+impl HeapSize for u8 {
+    /// A `u8` does not own any heap memory.
+    fn heap_size_of_children(&self) -> usize {
+        0
+    }
+}
+
+impl HeapSize for String {
+    /// A `String` owns enough heap memory to hold its reserved capacity.
+    fn heap_size_of_children(&self) -> usize {
+        self.capacity()
+    }
+}
+
+impl<T> HeapSize for Box<T>
+where
+    T: ?Sized + HeapSize,
+{
+    /// A `Box` owns however much heap memory was allocated to hold the value of
+    /// type `T` that we placed on the heap, plus transitively however much `T`
+    /// itself owns.
+    fn heap_size_of_children(&self) -> usize {
+        mem::size_of_val(&**self) + (**self).heap_size_of_children()
+    }
+}
+
+impl<T> HeapSize for [T]
+where
+    T: HeapSize,
+{
+    /// Sum of heap memory owned by each element of a dynamically sized slice of
+    /// `T`.
+    fn heap_size_of_children(&self) -> usize {
+        self.iter().map(HeapSize::heap_size_of_children).sum()
+    }
+}
+
+impl<'a, T> HeapSize for &'a T
+where
+    T: ?Sized,
+{
+    /// A shared reference does not own heap memory.
+    fn heap_size_of_children(&self) -> usize {
+        0
+    }
+}
diff --git a/examples/heapsize/heapsize_derive/Cargo.toml b/examples/heapsize/heapsize_derive/Cargo.toml
new file mode 100644
index 0000000..a71ab0a
--- /dev/null
+++ b/examples/heapsize/heapsize_derive/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "heapsize_derive"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "0.4"
+quote = "0.6"
+syn = { path = "../../.." }
diff --git a/examples/heapsize/heapsize_derive/src/lib.rs b/examples/heapsize/heapsize_derive/src/lib.rs
new file mode 100644
index 0000000..68055e5
--- /dev/null
+++ b/examples/heapsize/heapsize_derive/src/lib.rs
@@ -0,0 +1,88 @@
+extern crate proc_macro;
+extern crate proc_macro2;
+
+#[macro_use]
+extern crate syn;
+
+#[macro_use]
+extern crate quote;
+
+use proc_macro2::TokenStream;
+use syn::{DeriveInput, Data, Fields, Generics, GenericParam};
+
+#[proc_macro_derive(HeapSize)]
+pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    // Parse the input tokens into a syntax tree.
+    let input: DeriveInput = syn::parse(input).unwrap();
+
+    // Used in the quasi-quotation below as `#name`.
+    let name = input.ident;
+
+    // Add a bound `T: HeapSize` to every type parameter T.
+    let generics = add_trait_bounds(input.generics);
+    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+    // Generate an expression to sum up the heap size of each field.
+    let sum = heap_size_sum(&input.data);
+
+    let expanded = quote! {
+        // The generated impl.
+        impl #impl_generics ::heapsize::HeapSize for #name #ty_generics #where_clause {
+            fn heap_size_of_children(&self) -> usize {
+                #sum
+            }
+        }
+    };
+
+    // Hand the output tokens back to the compiler.
+    expanded.into()
+}
+
+// Add a bound `T: HeapSize` to every type parameter T.
+fn add_trait_bounds(mut generics: Generics) -> Generics {
+    for param in &mut generics.params {
+        if let GenericParam::Type(ref mut type_param) = *param {
+            type_param.bounds.push(parse_quote!(::heapsize::HeapSize));
+        }
+    }
+    generics
+}
+
+// Generate an expression to sum up the heap size of each field.
+fn heap_size_sum(data: &Data) -> TokenStream {
+    match *data {
+        Data::Struct(ref data) => {
+            match data.fields {
+                Fields::Named(ref fields) => {
+                    // Expands to an expression like
+                    //
+                    //     0 + self.x.heap_size() + self.y.heap_size() + self.z.heap_size()
+                    //
+                    // but using fully qualified function call syntax.
+                    let fnames = fields.named.iter().map(|f| &f.ident);
+                    quote! {
+                        0 #(
+                            + ::heapsize::HeapSize::heap_size_of_children(&self.#fnames)
+                        )*
+                    }
+                }
+                Fields::Unnamed(ref fields) => {
+                    // Expands to an expression like
+                    //
+                    //     0 + self.0.heap_size() + self.1.heap_size() + self.2.heap_size()
+                    let indices = 0..fields.unnamed.len();
+                    quote! {
+                        0 #(
+                            + ::heapsize::HeapSize::heap_size_of_children(&self.#indices)
+                        )*
+                    }
+                }
+                Fields::Unit => {
+                    // Unit structs cannot own more than 0 bytes of heap memory.
+                    quote!(0)
+                }
+            }
+        }
+        Data::Enum(_) | Data::Union(_) => unimplemented!(),
+    }
+}
diff --git a/examples/heapsize2/README.md b/examples/heapsize2/README.md
new file mode 100644
index 0000000..3d232e7
--- /dev/null
+++ b/examples/heapsize2/README.md
@@ -0,0 +1,61 @@
+A complete working custom derive that illustrates the hygiene properties of
+Macros 2.0. Currently requires a nightly Rust compiler >=1.24.0-nightly but we
+are working to stabilize all of the APIs used here.
+
+This is the same example as the unhygienic stable [`heapsize`](../heapsize)
+example. Please read that other example first before diving into this one, as
+the comments here assume an understanding of how the other one works.
+
+- [`heapsize/src/lib.rs`](heapsize/src/lib.rs) (unchanged)
+- [`heapsize_derive/src/lib.rs`](heapsize_derive/src/lib.rs)
+- [`example/src/main.rs`](example/src/main.rs)
+
+A major advantage of spans and the token-based procedural macro API is that we
+get great control over where the compiler's error messages are displayed.
+Consider the error the user sees if one of their field types does not implement
+`HeapSize`.
+
+```rust
+#[derive(HeapSize)]
+struct Broken {
+    ok: String,
+    bad: std::thread::Thread,
+}
+```
+
+The Macros 1.1 string-based procedural macro and a naively implemented
+token-based procedural macro result in the following error.
+
+```
+error[E0599]: no method named `heap_size_of_children` found for type `std::thread::Thread` in the current scope
+ --> src/main.rs:4:10
+  |
+4 | #[derive(HeapSize)]
+  |          ^^^^^^^^
+```
+
+With just a bit of work, as shown in the `heapsize_derive` implementation here,
+we can improve this error to point out exactly which field is not right.
+
+```
+error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
+ --> src/main.rs:7:5
+  |
+7 |     bad: std::thread::Thread,
+  |     ^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
+```
+
+Some unstable APIs in the `proc-macro2` crate let us improve this further by
+joining together the span of the field name and the field type. There is no
+difference in our code -- everything is as shown in this directory -- but
+building the example crate with `cargo build` shows errors like the one above
+and building with `RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build` is
+able to show errors like the following.
+
+```
+error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
+ --> src/main.rs:7:5
+  |
+7 |     bad: std::thread::Thread,
+  |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread`
+```
diff --git a/examples/heapsize2/example/Cargo.toml b/examples/heapsize2/example/Cargo.toml
new file mode 100644
index 0000000..0384d16
--- /dev/null
+++ b/examples/heapsize2/example/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "heapsize_example"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[dependencies]
+heapsize = { path = "../heapsize" }
+heapsize_derive = { path = "../heapsize_derive" }
diff --git a/examples/heapsize2/example/src/main.rs b/examples/heapsize2/example/src/main.rs
new file mode 100644
index 0000000..1c66692
--- /dev/null
+++ b/examples/heapsize2/example/src/main.rs
@@ -0,0 +1,29 @@
+#[macro_use]
+extern crate heapsize_derive;
+
+extern crate heapsize;
+
+#[derive(HeapSize)]
+struct Demo<'a, T: ?Sized> {
+    a: Box<T>,
+    b: u8,
+    c: &'a str,
+    d: HeapSize,
+}
+
+#[derive(HeapSize)]
+struct HeapSize {
+    e: String,
+}
+
+fn main() {
+    let demo = Demo {
+        a: b"bytestring".to_vec().into_boxed_slice(),
+        b: 255,
+        c: "&'static str",
+        d: HeapSize {
+            e: "String".to_owned(),
+        },
+    };
+    println!("heap size = {}", heapsize::HeapSize::heap_size_of_children(&demo));
+}
diff --git a/examples/heapsize2/heapsize/Cargo.toml b/examples/heapsize2/heapsize/Cargo.toml
new file mode 100644
index 0000000..7f321b5
--- /dev/null
+++ b/examples/heapsize2/heapsize/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "heapsize"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[dependencies]
diff --git a/examples/heapsize2/heapsize/src/lib.rs b/examples/heapsize2/heapsize/src/lib.rs
new file mode 100644
index 0000000..8b4ce03
--- /dev/null
+++ b/examples/heapsize2/heapsize/src/lib.rs
@@ -0,0 +1,62 @@
+use std::mem;
+
+pub trait HeapSize {
+    /// Total number of bytes of heap memory owned by `self`.
+    ///
+    /// Does not include the size of `self` itself, which may or may not be on
+    /// the heap. Includes only children of `self`, meaning things pointed to by
+    /// `self`.
+    fn heap_size_of_children(&self) -> usize;
+}
+
+//
+// In a real version of this library there would be lots more impls here, but
+// here are some interesting ones.
+//
+
+impl HeapSize for u8 {
+    /// A `u8` does not own any heap memory.
+    fn heap_size_of_children(&self) -> usize {
+        0
+    }
+}
+
+impl HeapSize for String {
+    /// A `String` owns enough heap memory to hold its reserved capacity.
+    fn heap_size_of_children(&self) -> usize {
+        self.capacity()
+    }
+}
+
+impl<T> HeapSize for Box<T>
+where
+    T: ?Sized + HeapSize,
+{
+    /// A `Box` owns however much heap memory was allocated to hold the value of
+    /// type `T` that we placed on the heap, plus transitively however much `T`
+    /// itself owns.
+    fn heap_size_of_children(&self) -> usize {
+        mem::size_of_val(&**self) + (**self).heap_size_of_children()
+    }
+}
+
+impl<T> HeapSize for [T]
+where
+    T: HeapSize,
+{
+    /// Sum of heap memory owned by each element of a dynamically sized slice of
+    /// `T`.
+    fn heap_size_of_children(&self) -> usize {
+        self.iter().map(HeapSize::heap_size_of_children).sum()
+    }
+}
+
+impl<'a, T> HeapSize for &'a T
+where
+    T: ?Sized,
+{
+    /// A shared reference does not own heap memory.
+    fn heap_size_of_children(&self) -> usize {
+        0
+    }
+}
diff --git a/examples/heapsize2/heapsize_derive/Cargo.toml b/examples/heapsize2/heapsize_derive/Cargo.toml
new file mode 100644
index 0000000..9dd7af7
--- /dev/null
+++ b/examples/heapsize2/heapsize_derive/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "heapsize_derive"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = { path = "../../.." }
+quote = "0.6"
+proc-macro2 = { version = "0.4", features = ["nightly"] }
diff --git a/examples/heapsize2/heapsize_derive/src/lib.rs b/examples/heapsize2/heapsize_derive/src/lib.rs
new file mode 100644
index 0000000..87bb60e
--- /dev/null
+++ b/examples/heapsize2/heapsize_derive/src/lib.rs
@@ -0,0 +1,105 @@
+extern crate proc_macro;
+extern crate proc_macro2;
+
+#[macro_use]
+extern crate syn;
+
+#[macro_use]
+extern crate quote;
+
+use proc_macro2::{Span, TokenStream};
+use syn::{DeriveInput, Data, Fields, Generics, GenericParam, Index};
+use syn::spanned::Spanned;
+
+#[proc_macro_derive(HeapSize)]
+pub fn derive_heap_size(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    // Parse the input tokens into a syntax tree.
+    let input: DeriveInput = syn::parse(input).unwrap();
+
+    // Used in the quasi-quotation below as `#name`.
+    let name = input.ident;
+
+    // Add a bound `T: HeapSize` to every type parameter T.
+    let generics = add_trait_bounds(input.generics);
+    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+    // Generate an expression to sum up the heap size of each field.
+    let var = quote!(self);
+    let sum = heap_size_sum(&input.data, &var);
+
+    let expanded = quote! {
+        // The generated impl.
+        impl #impl_generics ::heapsize::HeapSize for #name #ty_generics #where_clause {
+            fn heap_size_of_children(&#var) -> usize {
+                #sum
+            }
+        }
+    };
+
+    // Hand the output tokens back to the compiler.
+    expanded.into()
+}
+
+// Add a bound `T: HeapSize` to every type parameter T.
+fn add_trait_bounds(mut generics: Generics) -> Generics {
+    for param in &mut generics.params {
+        if let GenericParam::Type(ref mut type_param) = *param {
+            type_param.bounds.push(parse_quote!(::heapsize::HeapSize));
+        }
+    }
+    generics
+}
+
+// Generate an expression to sum up the heap size of each field.
+fn heap_size_sum(data: &Data, var: &TokenStream) -> TokenStream {
+    let call_site = Span::call_site();
+
+    match *data {
+        Data::Struct(ref data) => {
+            match data.fields {
+                Fields::Named(ref fields) => {
+                    // Expands to an expression like
+                    //
+                    //     0 + HeapSize::heap_size(&self.x) + HeapSize::heap_size(&self.y)
+                    //
+                    // We take some care to use the span of each `syn::Field` as
+                    // the span of the corresponding `heap_size_of_children`
+                    // call. This way if one of the field types does not
+                    // implement `HeapSize` then the compiler's error message
+                    // underlines which field it is. An example is shown in the
+                    // readme of the parent directory.
+                    let recurse = fields.named.iter().map(|f| {
+                        let name = &f.ident;
+                        let access = quote_spanned!(call_site=> #var.#name);
+                        quote_spanned! {f.span()=>
+                            ::heapsize::HeapSize::heap_size_of_children(&#access)
+                        }
+                    });
+                    quote! {
+                        0 #(+ #recurse)*
+                    }
+                }
+                Fields::Unnamed(ref fields) => {
+                    // This expands to an expression like
+                    //
+                    //     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 access = quote_spanned!(call_site=> #var.#index);
+                        quote_spanned! {f.span()=>
+                            ::heapsize::HeapSize::heap_size_of_children(&#access)
+                        }
+                    });
+                    quote! {
+                        0 #(+ #recurse)*
+                    }
+                }
+                Fields::Unit => {
+                    // Unit structs cannot own more than 0 bytes of heap memory.
+                    quote!(0)
+                }
+            }
+        }
+        Data::Enum(_) | Data::Union(_) => unimplemented!(),
+    }
+}
diff --git a/examples/lazy-static/README.md b/examples/lazy-static/README.md
new file mode 100644
index 0000000..bc64585
--- /dev/null
+++ b/examples/lazy-static/README.md
@@ -0,0 +1,42 @@
+An example of parsing a custom syntax within a `functionlike!(...)` procedural
+macro. Demonstrates how to trigger custom warnings and error messages on
+individual tokens of the input.
+
+- [`lazy-static/src/lib.rs`](lazy-static/src/lib.rs)
+- [`example/src/main.rs`](example/src/main.rs)
+
+The library implements a `lazy_static!` macro similar to the one from the real
+[`lazy_static`](https://docs.rs/lazy_static/1.0.0/lazy_static/) crate on
+crates.io.
+
+```rust
+lazy_static! {
+    static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
+}
+```
+
+Compile and run the example by doing `cargo run` in the directory of the
+`example` crate.
+
+The implementation shows how to trigger custom warnings and error messages on
+the macro input. For example if you try adding an uncreatively named `FOO` lazy
+static, the macro will scold you with the following warning.
+
+```
+warning: come on, pick a more creative name
+  --> src/main.rs:10:16
+   |
+10 |     static ref FOO: String = "lazy_static".to_owned();
+   |                ^^^
+```
+
+And if you try to lazily initialize `() = ()`, the macro will outright refuse to
+compile it for you.
+
+```
+error: I can't think of a legitimate use for lazily initializing the value `()`
+  --> src/main.rs:10:27
+   |
+10 |     static ref UNIT: () = ();
+   |                           ^^
+```
diff --git a/examples/lazy-static/example/Cargo.toml b/examples/lazy-static/example/Cargo.toml
new file mode 100644
index 0000000..d5d40c5
--- /dev/null
+++ b/examples/lazy-static/example/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "example"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[dependencies]
+lazy_static = { path = "../lazy-static" }
+regex = "0.2"
diff --git a/examples/lazy-static/example/src/main.rs b/examples/lazy-static/example/src/main.rs
new file mode 100644
index 0000000..16cfb36
--- /dev/null
+++ b/examples/lazy-static/example/src/main.rs
@@ -0,0 +1,25 @@
+#![feature(proc_macro)]
+
+extern crate lazy_static;
+extern crate regex;
+
+use lazy_static::lazy_static;
+use regex::Regex;
+
+lazy_static! {
+    static ref USERNAME: Regex = {
+        println!("Compiling username regex...");
+        Regex::new("^[a-z0-9_-]{3,16}$").unwrap()
+    };
+}
+
+fn main() {
+    println!("Let's validate some usernames.");
+    validate("fergie");
+    validate("will.i.am");
+}
+
+fn validate(name: &str) {
+    // The USERNAME regex is compiled lazily the first time its value is accessed.
+    println!("is_match({:?}): {}", name, USERNAME.is_match(name));
+}
diff --git a/examples/lazy-static/lazy-static/Cargo.toml b/examples/lazy-static/lazy-static/Cargo.toml
new file mode 100644
index 0000000..d5c8e3c
--- /dev/null
+++ b/examples/lazy-static/lazy-static/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "lazy_static"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = { path = "../../../", features = ["full"] }
+quote = "0.6"
+proc-macro2 = { version = "0.4", features = ["nightly"] }
diff --git a/examples/lazy-static/lazy-static/src/lib.rs b/examples/lazy-static/lazy-static/src/lib.rs
new file mode 100644
index 0000000..4d4131f
--- /dev/null
+++ b/examples/lazy-static/lazy-static/src/lib.rs
@@ -0,0 +1,134 @@
+#![recursion_limit = "128"]
+#![feature(proc_macro)]
+
+#[macro_use]
+extern crate syn;
+#[macro_use]
+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;
+
+/// Parses the following syntax, which aligns with the input of the real
+/// `lazy_static` crate.
+///
+///     lazy_static! {
+///         $VISIBILITY static ref $NAME: $TYPE = $EXPR;
+///     }
+///
+/// For example:
+///
+///     lazy_static! {
+///         static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
+///     }
+struct LazyStatic {
+    visibility: Visibility,
+    name: Ident,
+    ty: Type,
+    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 })
+    ));
+}
+
+#[proc_macro]
+pub fn lazy_static(input: TokenStream) -> TokenStream {
+    let LazyStatic { visibility, name, ty, init } = syn::parse(input).unwrap();
+
+    // The warning looks like this.
+    //
+    //     warning: come on, pick a more creative name
+    //       --> src/main.rs:10:16
+    //        |
+    //     10 |     static ref FOO: String = "lazy_static".to_owned();
+    //        |                ^^^
+    if name == "FOO" {
+        name.span().unstable()
+            .warning("come on, pick a more creative name")
+            .emit();
+    }
+
+    // The error looks like this.
+    //
+    //     error: I can't think of a legitimate use for lazily initializing the value `()`
+    //       --> src/main.rs:10:27
+    //        |
+    //     10 |     static ref UNIT: () = ();
+    //        |                           ^^
+    if let Expr::Tuple(ref init) = init {
+        if init.elems.is_empty() {
+            init.span().unstable()
+                .error("I can't think of a legitimate use for lazily initializing the value `()`")
+                .emit();
+            return TokenStream::new();
+        }
+    }
+
+    // Assert that the static type implements Sync. If not, user sees an error
+    // message like the following. We span this assertion with the field type's
+    // line/column so that the error message appears in the correct place.
+    //
+    //     error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
+    //       --> src/main.rs:10:21
+    //        |
+    //     10 |     static ref PTR: *const () = &();
+    //        |                     ^^^^^^^^^ `*const ()` cannot be shared between threads safely
+    let assert_sync = quote_spanned! {ty.span()=>
+        struct _AssertSync where #ty: ::std::marker::Sync;
+    };
+
+    // Check for Sized. Not vital to check here, but the error message is less
+    // confusing this way than if they get a Sized error in one of our
+    // implementation details where it assumes Sized.
+    //
+    //     error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+    //       --> src/main.rs:10:19
+    //        |
+    //     10 |     static ref A: str = "";
+    //        |                   ^^^ `str` does not have a constant size known at compile-time
+    let assert_sized = quote_spanned! {ty.span()=>
+        struct _AssertSized where #ty: ::std::marker::Sized;
+    };
+
+    let init_ptr = quote_spanned! {init.span()=>
+        Box::into_raw(Box::new(#init))
+    };
+
+    let expanded = quote! {
+        #visibility struct #name;
+
+        impl ::std::ops::Deref for #name {
+            type Target = #ty;
+
+            fn deref(&self) -> &#ty {
+                #assert_sync
+                #assert_sized
+
+                static ONCE: ::std::sync::Once = ::std::sync::ONCE_INIT;
+                static mut VALUE: *mut #ty = 0 as *mut #ty;
+
+                unsafe {
+                    ONCE.call_once(|| VALUE = #init_ptr);
+                    &*VALUE
+                }
+            }
+        }
+    };
+
+    expanded.into()
+}
diff --git a/examples/trace-var/README.md b/examples/trace-var/README.md
new file mode 100644
index 0000000..45eace7
--- /dev/null
+++ b/examples/trace-var/README.md
@@ -0,0 +1,61 @@
+An example of an attribute procedural macro. The `#[trace_var(...)]` attribute
+prints the value of the given variables each time they are reassigned.
+
+- [`trace-var/src/lib.rs`](trace-var/src/lib.rs)
+- [`example/src/main.rs`](example/src/main.rs)
+
+Consider the following factorial implementation.
+
+```rust
+#[trace_var(p, n)]
+fn factorial(mut n: u64) -> u64 {
+    let mut p = 1;
+    while n > 1 {
+        p *= n;
+        n -= 1;
+    }
+    p
+}
+```
+
+Invoking this with `factorial(8)` prints all the values of `p` and `n` during
+the execution of the function.
+
+```
+p = 1
+p = 8
+n = 7
+p = 56
+n = 6
+p = 336
+n = 5
+p = 1680
+n = 4
+p = 6720
+n = 3
+p = 20160
+n = 2
+p = 40320
+n = 1
+```
+
+The procedural macro uses a syntax tree [`Fold`] to rewrite every `let`
+statement and assignment expression in the following way:
+
+[`Fold`]: https://docs.rs/syn/0.14/syn/fold/trait.Fold.html
+
+```rust
+// Before
+let VAR = INIT;
+
+// After
+let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR };
+```
+
+```rust
+// Before
+VAR = INIT
+
+// After
+{ VAR = INIT; println!("VAR = {:?}", VAR); }
+```
diff --git a/examples/trace-var/example/Cargo.toml b/examples/trace-var/example/Cargo.toml
new file mode 100644
index 0000000..8c2d99d
--- /dev/null
+++ b/examples/trace-var/example/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "example"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[dependencies]
+trace-var = { path = "../trace-var" }
diff --git a/examples/trace-var/example/src/main.rs b/examples/trace-var/example/src/main.rs
new file mode 100644
index 0000000..c9371f3
--- /dev/null
+++ b/examples/trace-var/example/src/main.rs
@@ -0,0 +1,18 @@
+#![feature(proc_macro)]
+
+extern crate trace_var;
+use trace_var::trace_var;
+
+fn main() {
+    println!("{}", factorial(8));
+}
+
+#[trace_var(p, n)]
+fn factorial(mut n: u64) -> u64 {
+    let mut p = 1;
+    while n > 1 {
+        p *= n;
+        n -= 1;
+    }
+    p
+}
diff --git a/examples/trace-var/trace-var/Cargo.toml b/examples/trace-var/trace-var/Cargo.toml
new file mode 100644
index 0000000..4a14bd1
--- /dev/null
+++ b/examples/trace-var/trace-var/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "trace-var"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+publish = false
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = { path = "../../../", features = ["full", "fold"] }
+quote = "0.6"
+proc-macro2 = { version = "0.4", features = ["nightly"] }
diff --git a/examples/trace-var/trace-var/src/lib.rs b/examples/trace-var/trace-var/src/lib.rs
new file mode 100644
index 0000000..5fb6ccf
--- /dev/null
+++ b/examples/trace-var/trace-var/src/lib.rs
@@ -0,0 +1,198 @@
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+#[macro_use]
+extern crate syn;
+
+#[macro_use]
+extern crate quote;
+
+use proc_macro::TokenStream;
+use quote::ToTokens;
+use std::collections::HashSet as Set;
+use syn::fold::{self, Fold};
+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.
+///
+///     (a, b, c)
+///
+/// This is how the compiler passes in arguments to our attribute -- it is
+/// everything that comes 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 {
+            vars: vars.into_iter().collect(),
+        }
+    ));
+}
+
+impl Args {
+    /// Determines whether the given `Expr` is a path referring to one of the
+    /// variables we intend to print. Expressions are used as the left-hand side
+    /// of the assignment operator.
+    fn should_print_expr(&self, e: &Expr) -> bool {
+        match *e {
+            Expr::Path(ref e) => {
+                if e.path.leading_colon.is_some() {
+                    false
+                } else if e.path.segments.len() != 1 {
+                    false
+                } else {
+                    let first = e.path.segments.first().unwrap();
+                    let segment = first.value();
+                    self.vars.contains(&segment.ident) && segment.arguments.is_empty()
+                }
+            }
+            _ => false,
+        }
+    }
+
+    /// Determines whether the given `Pat` is an identifier equal to one of the
+    /// variables we intend to print. Patterns are used as the left-hand side of
+    /// a `let` binding.
+    fn should_print_pat(&self, p: &Punctuated<Pat, Token![|]>) -> bool {
+        if p.len() != 1 {
+            return false;
+        }
+        match p[0] {
+            Pat::Ident(ref p) => self.vars.contains(&p.ident),
+            _ => false,
+        }
+    }
+
+    /// Produces an expression that assigns the right-hand side to the left-hand
+    /// side and then prints the value.
+    ///
+    ///     // Before
+    ///     VAR = INIT
+    ///
+    ///     // After
+    ///     { VAR = INIT; println!("VAR = {:?}", VAR); }
+    fn assign_and_print(&mut self, left: Expr, op: &ToTokens, right: Expr) -> Expr {
+        let right = fold::fold_expr(self, right);
+        parse_quote!({
+            #left #op #right;
+            println!(concat!(stringify!(#left), " = {:?}"), #left);
+        })
+    }
+
+    /// Produces a let-binding that assigns the right-hand side to the left-hand
+    /// side and then prints the value.
+    ///
+    ///     // Before
+    ///     let VAR = INIT;
+    ///
+    ///     // After
+    ///     let VAR = { let VAR = INIT; println!("VAR = {:?}", VAR); VAR };
+    fn let_and_print(&mut self, local: Local) -> Stmt {
+        let Local { pats, ty, init, .. } = local;
+        let pat = &pats[0];
+        let ty = ty.map(|(colon_token, ty)| quote!(#colon_token #ty));
+        let init = self.fold_expr(*init.unwrap().1);
+        let ident = match *pat {
+            Pat::Ident(ref p) => &p.ident,
+            _ => unreachable!(),
+        };
+        parse_quote! {
+            let #pat #ty = {
+                let #pat = #init;
+                println!(concat!(stringify!(#ident), " = {:?}"), #ident);
+                #ident
+            };
+        }
+    }
+}
+
+/// The `Fold` trait is a way to traverse an owned syntax tree and replace some
+/// of its nodes.
+///
+/// Syn provides two other syntax tree traversal traits: `Visit` which walks a
+/// shared borrow of a syntax tree, and `VisitMut` which walks an exclusive
+/// borrow of a syntax tree and can mutate it in place.
+///
+/// All three traits have a method corresponding to each type of node in Syn's
+/// syntax tree. All of these methods have default no-op implementations that
+/// simply recurse on any child nodes. We can override only those methods for
+/// which we want non-default behavior. In this case the traversal needs to
+/// transform `Expr` and `Stmt` nodes.
+impl Fold for Args {
+    fn fold_expr(&mut self, e: Expr) -> Expr {
+        match e {
+            Expr::Assign(e) => {
+                if self.should_print_expr(&e.left) {
+                    self.assign_and_print(*e.left, &e.eq_token, *e.right)
+                } else {
+                    Expr::Assign(fold::fold_expr_assign(self, e))
+                }
+            }
+            Expr::AssignOp(e) => {
+                if self.should_print_expr(&e.left) {
+                    self.assign_and_print(*e.left, &e.op, *e.right)
+                } else {
+                    Expr::AssignOp(fold::fold_expr_assign_op(self, e))
+                }
+            }
+            _ => fold::fold_expr(self, e),
+        }
+    }
+
+    fn fold_stmt(&mut self, s: Stmt) -> Stmt {
+        match s {
+            Stmt::Local(s) => {
+                if s.init.is_some() && self.should_print_pat(&s.pats) {
+                    self.let_and_print(s)
+                } else {
+                    Stmt::Local(fold::fold_local(self, s))
+                }
+            }
+            _ => fold::fold_stmt(self, s),
+        }
+    }
+}
+
+/// Attribute to print the value of the given variables each time they are
+/// reassigned.
+///
+/// # Example
+///
+/// ```
+/// #[trace_var(p, n)]
+/// fn factorial(mut n: u64) -> u64 {
+///     let mut p = 1;
+///     while n > 1 {
+///         p *= n;
+///         n -= 1;
+///     }
+///     p
+/// }
+/// ```
+#[proc_macro_attribute]
+pub fn trace_var(args: TokenStream, input: TokenStream) -> TokenStream {
+    // Return the input unchanged if it failed to parse. The compiler will show
+    // the right diagnostics.
+    let input: ItemFn = match syn::parse(input.clone()) {
+        Ok(input) => input,
+        Err(_) => return input,
+    };
+
+    // Parse the list of variables the user wanted to print.
+    let mut args: Args = syn::parse(args).unwrap();
+
+    // Use a syntax tree traversal to transform the function body.
+    let output = args.fold_item_fn(input);
+
+    // Hand the resulting function body back to the compiler.
+    quote!(#output).into()
+}
diff --git a/src/attr.rs b/src/attr.rs
new file mode 100644
index 0000000..83ad8d7
--- /dev/null
+++ b/src/attr.rs
@@ -0,0 +1,547 @@
+// 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 super::*;
+use punctuated::Punctuated;
+
+use std::iter;
+
+use proc_macro2::{Delimiter, Spacing, TokenStream, TokenTree};
+
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+#[cfg(feature = "extra-traits")]
+use tt::TokenStreamHelper;
+
+ast_struct! {
+    /// An attribute like `#[repr(transparent)]`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax
+    ///
+    /// Rust has six types of attributes.
+    ///
+    /// - Outer attributes like `#[repr(transparent)]`. These appear outside or
+    ///   in front of the item they describe.
+    /// - Inner attributes like `#![feature(proc_macro)]`. These appear inside
+    ///   of the item they describe, usually a module.
+    /// - Outer doc comments like `/// # Example`.
+    /// - Inner doc comments like `//! Please file an issue`.
+    /// - Outer block comments `/** # Example */`.
+    /// - Inner block comments `/*! Please file an issue */`.
+    ///
+    /// The `style` field of type `AttrStyle` distinguishes whether an attribute
+    /// is outer or inner. Doc comments and block comments are promoted to
+    /// 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
+    /// comments. The `tts` field contains the rest of the attribute body as
+    /// tokens.
+    ///
+    /// ```text
+    /// #[derive(Copy)]      #[crate::precondition x < 5]
+    ///   ^^^^^^~~~~~~         ^^^^^^^^^^^^^^^^^^^ ~~~~~
+    ///    path  tts                   path         tts
+    /// ```
+    ///
+    /// Use the [`interpret_meta`] method to try parsing the tokens of an
+    /// attribute into the structured representation that is used by convention
+    /// across most Rust libraries.
+    ///
+    /// [`interpret_meta`]: #method.interpret_meta
+    pub struct Attribute #manual_extra_traits {
+        pub pound_token: Token![#],
+        pub style: AttrStyle,
+        pub bracket_token: token::Bracket,
+        pub path: Path,
+        pub tts: TokenStream,
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for Attribute {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for Attribute {
+    fn eq(&self, other: &Self) -> bool {
+        self.style == other.style
+            && self.pound_token == other.pound_token
+            && self.bracket_token == other.bracket_token
+            && self.path == other.path
+            && TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for Attribute {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        self.style.hash(state);
+        self.pound_token.hash(state);
+        self.bracket_token.hash(state);
+        self.path.hash(state);
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+impl Attribute {
+    /// Parses the tokens after the path as a [`Meta`](enum.Meta.html) if
+    /// possible.
+    pub fn interpret_meta(&self) -> Option<Meta> {
+        let name = if self.path.segments.len() == 1 {
+            &self.path.segments.first().unwrap().value().ident
+        } else {
+            return None;
+        };
+
+        if self.tts.is_empty() {
+            return Some(Meta::Word(name.clone()));
+        }
+
+        let tts = self.tts.clone().into_iter().collect::<Vec<_>>();
+
+        if tts.len() == 1 {
+            if let Some(meta) = Attribute::extract_meta_list(name.clone(), &tts[0]) {
+                return Some(meta);
+            }
+        }
+
+        if tts.len() == 2 {
+            if let Some(meta) = Attribute::extract_name_value(name.clone(), &tts[0], &tts[1]) {
+                return Some(meta);
+            }
+        }
+
+        None
+    }
+
+    fn extract_meta_list(ident: Ident, tt: &TokenTree) -> Option<Meta> {
+        let g = match *tt {
+            TokenTree::Group(ref g) => g,
+            _ => return None,
+        };
+        if g.delimiter() != Delimiter::Parenthesis {
+            return None;
+        }
+        let tokens = g.stream().clone().into_iter().collect::<Vec<_>>();
+        let nested = match list_of_nested_meta_items_from_tokens(&tokens) {
+            Some(n) => n,
+            None => return None,
+        };
+        Some(Meta::List(MetaList {
+            paren_token: token::Paren(g.span()),
+            ident: ident,
+            nested: nested,
+        }))
+    }
+
+    fn extract_name_value(ident: Ident, a: &TokenTree, b: &TokenTree) -> Option<Meta> {
+        let a = match *a {
+            TokenTree::Punct(ref o) => o,
+            _ => return None,
+        };
+        if a.spacing() != Spacing::Alone {
+            return None;
+        }
+        if a.as_char() != '=' {
+            return None;
+        }
+
+        match *b {
+            TokenTree::Literal(ref l) if !l.to_string().starts_with('/') => {
+                Some(Meta::NameValue(MetaNameValue {
+                    ident: ident,
+                    eq_token: Token![=]([a.span()]),
+                    lit: Lit::new(l.clone()),
+                }))
+            }
+            TokenTree::Ident(ref v) => match &v.to_string()[..] {
+                v @ "true" | v @ "false" => Some(Meta::NameValue(MetaNameValue {
+                    ident: ident,
+                    eq_token: Token![=]([a.span()]),
+                    lit: Lit::Bool(LitBool {
+                        value: v == "true",
+                        span: b.span(),
+                    }),
+                })),
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+}
+
+fn nested_meta_item_from_tokens(tts: &[TokenTree]) -> Option<(NestedMeta, &[TokenTree])> {
+    assert!(!tts.is_empty());
+
+    match tts[0] {
+        TokenTree::Literal(ref lit) => {
+            if lit.to_string().starts_with('/') {
+                None
+            } else {
+                let lit = Lit::new(lit.clone());
+                Some((NestedMeta::Literal(lit), &tts[1..]))
+            }
+        }
+
+        TokenTree::Ident(ref ident) => {
+            if tts.len() >= 3 {
+                if let Some(meta) = Attribute::extract_name_value(ident.clone(), &tts[1], &tts[2]) {
+                    return Some((NestedMeta::Meta(meta), &tts[3..]));
+                }
+            }
+
+            if tts.len() >= 2 {
+                if let Some(meta) = Attribute::extract_meta_list(ident.clone(), &tts[1]) {
+                    return Some((NestedMeta::Meta(meta), &tts[2..]));
+                }
+            }
+
+            Some((Meta::Word(ident.clone()).into(), &tts[1..]))
+        }
+
+        _ => None,
+    }
+}
+
+fn list_of_nested_meta_items_from_tokens(
+    mut tts: &[TokenTree],
+) -> Option<Punctuated<NestedMeta, Token![,]>> {
+    let mut nested_meta_items = Punctuated::new();
+    let mut first = true;
+
+    while !tts.is_empty() {
+        let prev_comma = if first {
+            first = false;
+            None
+        } else if let TokenTree::Punct(ref op) = tts[0] {
+            if op.spacing() != Spacing::Alone {
+                return None;
+            }
+            if op.as_char() != ',' {
+                return None;
+            }
+            let tok = Token![,]([op.span()]);
+            tts = &tts[1..];
+            if tts.is_empty() {
+                break;
+            }
+            Some(tok)
+        } else {
+            return None;
+        };
+        let (nested, rest) = match nested_meta_item_from_tokens(tts) {
+            Some(pair) => pair,
+            None => return None,
+        };
+        if let Some(comma) = prev_comma {
+            nested_meta_items.push_punct(comma);
+        }
+        nested_meta_items.push_value(nested);
+        tts = rest;
+    }
+
+    Some(nested_meta_items)
+}
+
+ast_enum! {
+    /// Distinguishes between attributes that decorate an item and attributes
+    /// that are contained within an item.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Outer attributes
+    ///
+    /// - `#[repr(transparent)]`
+    /// - `/// # Example`
+    /// - `/** Please file an issue */`
+    ///
+    /// # Inner attributes
+    ///
+    /// - `#![feature(proc_macro)]`
+    /// - `//! # Example`
+    /// - `/*! Please file an issue */`
+    #[cfg_attr(feature = "clone-impls", derive(Copy))]
+    pub enum AttrStyle {
+        Outer,
+        Inner(Token![!]),
+    }
+}
+
+ast_enum_of_structs! {
+    /// Content of a compile-time structured attribute.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// ## Word
+    ///
+    /// A meta word is like the `test` in `#[test]`.
+    ///
+    /// ## List
+    ///
+    /// A meta list is like the `derive(Copy)` in `#[derive(Copy)]`.
+    ///
+    /// ## NameValue
+    ///
+    /// A name-value meta is like the `path = "..."` in `#[path =
+    /// "sys/windows.rs"]`.
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum Meta {
+        pub Word(Ident),
+        /// A structured list within an attribute, like `derive(Copy, Clone)`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub List(MetaList {
+            pub ident: Ident,
+            pub paren_token: token::Paren,
+            pub nested: Punctuated<NestedMeta, Token![,]>,
+        }),
+        /// A name-value pair within an attribute, like `feature = "nightly"`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub NameValue(MetaNameValue {
+            pub ident: Ident,
+            pub eq_token: Token![=],
+            pub lit: Lit,
+        }),
+    }
+}
+
+impl Meta {
+    /// Returns the identifier that begins this structured meta item.
+    ///
+    /// For example this would return the `test` in `#[test]`, the `derive` in
+    /// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`.
+    pub fn name(&self) -> Ident {
+        match *self {
+            Meta::Word(ref meta) => meta.clone(),
+            Meta::List(ref meta) => meta.ident.clone(),
+            Meta::NameValue(ref meta) => meta.ident.clone(),
+        }
+    }
+}
+
+ast_enum_of_structs! {
+    /// Element of a compile-time attribute list.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum NestedMeta {
+        /// A structured meta item, like the `Copy` in `#[derive(Copy)]` which
+        /// would be a nested `Meta::Word`.
+        pub Meta(Meta),
+
+        /// A Rust literal, like the `"new_name"` in `#[rename("new_name")]`.
+        pub Literal(Lit),
+    }
+}
+
+pub trait FilterAttrs<'a> {
+    type Ret: Iterator<Item = &'a Attribute>;
+
+    fn outer(self) -> Self::Ret;
+    fn inner(self) -> Self::Ret;
+}
+
+impl<'a, T> FilterAttrs<'a> for T
+where
+    T: IntoIterator<Item = &'a Attribute>,
+{
+    type Ret = iter::Filter<T::IntoIter, fn(&&Attribute) -> bool>;
+
+    fn outer(self) -> Self::Ret {
+        fn is_outer(attr: &&Attribute) -> bool {
+            match attr.style {
+                AttrStyle::Outer => true,
+                _ => false,
+            }
+        }
+        self.into_iter().filter(is_outer)
+    }
+
+    fn inner(self) -> Self::Ret {
+        fn is_inner(attr: &&Attribute) -> bool {
+            match attr.style {
+                AttrStyle::Inner(_) => true,
+                _ => false,
+            }
+        }
+        self.into_iter().filter(is_inner)
+    }
+}
+
+#[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()
+    }
+
+    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,
+                        pound_token: pound,
+                        bracket_token: bracket,
+                    }
+                })
+            )
+            |
+            map!(
+                call!(lit_doc_comment, Comment::Inner),
+                |lit| {
+                    let span = lit.span();
+                    Attribute {
+                        style: AttrStyle::Inner(Token![!](span)),
+                        path: Ident::new("doc", span).into(),
+                        tts: vec![
+                            eq(span),
+                            lit,
+                        ].into_iter().collect(),
+                        pound_token: Token![#](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,
+                        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(),
+                        pound_token: Token![#](span),
+                        bracket_token: token::Bracket(span),
+                    }
+                }
+            )
+        ));
+    }
+
+    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 = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::ToTokens;
+
+    impl ToTokens for Attribute {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.pound_token.to_tokens(tokens);
+            if let AttrStyle::Inner(ref b) = self.style {
+                b.to_tokens(tokens);
+            }
+            self.bracket_token.surround(tokens, |tokens| {
+                self.path.to_tokens(tokens);
+                self.tts.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for MetaList {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                self.nested.to_tokens(tokens);
+            })
+        }
+    }
+
+    impl ToTokens for MetaNameValue {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.lit.to_tokens(tokens);
+        }
+    }
+}
diff --git a/src/buffer.rs b/src/buffer.rs
new file mode 100644
index 0000000..499c4f1
--- /dev/null
+++ b/src/buffer.rs
@@ -0,0 +1,469 @@
+// 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.
+
+//! 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
+// 100% safe but the implementation is fragile internally.
+
+#[cfg(all(
+    not(all(target_arch = "wasm32", target_os = "unknown")),
+    feature = "proc-macro"
+))]
+use proc_macro as pm;
+use proc_macro2::{Delimiter, Ident, Literal, Span, TokenStream};
+use proc_macro2::{Group, Punct, TokenTree};
+
+use std::marker::PhantomData;
+use std::ptr;
+
+#[cfg(synom_verbose_trace)]
+use std::fmt::{self, Debug};
+
+/// Internal type which is used instead of `TokenTree` to represent a token tree
+/// within a `TokenBuffer`.
+enum Entry {
+    // Mimicking types from proc-macro.
+    Group(Span, Delimiter, TokenBuffer),
+    Ident(Ident),
+    Punct(Punct),
+    Literal(Literal),
+    // End entries contain a raw pointer to the entry from the containing
+    // token tree, or null if this is the outermost level.
+    End(*const Entry),
+}
+
+/// A buffer that can be efficiently traversed multiple times, unlike
+/// `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
+    // will be messed up. Moving the `TokenBuffer` itself is safe as the actual
+    // backing slices won't be moved.
+    data: Box<[Entry]>,
+}
+
+impl TokenBuffer {
+    // NOTE: DO NOT MUTATE THE `Vec` RETURNED FROM THIS FUNCTION ONCE IT
+    // RETURNS, THE ADDRESS OF ITS BACKING MEMORY MUST REMAIN STABLE.
+    fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
+        // Build up the entries list, recording the locations of any Groups
+        // in the list to be processed later.
+        let mut entries = Vec::new();
+        let mut seqs = Vec::new();
+        for tt in stream {
+            match tt {
+                TokenTree::Ident(sym) => {
+                    entries.push(Entry::Ident(sym));
+                }
+                TokenTree::Punct(op) => {
+                    entries.push(Entry::Punct(op));
+                }
+                TokenTree::Literal(l) => {
+                    entries.push(Entry::Literal(l));
+                }
+                TokenTree::Group(g) => {
+                    // Record the index of the interesting entry, and store an
+                    // `End(null)` there temporarially.
+                    seqs.push((entries.len(), g.span(), g.delimiter(), g.stream().clone()));
+                    entries.push(Entry::End(ptr::null()));
+                }
+            }
+        }
+        // Add an `End` entry to the end with a reference to the enclosing token
+        // stream which was passed in.
+        entries.push(Entry::End(up));
+
+        // NOTE: This is done to ensure that we don't accidentally modify the
+        // length of the backing buffer. The backing buffer must remain at a
+        // constant address after this point, as we are going to store a raw
+        // pointer into it.
+        let mut entries = entries.into_boxed_slice();
+        for (idx, span, delim, seq_stream) in seqs {
+            // We know that this index refers to one of the temporary
+            // `End(null)` entries, and we know that the last entry is
+            // `End(up)`, so the next index is also valid.
+            let seq_up = &entries[idx + 1] as *const Entry;
+
+            // The end entry stored at the end of this Entry::Group should
+            // point to the Entry which follows the Group in the list.
+            let inner = Self::inner_new(seq_stream, seq_up);
+            entries[idx] = Entry::Group(span, delim, inner);
+        }
+
+        TokenBuffer { data: entries }
+    }
+
+    /// Creates a `TokenBuffer` containing all the tokens from the input
+    /// `TokenStream`.
+    ///
+    /// *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"
+    ))]
+    pub fn new(stream: pm::TokenStream) -> TokenBuffer {
+        Self::new2(stream.into())
+    }
+
+    /// Creates a `TokenBuffer` containing all the tokens from the input
+    /// `TokenStream`.
+    pub fn new2(stream: TokenStream) -> TokenBuffer {
+        Self::inner_new(stream, ptr::null())
+    }
+
+    /// Creates a cursor referencing the first token in the buffer and able to
+    /// traverse until the end of the buffer.
+    pub fn begin(&self) -> Cursor {
+        unsafe { Cursor::create(&self.data[0], &self.data[self.data.len() - 1]) }
+    }
+}
+
+/// A cheaply copyable cursor into a `TokenBuffer`.
+///
+/// This cursor holds a shared reference into the immutable data which is used
+/// internally to represent a `TokenStream`, and can be efficiently manipulated
+/// and copied around.
+///
+/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
+/// object and get a cursor to its first token with `begin()`.
+///
+/// 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> {
+    /// The current entry which the `Cursor` is pointing at.
+    ptr: *const Entry,
+    /// This is the only `Entry::End(..)` object which this cursor is allowed to
+    /// point at. All other `End` objects are skipped over in `Cursor::create`.
+    scope: *const Entry,
+    /// This uses the &'a reference which guarantees that these pointers are
+    /// still valid.
+    marker: PhantomData<&'a Entry>,
+}
+
+impl<'a> Cursor<'a> {
+    /// Creates a cursor referencing a static empty TokenStream.
+    pub fn empty() -> Self {
+        // It's safe in this situation for us to put an `Entry` object in global
+        // storage, despite it not actually being safe to send across threads
+        // (`Ident` is a reference into a thread-local table). This is because
+        // this entry never includes a `Ident` object.
+        //
+        // This wrapper struct allows us to break the rules and put a `Sync`
+        // object in global storage.
+        struct UnsafeSyncEntry(Entry);
+        unsafe impl Sync for UnsafeSyncEntry {}
+        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));
+
+        Cursor {
+            ptr: &EMPTY_ENTRY.0,
+            scope: &EMPTY_ENTRY.0,
+            marker: PhantomData,
+        }
+    }
+
+    /// This create method intelligently exits non-explicitly-entered
+    /// `None`-delimited scopes when the cursor reaches the end of them,
+    /// allowing for them to be treated transparently.
+    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
+        // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
+        // past it, unless `ptr == scope`, which means that we're at the edge of
+        // our cursor's scope. We should only have `ptr != scope` at the exit
+        // from None-delimited groups entered with `ignore_none`.
+        while let Entry::End(exit) = *ptr {
+            if ptr == scope {
+                break;
+            }
+            ptr = exit;
+        }
+
+        Cursor {
+            ptr: ptr,
+            scope: scope,
+            marker: PhantomData,
+        }
+    }
+
+    /// Get the current entry.
+    fn entry(self) -> &'a Entry {
+        unsafe { &*self.ptr }
+    }
+
+    /// Bump the cursor to point at the next token after the current one. This
+    /// is undefined behavior if the cursor is currently looking at an
+    /// `Entry::End`.
+    unsafe fn bump(self) -> Cursor<'a> {
+        Cursor::create(self.ptr.offset(1), self.scope)
+    }
+
+    /// If the cursor is looking at a `None`-delimited group, move it to look at
+    /// the first token inside instead. If the group is empty, this will move
+    /// the cursor past the `None`-delimited group.
+    ///
+    /// WARNING: This mutates its argument.
+    fn ignore_none(&mut self) {
+        if let Entry::Group(_, Delimiter::None, ref buf) = *self.entry() {
+            // NOTE: We call `Cursor::create` here to make sure that situations
+            // where we should immediately exit the span after entering it are
+            // handled correctly.
+            unsafe {
+                *self = Cursor::create(&buf.data[0], self.scope);
+            }
+        }
+    }
+
+    /// Checks whether the cursor is currently pointing at the end of its valid
+    /// scope.
+    #[inline]
+    pub fn eof(self) -> bool {
+        // We're at eof if we're at the end of our scope.
+        self.ptr == self.scope
+    }
+
+    /// If the cursor is pointing at a `Group` with the given delimiter, returns
+    /// a cursor into that group and one pointing to the next `TokenTree`.
+    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
+        // If we're not trying to enter a none-delimited group, we want to
+        // ignore them. We have to make sure to _not_ ignore them when we want
+        // to enter them, of course. For obvious reasons.
+        if delim != Delimiter::None {
+            self.ignore_none();
+        }
+
+        if let Entry::Group(span, group_delim, ref buf) = *self.entry() {
+            if group_delim == delim {
+                return Some((buf.begin(), span, unsafe { self.bump() }));
+            }
+        }
+
+        None
+    }
+
+    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
+    /// pointing at the next `TokenTree`.
+    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
+        self.ignore_none();
+        match *self.entry() {
+            Entry::Ident(ref ident) => Some((ident.clone(), unsafe { self.bump() })),
+            _ => None,
+        }
+    }
+
+    /// If the cursor is pointing at an `Punct`, returns it along with a cursor
+    /// pointing at the next `TokenTree`.
+    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() })),
+            _ => None,
+        }
+    }
+
+    /// If the cursor is pointing at a `Literal`, return it along with a cursor
+    /// pointing at the next `TokenTree`.
+    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
+        self.ignore_none();
+        match *self.entry() {
+            Entry::Literal(ref lit) => Some((lit.clone(), unsafe { self.bump() })),
+            _ => None,
+        }
+    }
+
+    /// Copies all remaining tokens visible from this cursor into a
+    /// `TokenStream`.
+    pub fn token_stream(self) -> TokenStream {
+        let mut tts = Vec::new();
+        let mut cursor = self;
+        while let Some((tt, rest)) = cursor.token_tree() {
+            tts.push(tt);
+            cursor = rest;
+        }
+        tts.into_iter().collect()
+    }
+
+    /// If the cursor is pointing at a `TokenTree`, returns it along with a
+    /// cursor pointing at the next `TokenTree`.
+    ///
+    /// Returns `None` if the cursor has reached the end of its stream.
+    ///
+    /// This method does not treat `None`-delimited groups as transparent, and
+    /// will return a `Group(None, ..)` if the cursor is looking at one.
+    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
+        let tree = match *self.entry() {
+            Entry::Group(span, delim, ref buf) => {
+                let stream = buf.begin().token_stream();
+                let mut g = Group::new(delim, stream);
+                g.set_span(span);
+                TokenTree::from(g)
+            }
+            Entry::Literal(ref lit) => lit.clone().into(),
+            Entry::Ident(ref ident) => ident.clone().into(),
+            Entry::Punct(ref op) => op.clone().into(),
+            Entry::End(..) => {
+                return None;
+            }
+        };
+
+        Some((tree, unsafe { self.bump() }))
+    }
+
+    /// Returns the `Span` of the current token, or `Span::call_site()` if this
+    /// cursor points to eof.
+    pub fn span(self) -> Span {
+        match *self.entry() {
+            Entry::Group(span, ..) => span,
+            Entry::Literal(ref l) => l.span(),
+            Entry::Ident(ref t) => t.span(),
+            Entry::Punct(ref o) => o.span(),
+            Entry::End(..) => Span::call_site(),
+        }
+    }
+}
+
+// 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
new file mode 100644
index 0000000..8ffc8a4
--- /dev/null
+++ b/src/data.rs
@@ -0,0 +1,415 @@
+// 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 super::*;
+use punctuated::Punctuated;
+
+ast_struct! {
+    /// An enum variant.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Variant {
+        /// Attributes tagged on the variant.
+        pub attrs: Vec<Attribute>,
+
+        /// Name of the variant.
+        pub ident: Ident,
+
+        /// Content stored in the variant.
+        pub fields: Fields,
+
+        /// Explicit discriminant: `Variant = 1`
+        pub discriminant: Option<(Token![=], Expr)>,
+    }
+}
+
+ast_enum_of_structs! {
+    /// Data stored within an enum variant or struct.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum Fields {
+        /// Named fields of a struct or struct variant such as `Point { x: f64,
+        /// y: f64 }`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Named(FieldsNamed {
+            pub brace_token: token::Brace,
+            pub named: Punctuated<Field, Token![,]>,
+        }),
+
+        /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Unnamed(FieldsUnnamed {
+            pub paren_token: token::Paren,
+            pub unnamed: Punctuated<Field, Token![,]>,
+        }),
+
+        /// Unit struct or unit variant such as `None`.
+        pub Unit,
+    }
+}
+
+impl Fields {
+    /// Get an iterator over the borrowed [`Field`] items in this object. This
+    /// iterator can be used to iterate over a named or unnamed struct or
+    /// variant's fields uniformly.
+    ///
+    /// [`Field`]: struct.Field.html
+    pub fn iter(&self) -> punctuated::Iter<Field> {
+        match *self {
+            Fields::Unit => punctuated::Iter::private_empty(),
+            Fields::Named(ref f) => f.named.iter(),
+            Fields::Unnamed(ref f) => f.unnamed.iter(),
+        }
+    }
+
+    /// Get an iterator over the mutably borrowed [`Field`] items in this
+    /// object. This iterator can be used to iterate over a named or unnamed
+    /// struct or variant's fields uniformly.
+    ///
+    /// [`Field`]: struct.Field.html
+    pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
+        match *self {
+            Fields::Unit => punctuated::IterMut::private_empty(),
+            Fields::Named(ref mut f) => f.named.iter_mut(),
+            Fields::Unnamed(ref mut f) => f.unnamed.iter_mut(),
+        }
+    }
+}
+
+impl<'a> IntoIterator for &'a Fields {
+    type Item = &'a Field;
+    type IntoIter = punctuated::Iter<'a, Field>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+impl<'a> IntoIterator for &'a mut Fields {
+    type Item = &'a mut Field;
+    type IntoIter = punctuated::IterMut<'a, Field>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter_mut()
+    }
+}
+
+ast_struct! {
+    /// A field of a struct or enum variant.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Field {
+        /// Attributes tagged on the field.
+        pub attrs: Vec<Attribute>,
+
+        /// Visibility of the field.
+        pub vis: Visibility,
+
+        /// Name of the field, if any.
+        ///
+        /// Fields of tuple structs have no names.
+        pub ident: Option<Ident>,
+
+        pub colon_token: Option<Token![:]>,
+
+        /// Type of the field.
+        pub ty: Type,
+    }
+}
+
+ast_enum_of_structs! {
+    /// The visibility level of an item: inherited or `pub` or
+    /// `pub(restricted)`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum Visibility {
+        /// A public visibility level: `pub`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Public(VisPublic {
+            pub pub_token: Token![pub],
+        }),
+
+        /// A crate-level visibility: `crate`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Crate(VisCrate {
+            pub crate_token: Token![crate],
+        }),
+
+        /// A visibility level restricted to some path: `pub(self)` or
+        /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Restricted(VisRestricted {
+            pub pub_token: Token![pub],
+            pub paren_token: token::Paren,
+            pub in_token: Option<Token![in]>,
+            pub path: Box<Path>,
+        }),
+
+        /// An inherited visibility, which usually means private.
+        pub Inherited,
+    }
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+
+    use synom::Synom;
+
+    impl Synom for Variant {
+        named!(parse -> Self, do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
+            id: syn!(Ident) >>
+            fields: alt!(
+                syn!(FieldsNamed) => { Fields::Named }
+                |
+                syn!(FieldsUnnamed) => { Fields::Unnamed }
+                |
+                epsilon!() => { |_| Fields::Unit }
+            ) >>
+            disr: option!(tuple!(punct!(=), syn!(Expr))) >>
+            (Variant {
+                ident: id,
+                attrs: attrs,
+                fields: fields,
+                discriminant: disr,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("enum variant")
+        }
+    }
+
+    impl Synom for FieldsNamed {
+        named!(parse -> Self, map!(
+            braces!(call!(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 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 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),
+            })
+        ));
+
+        named!(pub parse_unnamed -> Self, do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
+            vis: syn!(Visibility) >>
+            ty: syn!(Type) >>
+            (Field {
+                ident: None,
+                colon_token: None,
+                vis: vis,
+                attrs: attrs,
+                ty: ty,
+            })
+        ));
+    }
+
+    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 }
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("visibility qualifier such as `pub`")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::{ToTokens, TokenStreamExt};
+
+    impl ToTokens for Variant {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(&self.attrs);
+            self.ident.to_tokens(tokens);
+            self.fields.to_tokens(tokens);
+            if let Some((ref eq_token, ref disc)) = self.discriminant {
+                eq_token.to_tokens(tokens);
+                disc.to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for FieldsNamed {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.brace_token.surround(tokens, |tokens| {
+                self.named.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for FieldsUnnamed {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.paren_token.surround(tokens, |tokens| {
+                self.unnamed.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for Field {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(&self.attrs);
+            self.vis.to_tokens(tokens);
+            if let Some(ref ident) = self.ident {
+                ident.to_tokens(tokens);
+                TokensOrDefault(&self.colon_token).to_tokens(tokens);
+            }
+            self.ty.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for VisPublic {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.pub_token.to_tokens(tokens)
+        }
+    }
+
+    impl ToTokens for VisCrate {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.crate_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for VisRestricted {
+        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
+                // "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
new file mode 100644
index 0000000..ecef776
--- /dev/null
+++ b/src/derive.rs
@@ -0,0 +1,242 @@
+// 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 super::*;
+use punctuated::Punctuated;
+
+ast_struct! {
+    /// Data structure sent to a `proc_macro_derive` macro.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` feature.*
+    pub struct DeriveInput {
+        /// Attributes tagged on the whole struct or enum.
+        pub attrs: Vec<Attribute>,
+
+        /// Visibility of the struct or enum.
+        pub vis: Visibility,
+
+        /// Name of the struct or enum.
+        pub ident: Ident,
+
+        /// Generics required to complete the definition.
+        pub generics: Generics,
+
+        /// Data within the struct or enum.
+        pub data: Data,
+    }
+}
+
+ast_enum_of_structs! {
+    /// The storage of a struct, enum or union data structure.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum Data {
+        /// A struct input to a `proc_macro_derive` macro.
+        ///
+        /// *This type is available if Syn is built with the `"derive"`
+        /// feature.*
+        pub Struct(DataStruct {
+            pub struct_token: Token![struct],
+            pub fields: Fields,
+            pub semi_token: Option<Token![;]>,
+        }),
+
+        /// An enum input to a `proc_macro_derive` macro.
+        ///
+        /// *This type is available if Syn is built with the `"derive"`
+        /// feature.*
+        pub Enum(DataEnum {
+            pub enum_token: Token![enum],
+            pub brace_token: token::Brace,
+            pub variants: Punctuated<Variant, Token![,]>,
+        }),
+
+        /// A tagged union input to a `proc_macro_derive` macro.
+        ///
+        /// *This type is available if Syn is built with the `"derive"`
+        /// feature.*
+        pub Union(DataUnion {
+            pub union_token: Token![union],
+            pub fields: FieldsNamed,
+        }),
+    }
+
+    do_not_generate_to_tokens
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+
+    use synom::Synom;
+
+    enum DeriveInputKind {
+        Struct(Token![struct]),
+        Enum(Token![enum]),
+        Union(Token![union]),
+    }
+
+    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,
+                    attrs: attrs,
+                    generics: Generics {
+                        where_clause: wh,
+                        ..generics
+                    },
+                    data: Data::Struct(DataStruct {
+                        struct_token: s,
+                        fields: fields,
+                        semi_token: semi,
+                    }),
+                })
+                |
+                DeriveInputKind::Enum(e) => map!(data_enum, move |(wh, brace, variants)| DeriveInput {
+                    ident: id,
+                    vis: vis,
+                    attrs: attrs,
+                    generics: Generics {
+                        where_clause: wh,
+                        ..generics
+                    },
+                    data: Data::Enum(DataEnum {
+                        variants: variants,
+                        brace_token: brace,
+                        enum_token: e,
+                    }),
+                })
+                |
+                DeriveInputKind::Union(u) => map!(data_union, move |(wh, fields)| DeriveInput {
+                    ident: id,
+                    vis: vis,
+                    attrs: attrs,
+                    generics: Generics {
+                        where_clause: wh,
+                        ..generics
+                    },
+                    data: Data::Union(DataUnion {
+                        union_token: u,
+                        fields: fields,
+                    }),
+                })
+            ) >>
+            (item)
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("derive input")
+        }
+    }
+
+    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))
+        )
+    ));
+
+    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)
+    ));
+
+    named!(data_union -> (Option<WhereClause>, FieldsNamed), tuple!(
+        option!(syn!(WhereClause)),
+        syn!(FieldsNamed),
+    ));
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use attr::FilterAttrs;
+    use proc_macro2::TokenStream;
+    use quote::ToTokens;
+
+    impl ToTokens for DeriveInput {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            for attr in self.attrs.outer() {
+                attr.to_tokens(tokens);
+            }
+            self.vis.to_tokens(tokens);
+            match self.data {
+                Data::Struct(ref d) => d.struct_token.to_tokens(tokens),
+                Data::Enum(ref d) => d.enum_token.to_tokens(tokens),
+                Data::Union(ref d) => d.union_token.to_tokens(tokens),
+            }
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            match self.data {
+                Data::Struct(ref data) => match data.fields {
+                    Fields::Named(ref fields) => {
+                        self.generics.where_clause.to_tokens(tokens);
+                        fields.to_tokens(tokens);
+                    }
+                    Fields::Unnamed(ref fields) => {
+                        fields.to_tokens(tokens);
+                        self.generics.where_clause.to_tokens(tokens);
+                        TokensOrDefault(&data.semi_token).to_tokens(tokens);
+                    }
+                    Fields::Unit => {
+                        self.generics.where_clause.to_tokens(tokens);
+                        TokensOrDefault(&data.semi_token).to_tokens(tokens);
+                    }
+                },
+                Data::Enum(ref data) => {
+                    self.generics.where_clause.to_tokens(tokens);
+                    data.brace_token.surround(tokens, |tokens| {
+                        data.variants.to_tokens(tokens);
+                    });
+                }
+                Data::Union(ref data) => {
+                    self.generics.where_clause.to_tokens(tokens);
+                    data.fields.to_tokens(tokens);
+                }
+            }
+        }
+    }
+}
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..6673aa3
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,60 @@
+// 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 std::error::Error;
+use std::fmt::{self, Display};
+
+/// 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>;
+
+/// 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))
+}
+
+/// Error returned when a `Synom` parser cannot parse the input tokens.
+///
+/// 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.*
+#[derive(Debug)]
+pub struct ParseError(Option<String>);
+
+impl Error for ParseError {
+    fn description(&self) -> &str {
+        match self.0 {
+            Some(ref desc) => desc,
+            None => "failed to parse",
+        }
+    }
+}
+
+impl Display for ParseError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(self.description(), f)
+    }
+}
+
+impl ParseError {
+    // For syn use only. Not public API.
+    #[doc(hidden)]
+    pub fn new<T: Into<String>>(msg: T) -> Self {
+        ParseError(Some(msg.into()))
+    }
+}
diff --git a/src/expr.rs b/src/expr.rs
new file mode 100644
index 0000000..60caae2
--- /dev/null
+++ b/src/expr.rs
@@ -0,0 +1,3905 @@
+// 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 super::*;
+use proc_macro2::{Span, TokenStream};
+use punctuated::Punctuated;
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+#[cfg(feature = "full")]
+use std::mem;
+#[cfg(feature = "extra-traits")]
+use tt::TokenStreamHelper;
+
+ast_enum_of_structs! {
+    /// A Rust expression.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax tree enums
+    ///
+    /// This type is a syntax tree enum. In Syn this and other syntax tree enums
+    /// are designed to be traversed using the following rebinding idiom.
+    ///
+    /// ```
+    /// # use syn::Expr;
+    /// #
+    /// # fn example(expr: Expr) {
+    /// # const IGNORE: &str = stringify! {
+    /// let expr: Expr = /* ... */;
+    /// # };
+    /// match expr {
+    ///     Expr::MethodCall(expr) => {
+    ///         /* ... */
+    ///     }
+    ///     Expr::Cast(expr) => {
+    ///         /* ... */
+    ///     }
+    ///     Expr::IfLet(expr) => {
+    ///         /* ... */
+    ///     }
+    ///     /* ... */
+    ///     # _ => {}
+    /// }
+    /// # }
+    /// ```
+    ///
+    /// We begin with a variable `expr` of type `Expr` that has no fields
+    /// (because it is an enum), and by matching on it and rebinding a variable
+    /// with the same name `expr` we effectively imbue our variable with all of
+    /// the data fields provided by the variant that it turned out to be. So for
+    /// example above if we ended up in the `MethodCall` case then we get to use
+    /// `expr.receiver`, `expr.args` etc; if we ended up in the `IfLet` case we
+    /// get to use `expr.pat`, `expr.then_branch`, `expr.else_branch`.
+    ///
+    /// The pattern is similar if the input expression is borrowed:
+    ///
+    /// ```
+    /// # use syn::Expr;
+    /// #
+    /// # fn example(expr: &Expr) {
+    /// match *expr {
+    ///     Expr::MethodCall(ref expr) => {
+    /// #   }
+    /// #   _ => {}
+    /// # }
+    /// # }
+    /// ```
+    ///
+    /// This approach avoids repeating the variant names twice on every line.
+    ///
+    /// ```
+    /// # use syn::{Expr, ExprMethodCall};
+    /// #
+    /// # fn example(expr: Expr) {
+    /// # match expr {
+    /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
+    /// # }
+    /// # _ => {}
+    /// # }
+    /// # }
+    /// ```
+    ///
+    /// In general, the name to which a syntax tree enum variant is bound should
+    /// be a suitable name for the complete syntax tree enum type.
+    ///
+    /// ```
+    /// # use syn::{Expr, ExprField};
+    /// #
+    /// # fn example(discriminant: &ExprField) {
+    /// // Binding is called `base` which is the name I would use if I were
+    /// // assigning `*discriminant.base` without an `if let`.
+    /// if let Expr::Tuple(ref base) = *discriminant.base {
+    /// # }
+    /// # }
+    /// ```
+    ///
+    /// A sign that you may not be choosing the right variable names is if you
+    /// see names getting repeated in your code, like accessing
+    /// `receiver.receiver` or `pat.pat` or `cond.cond`.
+    pub enum Expr {
+        /// A box expression: `box f`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Box(ExprBox #full {
+            pub attrs: Vec<Attribute>,
+            pub box_token: Token![box],
+            pub expr: Box<Expr>,
+        }),
+
+        /// A placement expression: `place <- value`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub InPlace(ExprInPlace #full {
+            pub attrs: Vec<Attribute>,
+            pub place: Box<Expr>,
+            pub arrow_token: Token![<-],
+            pub value: Box<Expr>,
+        }),
+
+        /// A slice literal expression: `[a, b, c, d]`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Array(ExprArray #full {
+            pub attrs: Vec<Attribute>,
+            pub bracket_token: token::Bracket,
+            pub elems: Punctuated<Expr, Token![,]>,
+        }),
+
+        /// A function call expression: `invoke(a, b)`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Call(ExprCall {
+            pub attrs: Vec<Attribute>,
+            pub func: Box<Expr>,
+            pub paren_token: token::Paren,
+            pub args: Punctuated<Expr, Token![,]>,
+        }),
+
+        /// A method call expression: `x.foo::<T>(a, b)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub MethodCall(ExprMethodCall #full {
+            pub attrs: Vec<Attribute>,
+            pub receiver: Box<Expr>,
+            pub dot_token: Token![.],
+            pub method: Ident,
+            pub turbofish: Option<MethodTurbofish>,
+            pub paren_token: token::Paren,
+            pub args: Punctuated<Expr, Token![,]>,
+        }),
+
+        /// A tuple expression: `(a, b, c, d)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Tuple(ExprTuple #full {
+            pub attrs: Vec<Attribute>,
+            pub paren_token: token::Paren,
+            pub elems: Punctuated<Expr, Token![,]>,
+        }),
+
+        /// A binary operation: `a + b`, `a * b`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Binary(ExprBinary {
+            pub attrs: Vec<Attribute>,
+            pub left: Box<Expr>,
+            pub op: BinOp,
+            pub right: Box<Expr>,
+        }),
+
+        /// A unary operation: `!x`, `*x`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Unary(ExprUnary {
+            pub attrs: Vec<Attribute>,
+            pub op: UnOp,
+            pub expr: Box<Expr>,
+        }),
+
+        /// A literal in place of an expression: `1`, `"foo"`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Lit(ExprLit {
+            pub attrs: Vec<Attribute>,
+            pub lit: Lit,
+        }),
+
+        /// A cast expression: `foo as f64`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Cast(ExprCast {
+            pub attrs: Vec<Attribute>,
+            pub expr: Box<Expr>,
+            pub as_token: Token![as],
+            pub ty: Box<Type>,
+        }),
+
+        /// A type ascription expression: `foo: f64`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Type(ExprType #full {
+            pub attrs: Vec<Attribute>,
+            pub expr: Box<Expr>,
+            pub colon_token: Token![:],
+            pub ty: Box<Type>,
+        }),
+
+        /// An `if` expression with an optional `else` block: `if expr { ... }
+        /// else { ... }`.
+        ///
+        /// The `else` branch expression may only be an `If`, `IfLet`, or
+        /// `Block` expression, not any of the other types of expression.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub If(ExprIf #full {
+            pub attrs: Vec<Attribute>,
+            pub if_token: Token![if],
+            pub cond: Box<Expr>,
+            pub then_branch: Block,
+            pub else_branch: Option<(Token![else], Box<Expr>)>,
+        }),
+
+        /// An `if let` expression with an optional `else` block: `if let pat =
+        /// expr { ... } else { ... }`.
+        ///
+        /// The `else` branch expression may only be an `If`, `IfLet`, or
+        /// `Block` expression, not any of the other types of expression.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub IfLet(ExprIfLet #full {
+            pub attrs: Vec<Attribute>,
+            pub if_token: Token![if],
+            pub let_token: Token![let],
+            pub pats: Punctuated<Pat, Token![|]>,
+            pub eq_token: Token![=],
+            pub expr: Box<Expr>,
+            pub then_branch: Block,
+            pub else_branch: Option<(Token![else], Box<Expr>)>,
+        }),
+
+        /// A while loop: `while expr { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub While(ExprWhile #full {
+            pub attrs: Vec<Attribute>,
+            pub label: Option<Label>,
+            pub while_token: Token![while],
+            pub cond: Box<Expr>,
+            pub body: Block,
+        }),
+
+        /// A while-let loop: `while let pat = expr { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub WhileLet(ExprWhileLet #full {
+            pub attrs: Vec<Attribute>,
+            pub label: Option<Label>,
+            pub while_token: Token![while],
+            pub let_token: Token![let],
+            pub pats: Punctuated<Pat, Token![|]>,
+            pub eq_token: Token![=],
+            pub expr: Box<Expr>,
+            pub body: Block,
+        }),
+
+        /// A for loop: `for pat in expr { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub ForLoop(ExprForLoop #full {
+            pub attrs: Vec<Attribute>,
+            pub label: Option<Label>,
+            pub for_token: Token![for],
+            pub pat: Box<Pat>,
+            pub in_token: Token![in],
+            pub expr: Box<Expr>,
+            pub body: Block,
+        }),
+
+        /// Conditionless loop: `loop { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Loop(ExprLoop #full {
+            pub attrs: Vec<Attribute>,
+            pub label: Option<Label>,
+            pub loop_token: Token![loop],
+            pub body: Block,
+        }),
+
+        /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Match(ExprMatch #full {
+            pub attrs: Vec<Attribute>,
+            pub match_token: Token![match],
+            pub expr: Box<Expr>,
+            pub brace_token: token::Brace,
+            pub arms: Vec<Arm>,
+        }),
+
+        /// A closure expression: `|a, b| a + b`.
+        ///
+        /// *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![|],
+            pub inputs: Punctuated<FnArg, Token![,]>,
+            pub or2_token: Token![|],
+            pub output: ReturnType,
+            pub body: Box<Expr>,
+        }),
+
+        /// An unsafe block: `unsafe { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Unsafe(ExprUnsafe #full {
+            pub attrs: Vec<Attribute>,
+            pub unsafe_token: Token![unsafe],
+            pub block: Block,
+        }),
+
+        /// A blocked scope: `{ ... }`.
+        ///
+        /// *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,
+        }),
+
+        /// An assignment expression: `a = compute()`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Assign(ExprAssign #full {
+            pub attrs: Vec<Attribute>,
+            pub left: Box<Expr>,
+            pub eq_token: Token![=],
+            pub right: Box<Expr>,
+        }),
+
+        /// A compound assignment expression: `counter += 1`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub AssignOp(ExprAssignOp #full {
+            pub attrs: Vec<Attribute>,
+            pub left: Box<Expr>,
+            pub op: BinOp,
+            pub right: Box<Expr>,
+        }),
+
+        /// Access of a named struct field (`obj.k`) or unnamed tuple struct
+        /// field (`obj.0`).
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Field(ExprField {
+            pub attrs: Vec<Attribute>,
+            pub base: Box<Expr>,
+            pub dot_token: Token![.],
+            pub member: Member,
+        }),
+
+        /// A square bracketed indexing expression: `vector[2]`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Index(ExprIndex {
+            pub attrs: Vec<Attribute>,
+            pub expr: Box<Expr>,
+            pub bracket_token: token::Bracket,
+            pub index: Box<Expr>,
+        }),
+
+        /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Range(ExprRange #full {
+            pub attrs: Vec<Attribute>,
+            pub from: Option<Box<Expr>>,
+            pub limits: RangeLimits,
+            pub to: Option<Box<Expr>>,
+        }),
+
+        /// A path like `std::mem::replace` possibly containing generic
+        /// parameters and a qualified self-type.
+        ///
+        /// A plain identifier like `x` is a path of length 1.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Path(ExprPath {
+            pub attrs: Vec<Attribute>,
+            pub qself: Option<QSelf>,
+            pub path: Path,
+        }),
+
+        /// A referencing operation: `&a` or `&mut a`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Reference(ExprReference #full {
+            pub attrs: Vec<Attribute>,
+            pub and_token: Token![&],
+            pub mutability: Option<Token![mut]>,
+            pub expr: Box<Expr>,
+        }),
+
+        /// A `break`, with an optional label to break and an optional
+        /// expression.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Break(ExprBreak #full {
+            pub attrs: Vec<Attribute>,
+            pub break_token: Token![break],
+            pub label: Option<Lifetime>,
+            pub expr: Option<Box<Expr>>,
+        }),
+
+        /// A `continue`, with an optional label.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Continue(ExprContinue #full {
+            pub attrs: Vec<Attribute>,
+            pub continue_token: Token![continue],
+            pub label: Option<Lifetime>,
+        }),
+
+        /// A `return`, with an optional value to be returned.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Return(ExprReturn #full {
+            pub attrs: Vec<Attribute>,
+            pub return_token: Token![return],
+            pub expr: Option<Box<Expr>>,
+        }),
+
+        /// A macro invocation expression: `format!("{}", q)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Macro(ExprMacro #full {
+            pub attrs: Vec<Attribute>,
+            pub mac: Macro,
+        }),
+
+        /// A struct literal expression: `Point { x: 1, y: 1 }`.
+        ///
+        /// The `rest` provides the value of the remaining fields as in `S { a:
+        /// 1, b: 1, ..rest }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Struct(ExprStruct #full {
+            pub attrs: Vec<Attribute>,
+            pub path: Path,
+            pub brace_token: token::Brace,
+            pub fields: Punctuated<FieldValue, Token![,]>,
+            pub dot2_token: Option<Token![..]>,
+            pub rest: Option<Box<Expr>>,
+        }),
+
+        /// An array literal constructed from one repeated element: `[0u8; N]`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Repeat(ExprRepeat #full {
+            pub attrs: Vec<Attribute>,
+            pub bracket_token: token::Bracket,
+            pub expr: Box<Expr>,
+            pub semi_token: Token![;],
+            pub len: Box<Expr>,
+        }),
+
+        /// A parenthesized expression: `(a + b)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Paren(ExprParen {
+            pub attrs: Vec<Attribute>,
+            pub paren_token: token::Paren,
+            pub expr: Box<Expr>,
+        }),
+
+        /// An expression contained within invisible delimiters.
+        ///
+        /// This variant is important for faithfully representing the precedence
+        /// of expressions and is related to `None`-delimited spans in a
+        /// `TokenStream`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Group(ExprGroup #full {
+            pub attrs: Vec<Attribute>,
+            pub group_token: token::Group,
+            pub expr: Box<Expr>,
+        }),
+
+        /// A try-expression: `expr?`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Try(ExprTry #full {
+            pub attrs: Vec<Attribute>,
+            pub expr: Box<Expr>,
+            pub question_token: Token![?],
+        }),
+
+        /// An async block: `async { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Async(ExprAsync #full {
+            pub attrs: Vec<Attribute>,
+            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,
+        }),
+
+        /// A yield expression: `yield expr`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Yield(ExprYield #full {
+            pub attrs: Vec<Attribute>,
+            pub yield_token: Token![yield],
+            pub expr: Option<Box<Expr>>,
+        }),
+
+        /// Tokens in expression position not interpreted by Syn.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Verbatim(ExprVerbatim #manual_extra_traits {
+            pub tts: TokenStream,
+        }),
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for ExprVerbatim {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for ExprVerbatim {
+    fn eq(&self, other: &Self) -> bool {
+        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for ExprVerbatim {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+impl Expr {
+    // Not public API.
+    #[doc(hidden)]
+    #[cfg(feature = "full")]
+    pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
+        match *self {
+            Expr::Box(ExprBox { ref mut attrs, .. })
+            | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
+            | Expr::Array(ExprArray { ref mut attrs, .. })
+            | Expr::Call(ExprCall { ref mut attrs, .. })
+            | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
+            | Expr::Tuple(ExprTuple { ref mut attrs, .. })
+            | Expr::Binary(ExprBinary { ref mut attrs, .. })
+            | Expr::Unary(ExprUnary { ref mut attrs, .. })
+            | Expr::Lit(ExprLit { ref mut attrs, .. })
+            | Expr::Cast(ExprCast { ref mut attrs, .. })
+            | Expr::Type(ExprType { ref mut attrs, .. })
+            | Expr::If(ExprIf { ref mut attrs, .. })
+            | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
+            | Expr::While(ExprWhile { ref mut attrs, .. })
+            | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
+            | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
+            | Expr::Loop(ExprLoop { ref mut attrs, .. })
+            | Expr::Match(ExprMatch { ref mut attrs, .. })
+            | Expr::Closure(ExprClosure { ref mut attrs, .. })
+            | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
+            | Expr::Block(ExprBlock { ref mut attrs, .. })
+            | Expr::Assign(ExprAssign { ref mut attrs, .. })
+            | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
+            | Expr::Field(ExprField { ref mut attrs, .. })
+            | Expr::Index(ExprIndex { ref mut attrs, .. })
+            | Expr::Range(ExprRange { ref mut attrs, .. })
+            | Expr::Path(ExprPath { ref mut attrs, .. })
+            | Expr::Reference(ExprReference { ref mut attrs, .. })
+            | Expr::Break(ExprBreak { ref mut attrs, .. })
+            | Expr::Continue(ExprContinue { ref mut attrs, .. })
+            | Expr::Return(ExprReturn { ref mut attrs, .. })
+            | Expr::Macro(ExprMacro { ref mut attrs, .. })
+            | Expr::Struct(ExprStruct { ref mut attrs, .. })
+            | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
+            | Expr::Paren(ExprParen { ref mut attrs, .. })
+            | Expr::Group(ExprGroup { ref mut attrs, .. })
+            | Expr::Try(ExprTry { ref mut attrs, .. })
+            | Expr::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()
+            }
+        }
+    }
+}
+
+ast_enum! {
+    /// A struct or tuple struct field accessed in a struct literal or field
+    /// expression.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum Member {
+        /// A named field like `self.x`.
+        Named(Ident),
+        /// An unnamed field like `self.0`.
+        Unnamed(Index),
+    }
+}
+
+ast_struct! {
+    /// The index of an unnamed tuple struct field.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Index #manual_extra_traits {
+        pub index: u32,
+        pub span: Span,
+    }
+}
+
+impl From<usize> for Index {
+    fn from(index: usize) -> Index {
+        assert!(index < u32::max_value() as usize);
+        Index {
+            index: index as u32,
+            span: Span::call_site(),
+        }
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for Index {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for Index {
+    fn eq(&self, other: &Self) -> bool {
+        self.index == other.index
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for Index {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.index.hash(state);
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+    /// The `::<>` explicit type parameters passed to a method call:
+    /// `parse::<u64>()`.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct MethodTurbofish {
+        pub colon2_token: Token![::],
+        pub lt_token: Token![<],
+        pub args: Punctuated<GenericMethodArgument, Token![,]>,
+        pub gt_token: Token![>],
+    }
+}
+
+#[cfg(feature = "full")]
+ast_enum! {
+    /// An individual generic argument to a method, like `T`.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub enum GenericMethodArgument {
+        /// A type argument.
+        Type(Type),
+        /// A const expression. Must be inside of a block.
+        ///
+        /// NOTE: Identity expressions are represented as Type arguments, as
+        /// they are indistinguishable syntactically.
+        Const(Expr),
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+    /// A field-value pair in a struct literal.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct FieldValue {
+        /// Attributes tagged on the field.
+        pub attrs: Vec<Attribute>,
+
+        /// Name or index of the field.
+        pub member: Member,
+
+        /// The colon in `Struct { x: x }`. If written in shorthand like
+        /// `Struct { x }`, there is no colon.
+        pub colon_token: Option<Token![:]>,
+
+        /// Value of the field.
+        pub expr: Expr,
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+    /// A lifetime labeling a `for`, `while`, or `loop`.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct Label {
+        pub name: Lifetime,
+        pub colon_token: Token![:],
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+    /// A braced block containing Rust statements.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct Block {
+        pub brace_token: token::Brace,
+        /// Statements in a block
+        pub stmts: Vec<Stmt>,
+    }
+}
+
+#[cfg(feature = "full")]
+ast_enum! {
+    /// A statement, usually ending in a semicolon.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub enum Stmt {
+        /// A local (let) binding.
+        Local(Local),
+
+        /// An item definition.
+        Item(Item),
+
+        /// Expr without trailing semicolon.
+        Expr(Expr),
+
+        /// Expression with trailing semicolon.
+        Semi(Expr, Token![;]),
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+    /// A local `let` binding: `let x: u64 = s.parse()?`.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct Local {
+        pub attrs: Vec<Attribute>,
+        pub let_token: Token![let],
+        pub pats: Punctuated<Pat, Token![|]>,
+        pub ty: Option<(Token![:], Box<Type>)>,
+        pub init: Option<(Token![=], Box<Expr>)>,
+        pub semi_token: Token![;],
+    }
+}
+
+#[cfg(feature = "full")]
+ast_enum_of_structs! {
+    /// A pattern in a local binding, function signature, match expression, or
+    /// various other places.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    // Clippy false positive
+    // https://github.com/Manishearth/rust-clippy/issues/1241
+    #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
+    pub enum Pat {
+        /// A pattern that matches any value: `_`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Wild(PatWild {
+            pub underscore_token: Token![_],
+        }),
+
+        /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Ident(PatIdent {
+            pub by_ref: Option<Token![ref]>,
+            pub mutability: Option<Token![mut]>,
+            pub ident: Ident,
+            pub subpat: Option<(Token![@], Box<Pat>)>,
+        }),
+
+        /// A struct or struct variant pattern: `Variant { x, y, .. }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Struct(PatStruct {
+            pub path: Path,
+            pub brace_token: token::Brace,
+            pub fields: Punctuated<FieldPat, Token![,]>,
+            pub dot2_token: Option<Token![..]>,
+        }),
+
+        /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub TupleStruct(PatTupleStruct {
+            pub path: Path,
+            pub pat: PatTuple,
+        }),
+
+        /// A path pattern like `Color::Red`, optionally qualified with a
+        /// self-type.
+        ///
+        /// Unquailfied path patterns can legally refer to variants, structs,
+        /// constants or associated constants. Quailfied path patterns like
+        /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
+        /// associated constants.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Path(PatPath {
+            pub qself: Option<QSelf>,
+            pub path: Path,
+        }),
+
+        /// A tuple pattern: `(a, b)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Tuple(PatTuple {
+            pub paren_token: token::Paren,
+            pub front: Punctuated<Pat, Token![,]>,
+            pub dot2_token: Option<Token![..]>,
+            pub comma_token: Option<Token![,]>,
+            pub back: Punctuated<Pat, Token![,]>,
+        }),
+
+        /// A box pattern: `box v`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Box(PatBox {
+            pub box_token: Token![box],
+            pub pat: Box<Pat>,
+        }),
+
+        /// A reference pattern: `&mut (first, second)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Ref(PatRef {
+            pub and_token: Token![&],
+            pub mutability: Option<Token![mut]>,
+            pub pat: Box<Pat>,
+        }),
+
+        /// A literal pattern: `0`.
+        ///
+        /// This holds an `Expr` rather than a `Lit` because negative numbers
+        /// are represented as an `Expr::Unary`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Lit(PatLit {
+            pub expr: Box<Expr>,
+        }),
+
+        /// A range pattern: `1..=2`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Range(PatRange {
+            pub lo: Box<Expr>,
+            pub limits: RangeLimits,
+            pub hi: Box<Expr>,
+        }),
+
+        /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Slice(PatSlice {
+            pub bracket_token: token::Bracket,
+            pub front: Punctuated<Pat, Token![,]>,
+            pub middle: Option<Box<Pat>>,
+            pub dot2_token: Option<Token![..]>,
+            pub comma_token: Option<Token![,]>,
+            pub back: Punctuated<Pat, Token![,]>,
+        }),
+
+        /// A macro in expression position.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Macro(PatMacro {
+            pub mac: Macro,
+        }),
+
+        /// Tokens in pattern position not interpreted by Syn.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Verbatim(PatVerbatim #manual_extra_traits {
+            pub tts: TokenStream,
+        }),
+    }
+}
+
+#[cfg(all(feature = "full", feature = "extra-traits"))]
+impl Eq for PatVerbatim {}
+
+#[cfg(all(feature = "full", feature = "extra-traits"))]
+impl PartialEq for PatVerbatim {
+    fn eq(&self, other: &Self) -> bool {
+        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(all(feature = "full", feature = "extra-traits"))]
+impl Hash for PatVerbatim {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+    /// One arm of a `match` expression: `0...10 => { return true; }`.
+    ///
+    /// As in:
+    ///
+    /// ```rust
+    /// # fn f() -> bool {
+    /// #     let n = 0;
+    /// match n {
+    ///     0...10 => {
+    ///         return true;
+    ///     }
+    ///     // ...
+    ///     # _ => {}
+    /// }
+    /// #   false
+    /// # }
+    /// ```
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct Arm {
+        pub attrs: Vec<Attribute>,
+        pub leading_vert: Option<Token![|]>,
+        pub pats: Punctuated<Pat, Token![|]>,
+        pub guard: Option<(Token![if], Box<Expr>)>,
+        pub fat_arrow_token: Token![=>],
+        pub body: Box<Expr>,
+        pub comma: Option<Token![,]>,
+    }
+}
+
+#[cfg(feature = "full")]
+ast_enum! {
+    /// Limit types of a range, inclusive or exclusive.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    #[cfg_attr(feature = "clone-impls", derive(Copy))]
+    pub enum RangeLimits {
+        /// Inclusive at the beginning, exclusive at the end.
+        HalfOpen(Token![..]),
+        /// Inclusive at the beginning and end.
+        Closed(Token![..=]),
+    }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+    /// A single field in a struct pattern.
+    ///
+    /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
+    /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct FieldPat {
+        pub attrs: Vec<Attribute>,
+        pub member: Member,
+        pub colon_token: Option<Token![:]>,
+        pub pat: Box<Pat>,
+    }
+}
+
+#[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
+    match *expr {
+        Expr::Unsafe(..)
+        | Expr::Block(..)
+        | Expr::If(..)
+        | Expr::IfLet(..)
+        | Expr::Match(..)
+        | Expr::While(..)
+        | Expr::WhileLet(..)
+        | Expr::Loop(..)
+        | Expr::ForLoop(..)
+        | Expr::Async(..)
+        | Expr::TryBlock(..) => false,
+        _ => true,
+    }
+}
+
+#[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;
+
+    // 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)
+        };
+    }
+
+    // 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 Synom for Expr {
+        named!(parse -> Self, ambiguous_expr!(true));
+
+        fn description() -> Option<&'static str> {
+            Some("expression")
+        }
+    }
+
+    #[cfg(feature = "full")]
+    named!(expr_no_struct -> Expr, ambiguous_expr!(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 {
+                        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),
+                        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 {
+                        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 {
+                    attrs: Vec::new(),
+                    from: Some(Box::new(e)),
+                    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 {
+                    attrs: Vec::new(),
+                    expr: Box::new(e),
+                    as_token: as_,
+                    ty: Box::new(ty),
+                }.into();
+            })
+        )) >>
+        (e)
+    ));
+
+    // <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),
+            }
+        }
+        *attrs = inner;
+        outer
+    }
+
+    // <atom> (..<args>) ...
+    // <atom> . <ident> (..<args>) ...
+    // <atom> . <ident> ...
+    // <atom> . <lit> ...
+    // <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
+        })
+    ));
+
+    // 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 {
+                    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 {
+                    attrs: Vec::new(),
+                    base: Box::new(e),
+                    dot_token: token,
+                    member: member,
+                }.into();
+            })
+            |
+            tap!(i: and_index => {
+                e = ExprIndex {
+                    attrs: Vec::new(),
+                    expr: Box::new(e),
+                    bracket_token: i.0,
+                    index: Box::new(i.1),
+                }.into();
+            })
+        )) >>
+        (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
+        syn!(ExprAsync) => { Expr::Async }
+        |
+        // must be before ExprStruct
+        syn!(ExprTryBlock) => { Expr::TryBlock }
+        |
+        // 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!(ExprYield) => { Expr::Yield }
+        |
+        syn!(ExprUnsafe) => { Expr::Unsafe }
+        |
+        call!(expr_closure, allow_struct)
+        |
+        cond_reduce!(allow_block, syn!(ExprBlock)) => { Expr::Block }
+        |
+        // NOTE: This is the prefix-form of range
+        call!(expr_range, allow_struct)
+        |
+        syn!(ExprPath) => { Expr::Path }
+        |
+        syn!(ExprRepeat) => { Expr::Repeat }
+    ));
+
+    #[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!(ExprTryBlock) => { Expr::TryBlock }
+            |
+            syn!(ExprYield) => { Expr::Yield }
+            |
+            syn!(ExprUnsafe) => { Expr::Unsafe }
+            |
+            syn!(ExprBlock) => { Expr::Block }
+        ) >>
+        // 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")
+        }
+    }
+
+    #[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")
+        }
+    }
+
+    #[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(),
+                    label: None,
+                    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 ExprTryBlock {
+        named!(parse -> Self, do_parse!(
+            try_token: keyword!(try) >>
+            block: syn!(Block) >>
+            (ExprTryBlock {
+                attrs: Vec::new(),
+                try_token: try_token,
+                block: block,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("`try` block")
+        }
+    }
+
+    #[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!(
+        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(),
+                        label: None,
+                        block: body,
+                    },
+                ))
+            )
+            |
+            map!(ambiguous_expr!(allow_struct), |e| (ReturnType::Default, e))
+        ) >>
+        (Expr::Closure(ExprClosure {
+            attrs: attrs,
+            asyncness: asyncness,
+            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")]
+    impl Synom for ExprAsync {
+        named!(parse -> Self, do_parse!(
+            attrs: many0!(Attribute::parse_outer) >>
+            async_token: keyword!(async) >>
+            capture: option!(keyword!(move)) >>
+            block: syn!(Block) >>
+            (ExprAsync {
+                attrs: attrs,
+                async_token: async_token,
+                capture: capture,
+                block: block,
+            })
+        ));
+    }
+
+    #[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),
+                }
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("struct literal expression")
+        }
+    }
+
+    #[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 description() -> Option<&'static str> {
+            Some("field-value pair: `field: value`")
+        }
+    }
+
+    #[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 description() -> Option<&'static str> {
+            Some("repeated array literal: `[val; N]`")
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Synom for ExprUnsafe {
+        named!(parse -> Self, do_parse!(
+            unsafe_: keyword!(unsafe) >>
+            b: syn!(Block) >>
+            (ExprUnsafe {
+                attrs: Vec::new(),
+                unsafe_token: unsafe_,
+                block: b,
+            })
+        ));
+
+        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) >>
+            label: option!(syn!(Label)) >>
+            block: braces!(tuple!(
+                many0!(Attribute::parse_inner),
+                call!(Block::parse_within),
+            )) >>
+            (ExprBlock {
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend((block.1).0);
+                    attrs
+                },
+                label: label,
+                block: Block {
+                    brace_token: block.0,
+                    stmts: (block.1).1,
+                },
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("block: `{ .. }`")
+        }
+    }
+
+    #[cfg(feature = "full")]
+    named!(expr_range(allow_struct: bool) -> Expr, do_parse!(
+        limits: syn!(RangeLimits) >>
+        hi: opt_ambiguous_expr!(allow_struct) >>
+        (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.spans)) }
+            |
+            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,
+        })
+    ));
+
+    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,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("block: `{ .. }`")
+        }
+    }
+
+    #[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
+                }
+            })
+        ));
+    }
+
+    #[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)
+            }
+        })
+    ));
+
+    #[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")
+        }
+    }
+
+    #[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: `_`")
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Synom for PatBox {
+        named!(parse -> Self, do_parse!(
+            boxed: keyword!(box) >>
+            pat: syn!(Pat) >>
+            (PatBox {
+                pat: Box::new(pat),
+                box_token: boxed,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("box pattern")
+        }
+    }
+
+    #[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
+            } else {
+                PatLit {
+                    expr: Box::new(lit),
+                }
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("literal pattern")
+        }
+    }
+
+    #[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 description() -> Option<&'static str> {
+            Some("range 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 {
+            Expr::Unary(ExprUnary {
+                attrs: Vec::new(),
+                op: UnOp::Neg(neg),
+                expr: Box::new(v)
+            })
+        } 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.spans)),
+                    comma_token: middle.as_ref().and_then(|m| {
+                        m.1.as_ref().map(|m| Token![,](m.spans))
+                    }),
+                    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")
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl Synom for PatMacro {
+        named!(parse -> Self, map!(syn!(Macro), |mac| PatMacro { mac: mac }));
+
+        fn description() -> Option<&'static str> {
+            Some("macro pattern")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    #[cfg(feature = "full")]
+    use attr::FilterAttrs;
+    use proc_macro2::{Literal, TokenStream};
+    use quote::{ToTokens, TokenStreamExt};
+
+    // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
+    // before appending it to `TokenStream`.
+    #[cfg(feature = "full")]
+    fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
+        if let Expr::Struct(_) = *e {
+            token::Paren::default().surround(tokens, |tokens| {
+                e.to_tokens(tokens);
+            });
+        } else {
+            e.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
+        tokens.append_all(attrs.outer());
+    }
+
+    #[cfg(feature = "full")]
+    fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
+        tokens.append_all(attrs.inner());
+    }
+
+    #[cfg(not(feature = "full"))]
+    fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
+
+    #[cfg(not(feature = "full"))]
+    fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprBox {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.box_token.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprInPlace {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.place.to_tokens(tokens);
+            self.arrow_token.to_tokens(tokens);
+            self.value.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprArray {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.bracket_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                self.elems.to_tokens(tokens);
+            })
+        }
+    }
+
+    impl ToTokens for ExprCall {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.func.to_tokens(tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                self.args.to_tokens(tokens);
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprMethodCall {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.receiver.to_tokens(tokens);
+            self.dot_token.to_tokens(tokens);
+            self.method.to_tokens(tokens);
+            self.turbofish.to_tokens(tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                self.args.to_tokens(tokens);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for MethodTurbofish {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.colon2_token.to_tokens(tokens);
+            self.lt_token.to_tokens(tokens);
+            self.args.to_tokens(tokens);
+            self.gt_token.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for GenericMethodArgument {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
+                GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprTuple {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                self.elems.to_tokens(tokens);
+                // If we only have one argument, we need a trailing comma to
+                // distinguish ExprTuple from ExprParen.
+                if self.elems.len() == 1 && !self.elems.trailing_punct() {
+                    <Token![,]>::default().to_tokens(tokens);
+                }
+            })
+        }
+    }
+
+    impl ToTokens for ExprBinary {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.left.to_tokens(tokens);
+            self.op.to_tokens(tokens);
+            self.right.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ExprUnary {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.op.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ExprLit {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.lit.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ExprCast {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.expr.to_tokens(tokens);
+            self.as_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprType {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.expr.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
+        if let Some((ref else_token, ref else_)) = *else_ {
+            else_token.to_tokens(tokens);
+
+            // If we are not one of the valid expressions to exist in an else
+            // clause, wrap ourselves in a block.
+            match **else_ {
+                Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
+                    else_.to_tokens(tokens);
+                }
+                _ => {
+                    token::Brace::default().surround(tokens, |tokens| {
+                        else_.to_tokens(tokens);
+                    });
+                }
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprIf {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.if_token.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.cond);
+            self.then_branch.to_tokens(tokens);
+            maybe_wrap_else(tokens, &self.else_branch);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprIfLet {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.if_token.to_tokens(tokens);
+            self.let_token.to_tokens(tokens);
+            self.pats.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
+            self.then_branch.to_tokens(tokens);
+            maybe_wrap_else(tokens, &self.else_branch);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprWhile {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.label.to_tokens(tokens);
+            self.while_token.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.cond);
+            self.body.brace_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                tokens.append_all(&self.body.stmts);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprWhileLet {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.label.to_tokens(tokens);
+            self.while_token.to_tokens(tokens);
+            self.let_token.to_tokens(tokens);
+            self.pats.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
+            self.body.brace_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                tokens.append_all(&self.body.stmts);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprForLoop {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.label.to_tokens(tokens);
+            self.for_token.to_tokens(tokens);
+            self.pat.to_tokens(tokens);
+            self.in_token.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
+            self.body.brace_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                tokens.append_all(&self.body.stmts);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprLoop {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.label.to_tokens(tokens);
+            self.loop_token.to_tokens(tokens);
+            self.body.brace_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                tokens.append_all(&self.body.stmts);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprMatch {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.match_token.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
+            self.brace_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                for (i, arm) in self.arms.iter().enumerate() {
+                    arm.to_tokens(tokens);
+                    // 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() {
+                        <Token![,]>::default().to_tokens(tokens);
+                    }
+                }
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprAsync {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, 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);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprYield {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.yield_token.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    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);
+            for input in self.inputs.pairs() {
+                match **input.value() {
+                    FnArg::Captured(ArgCaptured {
+                        ref pat,
+                        ty: Type::Infer(_),
+                        ..
+                    }) => {
+                        pat.to_tokens(tokens);
+                    }
+                    _ => input.value().to_tokens(tokens),
+                }
+                input.punct().to_tokens(tokens);
+            }
+            self.or2_token.to_tokens(tokens);
+            self.output.to_tokens(tokens);
+            self.body.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprUnsafe {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.unsafe_token.to_tokens(tokens);
+            self.block.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    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);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprAssign {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.left.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.right.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprAssignOp {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.left.to_tokens(tokens);
+            self.op.to_tokens(tokens);
+            self.right.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ExprField {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.base.to_tokens(tokens);
+            self.dot_token.to_tokens(tokens);
+            self.member.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for Member {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                Member::Named(ref ident) => ident.to_tokens(tokens),
+                Member::Unnamed(ref index) => index.to_tokens(tokens),
+            }
+        }
+    }
+
+    impl ToTokens for Index {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
+            lit.set_span(self.span);
+            tokens.append(lit);
+        }
+    }
+
+    impl ToTokens for ExprIndex {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.expr.to_tokens(tokens);
+            self.bracket_token.surround(tokens, |tokens| {
+                self.index.to_tokens(tokens);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprRange {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.from.to_tokens(tokens);
+            match self.limits {
+                RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
+                RangeLimits::Closed(ref t) => t.to_tokens(tokens),
+            }
+            self.to.to_tokens(tokens);
+        }
+    }
+
+    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)
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprReference {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.and_token.to_tokens(tokens);
+            self.mutability.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprBreak {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.break_token.to_tokens(tokens);
+            self.label.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprContinue {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.continue_token.to_tokens(tokens);
+            self.label.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprReturn {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.return_token.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprMacro {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.mac.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprStruct {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.path.to_tokens(tokens);
+            self.brace_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                self.fields.to_tokens(tokens);
+                if self.rest.is_some() {
+                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
+                    self.rest.to_tokens(tokens);
+                }
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprRepeat {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.bracket_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                self.expr.to_tokens(tokens);
+                self.semi_token.to_tokens(tokens);
+                self.len.to_tokens(tokens);
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprGroup {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.group_token.surround(tokens, |tokens| {
+                self.expr.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for ExprParen {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                inner_attrs_to_tokens(&self.attrs, tokens);
+                self.expr.to_tokens(tokens);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for ExprTry {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.expr.to_tokens(tokens);
+            self.question_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ExprVerbatim {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.tts.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for Label {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.name.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for FieldValue {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.member.to_tokens(tokens);
+            if let Some(ref colon_token) = self.colon_token {
+                colon_token.to_tokens(tokens);
+                self.expr.to_tokens(tokens);
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for Arm {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(&self.attrs);
+            self.leading_vert.to_tokens(tokens);
+            self.pats.to_tokens(tokens);
+            if let Some((ref if_token, ref guard)) = self.guard {
+                if_token.to_tokens(tokens);
+                guard.to_tokens(tokens);
+            }
+            self.fat_arrow_token.to_tokens(tokens);
+            self.body.to_tokens(tokens);
+            self.comma.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatWild {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.underscore_token.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatIdent {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.by_ref.to_tokens(tokens);
+            self.mutability.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            if let Some((ref at_token, ref subpat)) = self.subpat {
+                at_token.to_tokens(tokens);
+                subpat.to_tokens(tokens);
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatStruct {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.path.to_tokens(tokens);
+            self.brace_token.surround(tokens, |tokens| {
+                self.fields.to_tokens(tokens);
+                // NOTE: We need a comma before the dot2 token if it is present.
+                if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
+                    <Token![,]>::default().to_tokens(tokens);
+                }
+                self.dot2_token.to_tokens(tokens);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatTupleStruct {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.path.to_tokens(tokens);
+            self.pat.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatPath {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatTuple {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.paren_token.surround(tokens, |tokens| {
+                self.front.to_tokens(tokens);
+                if let Some(ref dot2_token) = self.dot2_token {
+                    if !self.front.empty_or_trailing() {
+                        // Ensure there is a comma before the .. token.
+                        <Token![,]>::default().to_tokens(tokens);
+                    }
+                    dot2_token.to_tokens(tokens);
+                    self.comma_token.to_tokens(tokens);
+                    if self.comma_token.is_none() && !self.back.is_empty() {
+                        // Ensure there is a comma after the .. token.
+                        <Token![,]>::default().to_tokens(tokens);
+                    }
+                }
+                self.back.to_tokens(tokens);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatBox {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.box_token.to_tokens(tokens);
+            self.pat.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatRef {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.and_token.to_tokens(tokens);
+            self.mutability.to_tokens(tokens);
+            self.pat.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatLit {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.expr.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatRange {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.lo.to_tokens(tokens);
+            match self.limits {
+                RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
+                RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
+            }
+            self.hi.to_tokens(tokens);
+        }
+    }
+
+    #[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);
+
+                // If we need a comma before the middle or standalone .. token,
+                // then make sure it's present.
+                if !self.front.empty_or_trailing()
+                    && (self.middle.is_some() || self.dot2_token.is_some())
+                {
+                    <Token![,]>::default().to_tokens(tokens);
+                }
+
+                // If we have an identifier, we always need a .. token.
+                if self.middle.is_some() {
+                    self.middle.to_tokens(tokens);
+                    TokensOrDefault(&self.dot2_token).to_tokens(tokens);
+                } else if self.dot2_token.is_some() {
+                    self.dot2_token.to_tokens(tokens);
+                }
+
+                // Make sure we have a comma before the back half.
+                if !self.back.is_empty() {
+                    TokensOrDefault(&self.comma_token).to_tokens(tokens);
+                    self.back.to_tokens(tokens);
+                } else {
+                    self.comma_token.to_tokens(tokens);
+                }
+            })
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatMacro {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.mac.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for PatVerbatim {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.tts.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for FieldPat {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            if let Some(ref colon_token) = self.colon_token {
+                self.member.to_tokens(tokens);
+                colon_token.to_tokens(tokens);
+            }
+            self.pat.to_tokens(tokens);
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for Block {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(&self.stmts);
+            });
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for Stmt {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                Stmt::Local(ref local) => local.to_tokens(tokens),
+                Stmt::Item(ref item) => item.to_tokens(tokens),
+                Stmt::Expr(ref expr) => expr.to_tokens(tokens),
+                Stmt::Semi(ref expr, ref semi) => {
+                    expr.to_tokens(tokens);
+                    semi.to_tokens(tokens);
+                }
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
+    impl ToTokens for Local {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            outer_attrs_to_tokens(&self.attrs, tokens);
+            self.let_token.to_tokens(tokens);
+            self.pats.to_tokens(tokens);
+            if let Some((ref colon_token, ref ty)) = self.ty {
+                colon_token.to_tokens(tokens);
+                ty.to_tokens(tokens);
+            }
+            if let Some((ref eq_token, ref init)) = self.init {
+                eq_token.to_tokens(tokens);
+                init.to_tokens(tokens);
+            }
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+}
diff --git a/src/file.rs b/src/file.rs
new file mode 100644
index 0000000..9b5b11f
--- /dev/null
+++ b/src/file.rs
@@ -0,0 +1,123 @@
+// 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 super::*;
+
+ast_struct! {
+    /// A complete file of Rust source code.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Example
+    ///
+    /// Parse a Rust source file into a `syn::File` and print out a debug
+    /// representation of the syntax tree.
+    ///
+    /// ```
+    /// extern crate syn;
+    ///
+    /// use std::env;
+    /// use std::fs::File;
+    /// use std::io::Read;
+    /// use std::process;
+    ///
+    /// fn main() {
+    /// # }
+    /// #
+    /// # fn fake_main() {
+    ///     let mut args = env::args();
+    ///     let _ = args.next(); // executable name
+    ///
+    ///     let filename = match (args.next(), args.next()) {
+    ///         (Some(filename), None) => filename,
+    ///         _ => {
+    ///             eprintln!("Usage: dump-syntax path/to/filename.rs");
+    ///             process::exit(1);
+    ///         }
+    ///     };
+    ///
+    ///     let mut file = File::open(&filename).expect("Unable to open file");
+    ///
+    ///     let mut src = String::new();
+    ///     file.read_to_string(&mut src).expect("Unable to read file");
+    ///
+    ///     let syntax = syn::parse_file(&src).expect("Unable to parse file");
+    ///     println!("{:#?}", syntax);
+    /// }
+    /// ```
+    ///
+    /// Running with its own source code as input, this program prints output
+    /// that begins with:
+    ///
+    /// ```text
+    /// File {
+    ///     shebang: None,
+    ///     attrs: [],
+    ///     items: [
+    ///         ExternCrate(
+    ///             ItemExternCrate {
+    ///                 attrs: [],
+    ///                 vis: Inherited,
+    ///                 extern_token: Extern,
+    ///                 crate_token: Crate,
+    ///                 ident: Ident {
+    ///                     term: Term(
+    ///                         "syn"
+    ///                     ),
+    ///                     span: Span
+    ///                 },
+    ///                 rename: None,
+    ///                 semi_token: Semi
+    ///             }
+    ///         ),
+    /// ...
+    /// ```
+    pub struct File {
+        pub shebang: Option<String>,
+        pub attrs: Vec<Attribute>,
+        pub items: Vec<Item>,
+    }
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+
+    use synom::Synom;
+
+    impl Synom for File {
+        named!(parse -> Self, do_parse!(
+            attrs: many0!(Attribute::parse_inner) >>
+            items: many0!(Item::parse) >>
+            (File {
+                shebang: None,
+                attrs: attrs,
+                items: items,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("crate")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use attr::FilterAttrs;
+    use proc_macro2::TokenStream;
+    use quote::{ToTokens, TokenStreamExt};
+
+    impl ToTokens for File {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.inner());
+            tokens.append_all(&self.items);
+        }
+    }
+}
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
new file mode 100644
index 0000000..fe1088a
--- /dev/null
+++ b/src/gen/fold.rs
@@ -0,0 +1,3064 @@
+// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT
+
+#![allow(unreachable_code)]
+#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
+#[cfg(any(feature = "full", feature = "derive"))]
+use gen::helper::fold::*;
+use proc_macro2::Span;
+#[cfg(any(feature = "full", feature = "derive"))]
+use token::{Brace, Bracket, Group, Paren};
+use *;
+#[cfg(feature = "full")]
+macro_rules! full {
+    ($e:expr) => {
+        $e
+    };
+}
+#[cfg(all(feature = "derive", not(feature = "full")))]
+macro_rules! full {
+    ($e:expr) => {
+        unreachable!()
+    };
+}
+#[doc = r" Syntax tree traversal to transform the nodes of an owned syntax tree."]
+#[doc = r""]
+#[doc = r" See the [module documentation] for details."]
+#[doc = r""]
+#[doc = r" [module documentation]: index.html"]
+#[doc = r""]
+#[doc = r#" *This trait is available if Syn is built with the `"fold"` feature.*"#]
+pub trait Fold {
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_abi(&mut self, i: Abi) -> Abi {
+        fold_abi(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_angle_bracketed_generic_arguments(
+        &mut self,
+        i: AngleBracketedGenericArguments,
+    ) -> AngleBracketedGenericArguments {
+        fold_angle_bracketed_generic_arguments(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_arg_captured(&mut self, i: ArgCaptured) -> ArgCaptured {
+        fold_arg_captured(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_arg_self(&mut self, i: ArgSelf) -> ArgSelf {
+        fold_arg_self(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_arg_self_ref(&mut self, i: ArgSelfRef) -> ArgSelfRef {
+        fold_arg_self_ref(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_arm(&mut self, i: Arm) -> Arm {
+        fold_arm(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_attr_style(&mut self, i: AttrStyle) -> AttrStyle {
+        fold_attr_style(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_attribute(&mut self, i: Attribute) -> Attribute {
+        fold_attribute(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_bare_fn_arg(&mut self, i: BareFnArg) -> BareFnArg {
+        fold_bare_fn_arg(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_bare_fn_arg_name(&mut self, i: BareFnArgName) -> BareFnArgName {
+        fold_bare_fn_arg_name(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_bin_op(&mut self, i: BinOp) -> BinOp {
+        fold_bin_op(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_binding(&mut self, i: Binding) -> Binding {
+        fold_binding(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_block(&mut self, i: Block) -> Block {
+        fold_block(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_bound_lifetimes(&mut self, i: BoundLifetimes) -> BoundLifetimes {
+        fold_bound_lifetimes(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_const_param(&mut self, i: ConstParam) -> ConstParam {
+        fold_const_param(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn fold_data(&mut self, i: Data) -> Data {
+        fold_data(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn fold_data_enum(&mut self, i: DataEnum) -> DataEnum {
+        fold_data_enum(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn fold_data_struct(&mut self, i: DataStruct) -> DataStruct {
+        fold_data_struct(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn fold_data_union(&mut self, i: DataUnion) -> DataUnion {
+        fold_data_union(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn fold_derive_input(&mut self, i: DeriveInput) -> DeriveInput {
+        fold_derive_input(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr(&mut self, i: Expr) -> Expr {
+        fold_expr(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_array(&mut self, i: ExprArray) -> ExprArray {
+        fold_expr_array(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_assign(&mut self, i: ExprAssign) -> ExprAssign {
+        fold_expr_assign(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_block(&mut self, i: ExprBlock) -> ExprBlock {
+        fold_expr_block(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_box(&mut self, i: ExprBox) -> ExprBox {
+        fold_expr_box(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_break(&mut self, i: ExprBreak) -> ExprBreak {
+        fold_expr_break(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_call(&mut self, i: ExprCall) -> ExprCall {
+        fold_expr_call(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_cast(&mut self, i: ExprCast) -> ExprCast {
+        fold_expr_cast(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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_continue(&mut self, i: ExprContinue) -> ExprContinue {
+        fold_expr_continue(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_field(&mut self, i: ExprField) -> ExprField {
+        fold_expr_field(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_for_loop(&mut self, i: ExprForLoop) -> ExprForLoop {
+        fold_expr_for_loop(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_group(&mut self, i: ExprGroup) -> ExprGroup {
+        fold_expr_group(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_if(&mut self, i: ExprIf) -> ExprIf {
+        fold_expr_if(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_if_let(&mut self, i: ExprIfLet) -> ExprIfLet {
+        fold_expr_if_let(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_in_place(&mut self, i: ExprInPlace) -> ExprInPlace {
+        fold_expr_in_place(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_index(&mut self, i: ExprIndex) -> ExprIndex {
+        fold_expr_index(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_lit(&mut self, i: ExprLit) -> ExprLit {
+        fold_expr_lit(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_loop(&mut self, i: ExprLoop) -> ExprLoop {
+        fold_expr_loop(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_macro(&mut self, i: ExprMacro) -> ExprMacro {
+        fold_expr_macro(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_match(&mut self, i: ExprMatch) -> ExprMatch {
+        fold_expr_match(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_method_call(&mut self, i: ExprMethodCall) -> ExprMethodCall {
+        fold_expr_method_call(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_paren(&mut self, i: ExprParen) -> ExprParen {
+        fold_expr_paren(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_path(&mut self, i: ExprPath) -> ExprPath {
+        fold_expr_path(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_range(&mut self, i: ExprRange) -> ExprRange {
+        fold_expr_range(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_reference(&mut self, i: ExprReference) -> ExprReference {
+        fold_expr_reference(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_repeat(&mut self, i: ExprRepeat) -> ExprRepeat {
+        fold_expr_repeat(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_return(&mut self, i: ExprReturn) -> ExprReturn {
+        fold_expr_return(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_struct(&mut self, i: ExprStruct) -> ExprStruct {
+        fold_expr_struct(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_try(&mut self, i: ExprTry) -> ExprTry {
+        fold_expr_try(self, i)
+    }
+    #[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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_type(&mut self, i: ExprType) -> ExprType {
+        fold_expr_type(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_unary(&mut self, i: ExprUnary) -> ExprUnary {
+        fold_expr_unary(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_unsafe(&mut self, i: ExprUnsafe) -> ExprUnsafe {
+        fold_expr_unsafe(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_verbatim(&mut self, i: ExprVerbatim) -> ExprVerbatim {
+        fold_expr_verbatim(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_while(&mut self, i: ExprWhile) -> ExprWhile {
+        fold_expr_while(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_while_let(&mut self, i: ExprWhileLet) -> ExprWhileLet {
+        fold_expr_while_let(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_expr_yield(&mut self, i: ExprYield) -> ExprYield {
+        fold_expr_yield(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_field(&mut self, i: Field) -> Field {
+        fold_field(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_field_pat(&mut self, i: FieldPat) -> FieldPat {
+        fold_field_pat(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_field_value(&mut self, i: FieldValue) -> FieldValue {
+        fold_field_value(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_fields(&mut self, i: Fields) -> Fields {
+        fold_fields(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_fields_named(&mut self, i: FieldsNamed) -> FieldsNamed {
+        fold_fields_named(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_fields_unnamed(&mut self, i: FieldsUnnamed) -> FieldsUnnamed {
+        fold_fields_unnamed(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_file(&mut self, i: File) -> File {
+        fold_file(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_fn_arg(&mut self, i: FnArg) -> FnArg {
+        fold_fn_arg(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_fn_decl(&mut self, i: FnDecl) -> FnDecl {
+        fold_fn_decl(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_foreign_item(&mut self, i: ForeignItem) -> ForeignItem {
+        fold_foreign_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_foreign_item_fn(&mut self, i: ForeignItemFn) -> ForeignItemFn {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn fold_foreign_item_type(&mut self, i: ForeignItemType) -> ForeignItemType {
+        fold_foreign_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_foreign_item_verbatim(&mut self, i: ForeignItemVerbatim) -> ForeignItemVerbatim {
+        fold_foreign_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_generic_argument(&mut self, i: GenericArgument) -> GenericArgument {
+        fold_generic_argument(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_generic_method_argument(&mut self, i: GenericMethodArgument) -> GenericMethodArgument {
+        fold_generic_method_argument(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_generic_param(&mut self, i: GenericParam) -> GenericParam {
+        fold_generic_param(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_generics(&mut self, i: Generics) -> Generics {
+        fold_generics(self, i)
+    }
+    fn fold_ident(&mut self, i: Ident) -> Ident {
+        fold_ident(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_impl_item(&mut self, i: ImplItem) -> ImplItem {
+        fold_impl_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_impl_item_const(&mut self, i: ImplItemConst) -> ImplItemConst {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn fold_impl_item_method(&mut self, i: ImplItemMethod) -> ImplItemMethod {
+        fold_impl_item_method(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_impl_item_type(&mut self, i: ImplItemType) -> ImplItemType {
+        fold_impl_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_impl_item_verbatim(&mut self, i: ImplItemVerbatim) -> ImplItemVerbatim {
+        fold_impl_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_index(&mut self, i: Index) -> Index {
+        fold_index(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item(&mut self, i: Item) -> Item {
+        fold_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_const(&mut self, i: ItemConst) -> ItemConst {
+        fold_item_const(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_enum(&mut self, i: ItemEnum) -> ItemEnum {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_fn(&mut self, i: ItemFn) -> ItemFn {
+        fold_item_fn(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_foreign_mod(&mut self, i: ItemForeignMod) -> ItemForeignMod {
+        fold_item_foreign_mod(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_impl(&mut self, i: ItemImpl) -> ItemImpl {
+        fold_item_impl(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_macro(&mut self, i: ItemMacro) -> ItemMacro {
+        fold_item_macro(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_macro2(&mut self, i: ItemMacro2) -> ItemMacro2 {
+        fold_item_macro2(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_mod(&mut self, i: ItemMod) -> ItemMod {
+        fold_item_mod(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_static(&mut self, i: ItemStatic) -> ItemStatic {
+        fold_item_static(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_struct(&mut self, i: ItemStruct) -> ItemStruct {
+        fold_item_struct(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_trait(&mut self, i: ItemTrait) -> ItemTrait {
+        fold_item_trait(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_type(&mut self, i: ItemType) -> ItemType {
+        fold_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_union(&mut self, i: ItemUnion) -> ItemUnion {
+        fold_item_union(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_use(&mut self, i: ItemUse) -> ItemUse {
+        fold_item_use(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_item_verbatim(&mut self, i: ItemVerbatim) -> ItemVerbatim {
+        fold_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    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)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lifetime_def(&mut self, i: LifetimeDef) -> LifetimeDef {
+        fold_lifetime_def(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit(&mut self, i: Lit) -> Lit {
+        fold_lit(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_bool(&mut self, i: LitBool) -> LitBool {
+        fold_lit_bool(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_byte(&mut self, i: LitByte) -> LitByte {
+        fold_lit_byte(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_byte_str(&mut self, i: LitByteStr) -> LitByteStr {
+        fold_lit_byte_str(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_char(&mut self, i: LitChar) -> LitChar {
+        fold_lit_char(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_float(&mut self, i: LitFloat) -> LitFloat {
+        fold_lit_float(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_int(&mut self, i: LitInt) -> LitInt {
+        fold_lit_int(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_str(&mut self, i: LitStr) -> LitStr {
+        fold_lit_str(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_lit_verbatim(&mut self, i: LitVerbatim) -> LitVerbatim {
+        fold_lit_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_local(&mut self, i: Local) -> Local {
+        fold_local(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_macro(&mut self, i: Macro) -> Macro {
+        fold_macro(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_macro_delimiter(&mut self, i: MacroDelimiter) -> MacroDelimiter {
+        fold_macro_delimiter(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_member(&mut self, i: Member) -> Member {
+        fold_member(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_meta(&mut self, i: Meta) -> Meta {
+        fold_meta(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_meta_list(&mut self, i: MetaList) -> MetaList {
+        fold_meta_list(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_meta_name_value(&mut self, i: MetaNameValue) -> MetaNameValue {
+        fold_meta_name_value(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_method_sig(&mut self, i: MethodSig) -> MethodSig {
+        fold_method_sig(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_method_turbofish(&mut self, i: MethodTurbofish) -> MethodTurbofish {
+        fold_method_turbofish(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_nested_meta(&mut self, i: NestedMeta) -> NestedMeta {
+        fold_nested_meta(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_parenthesized_generic_arguments(
+        &mut self,
+        i: ParenthesizedGenericArguments,
+    ) -> ParenthesizedGenericArguments {
+        fold_parenthesized_generic_arguments(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat(&mut self, i: Pat) -> Pat {
+        fold_pat(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_box(&mut self, i: PatBox) -> PatBox {
+        fold_pat_box(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_ident(&mut self, i: PatIdent) -> PatIdent {
+        fold_pat_ident(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_lit(&mut self, i: PatLit) -> PatLit {
+        fold_pat_lit(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_macro(&mut self, i: PatMacro) -> PatMacro {
+        fold_pat_macro(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_path(&mut self, i: PatPath) -> PatPath {
+        fold_pat_path(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_range(&mut self, i: PatRange) -> PatRange {
+        fold_pat_range(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_ref(&mut self, i: PatRef) -> PatRef {
+        fold_pat_ref(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_slice(&mut self, i: PatSlice) -> PatSlice {
+        fold_pat_slice(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_struct(&mut self, i: PatStruct) -> PatStruct {
+        fold_pat_struct(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_tuple(&mut self, i: PatTuple) -> PatTuple {
+        fold_pat_tuple(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_tuple_struct(&mut self, i: PatTupleStruct) -> PatTupleStruct {
+        fold_pat_tuple_struct(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_verbatim(&mut self, i: PatVerbatim) -> PatVerbatim {
+        fold_pat_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_pat_wild(&mut self, i: PatWild) -> PatWild {
+        fold_pat_wild(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_path(&mut self, i: Path) -> Path {
+        fold_path(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_path_arguments(&mut self, i: PathArguments) -> PathArguments {
+        fold_path_arguments(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_path_segment(&mut self, i: PathSegment) -> PathSegment {
+        fold_path_segment(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_predicate_eq(&mut self, i: PredicateEq) -> PredicateEq {
+        fold_predicate_eq(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_predicate_lifetime(&mut self, i: PredicateLifetime) -> PredicateLifetime {
+        fold_predicate_lifetime(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_predicate_type(&mut self, i: PredicateType) -> PredicateType {
+        fold_predicate_type(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_qself(&mut self, i: QSelf) -> QSelf {
+        fold_qself(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_range_limits(&mut self, i: RangeLimits) -> RangeLimits {
+        fold_range_limits(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_return_type(&mut self, i: ReturnType) -> ReturnType {
+        fold_return_type(self, i)
+    }
+    fn fold_span(&mut self, i: Span) -> Span {
+        fold_span(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn fold_stmt(&mut self, i: Stmt) -> Stmt {
+        fold_stmt(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_trait_bound(&mut self, i: TraitBound) -> TraitBound {
+        fold_trait_bound(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_trait_bound_modifier(&mut self, i: TraitBoundModifier) -> TraitBoundModifier {
+        fold_trait_bound_modifier(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_trait_item(&mut self, i: TraitItem) -> TraitItem {
+        fold_trait_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_trait_item_const(&mut self, i: TraitItemConst) -> TraitItemConst {
+        fold_trait_item_const(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_trait_item_existential(&mut self, i: TraitItemExistential) -> TraitItemExistential {
+        fold_trait_item_existential(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_trait_item_macro(&mut self, i: TraitItemMacro) -> TraitItemMacro {
+        fold_trait_item_macro(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_trait_item_method(&mut self, i: TraitItemMethod) -> TraitItemMethod {
+        fold_trait_item_method(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_trait_item_type(&mut self, i: TraitItemType) -> TraitItemType {
+        fold_trait_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_trait_item_verbatim(&mut self, i: TraitItemVerbatim) -> TraitItemVerbatim {
+        fold_trait_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type(&mut self, i: Type) -> Type {
+        fold_type(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_array(&mut self, i: TypeArray) -> TypeArray {
+        fold_type_array(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_bare_fn(&mut self, i: TypeBareFn) -> TypeBareFn {
+        fold_type_bare_fn(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_group(&mut self, i: TypeGroup) -> TypeGroup {
+        fold_type_group(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_impl_trait(&mut self, i: TypeImplTrait) -> TypeImplTrait {
+        fold_type_impl_trait(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_infer(&mut self, i: TypeInfer) -> TypeInfer {
+        fold_type_infer(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_macro(&mut self, i: TypeMacro) -> TypeMacro {
+        fold_type_macro(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_never(&mut self, i: TypeNever) -> TypeNever {
+        fold_type_never(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_param(&mut self, i: TypeParam) -> TypeParam {
+        fold_type_param(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_param_bound(&mut self, i: TypeParamBound) -> TypeParamBound {
+        fold_type_param_bound(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_paren(&mut self, i: TypeParen) -> TypeParen {
+        fold_type_paren(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_path(&mut self, i: TypePath) -> TypePath {
+        fold_type_path(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_ptr(&mut self, i: TypePtr) -> TypePtr {
+        fold_type_ptr(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_reference(&mut self, i: TypeReference) -> TypeReference {
+        fold_type_reference(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_slice(&mut self, i: TypeSlice) -> TypeSlice {
+        fold_type_slice(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_trait_object(&mut self, i: TypeTraitObject) -> TypeTraitObject {
+        fold_type_trait_object(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_tuple(&mut self, i: TypeTuple) -> TypeTuple {
+        fold_type_tuple(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_type_verbatim(&mut self, i: TypeVerbatim) -> TypeVerbatim {
+        fold_type_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_un_op(&mut self, i: UnOp) -> UnOp {
+        fold_un_op(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_use_glob(&mut self, i: UseGlob) -> UseGlob {
+        fold_use_glob(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_use_group(&mut self, i: UseGroup) -> UseGroup {
+        fold_use_group(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_use_name(&mut self, i: UseName) -> UseName {
+        fold_use_name(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_use_path(&mut self, i: UsePath) -> UsePath {
+        fold_use_path(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_use_rename(&mut self, i: UseRename) -> UseRename {
+        fold_use_rename(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn fold_use_tree(&mut self, i: UseTree) -> UseTree {
+        fold_use_tree(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_variant(&mut self, i: Variant) -> Variant {
+        fold_variant(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_vis_crate(&mut self, i: VisCrate) -> VisCrate {
+        fold_vis_crate(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_vis_public(&mut self, i: VisPublic) -> VisPublic {
+        fold_vis_public(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_vis_restricted(&mut self, i: VisRestricted) -> VisRestricted {
+        fold_vis_restricted(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_visibility(&mut self, i: Visibility) -> Visibility {
+        fold_visibility(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_where_clause(&mut self, i: WhereClause) -> WhereClause {
+        fold_where_clause(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn fold_where_predicate(&mut self, i: WherePredicate) -> WherePredicate {
+        fold_where_predicate(self, i)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! fold_span_only {
+    ($f:ident : $t:ident) => {
+        pub fn $f<V: Fold + ?Sized>(_visitor: &mut V, mut _i: $t) -> $t {
+            let span = _visitor.fold_span(_i.span());
+            _i.set_span(span);
+            _i
+        }
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+fold_span_only!(fold_lit_byte: LitByte);
+#[cfg(any(feature = "full", feature = "derive"))]
+fold_span_only!(fold_lit_byte_str: LitByteStr);
+#[cfg(any(feature = "full", feature = "derive"))]
+fold_span_only!(fold_lit_char: LitChar);
+#[cfg(any(feature = "full", feature = "derive"))]
+fold_span_only!(fold_lit_float: LitFloat);
+#[cfg(any(feature = "full", feature = "derive"))]
+fold_span_only!(fold_lit_int: LitInt);
+#[cfg(any(feature = "full", feature = "derive"))]
+fold_span_only!(fold_lit_str: LitStr);
+#[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.span)),
+        name: (_i.name).map(|it| _visitor.fold_lit_str(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_angle_bracketed_generic_arguments<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: AngleBracketedGenericArguments,
+) -> AngleBracketedGenericArguments {
+    AngleBracketedGenericArguments {
+        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.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.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.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.spans)),
+        lifetime: (_i.lifetime).map(|it| _visitor.fold_lifetime(it)),
+        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"))]
+#[cfg(feature = "full")]
+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.spans))),
+        pats: FoldHelper::lift(_i.pats, |it| _visitor.fold_pat(it)),
+        guard: (_i.guard).map(|it| {
+            (
+                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.spans)),
+        body: Box::new(_visitor.fold_expr(*_i.body)),
+        comma: (_i.comma).map(|it| Token ! [ , ](tokens_helper(_visitor, &it.spans))),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_attr_style<V: Fold + ?Sized>(_visitor: &mut V, _i: AttrStyle) -> AttrStyle {
+    match _i {
+        AttrStyle::Outer => AttrStyle::Outer,
+        AttrStyle::Inner(_binding_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.spans)),
+        style: _visitor.fold_attr_style(_i.style),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
+        path: _visitor.fold_path(_i.path),
+        tts: _i.tts,
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_bare_fn_arg<V: Fold + ?Sized>(_visitor: &mut V, _i: BareFnArg) -> BareFnArg {
+    BareFnArg {
+        name: (_i.name).map(|it| {
+            (
+                _visitor.fold_bare_fn_arg_name((it).0),
+                Token ! [ : ](tokens_helper(_visitor, &(it).1.spans)),
+            )
+        }),
+        ty: _visitor.fold_type(_i.ty),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_bare_fn_arg_name<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: BareFnArgName,
+) -> BareFnArgName {
+    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.spans)))
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans)))
+        }
+        BinOp::Sub(_binding_0) => {
+            BinOp::Sub(Token ! [ - ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Mul(_binding_0) => {
+            BinOp::Mul(Token ! [ * ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Div(_binding_0) => {
+            BinOp::Div(Token ! [ / ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Rem(_binding_0) => {
+            BinOp::Rem(Token ! [ % ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::And(_binding_0) => {
+            BinOp::And(Token ! [ && ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Or(_binding_0) => {
+            BinOp::Or(Token ! [ || ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::BitXor(_binding_0) => {
+            BinOp::BitXor(Token ! [ ^ ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::BitAnd(_binding_0) => {
+            BinOp::BitAnd(Token ! [ & ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::BitOr(_binding_0) => {
+            BinOp::BitOr(Token ! [ | ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Shl(_binding_0) => {
+            BinOp::Shl(Token ! [ << ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Shr(_binding_0) => {
+            BinOp::Shr(Token ! [ >> ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Eq(_binding_0) => {
+            BinOp::Eq(Token ! [ == ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        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.spans)))
+        }
+        BinOp::Ne(_binding_0) => {
+            BinOp::Ne(Token ! [ != ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::Ge(_binding_0) => {
+            BinOp::Ge(Token ! [ >= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        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.spans)))
+        }
+        BinOp::SubEq(_binding_0) => {
+            BinOp::SubEq(Token ! [ -= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::MulEq(_binding_0) => {
+            BinOp::MulEq(Token ! [ *= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::DivEq(_binding_0) => {
+            BinOp::DivEq(Token ! [ /= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::RemEq(_binding_0) => {
+            BinOp::RemEq(Token ! [ %= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::BitXorEq(_binding_0) => {
+            BinOp::BitXorEq(Token ! [ ^= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::BitAndEq(_binding_0) => {
+            BinOp::BitAndEq(Token ! [ &= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::BitOrEq(_binding_0) => {
+            BinOp::BitOrEq(Token ! [ |= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::ShlEq(_binding_0) => {
+            BinOp::ShlEq(Token ! [ <<= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+        BinOp::ShrEq(_binding_0) => {
+            BinOp::ShrEq(Token ! [ >>= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans)),
+        ty: _visitor.fold_type(_i.ty),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.span)),
+        stmts: FoldHelper::lift(_i.stmts, |it| _visitor.fold_stmt(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_bound_lifetimes<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: BoundLifetimes,
+) -> BoundLifetimes {
+    BoundLifetimes {
+        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.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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        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.spans))),
+        default: (_i.default).map(|it| _visitor.fold_expr(it)),
+    }
+}
+#[cfg(feature = "derive")]
+pub fn fold_data<V: Fold + ?Sized>(_visitor: &mut V, _i: Data) -> Data {
+    match _i {
+        Data::Struct(_binding_0) => Data::Struct(_visitor.fold_data_struct(_binding_0)),
+        Data::Enum(_binding_0) => Data::Enum(_visitor.fold_data_enum(_binding_0)),
+        Data::Union(_binding_0) => Data::Union(_visitor.fold_data_union(_binding_0)),
+    }
+}
+#[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.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.span)),
+        fields: _visitor.fold_fields(_i.fields),
+        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.span)),
+        fields: _visitor.fold_fields_named(_i.fields),
+    }
+}
+#[cfg(feature = "derive")]
+pub fn fold_derive_input<V: Fold + ?Sized>(_visitor: &mut V, _i: DeriveInput) -> DeriveInput {
+    DeriveInput {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        vis: _visitor.fold_visibility(_i.vis),
+        ident: _visitor.fold_ident(_i.ident),
+        generics: _visitor.fold_generics(_i.generics),
+        data: _visitor.fold_data(_i.data),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr<V: Fold + ?Sized>(_visitor: &mut V, _i: Expr) -> Expr {
+    match _i {
+        Expr::Box(_binding_0) => Expr::Box(full!(_visitor.fold_expr_box(_binding_0))),
+        Expr::InPlace(_binding_0) => Expr::InPlace(full!(_visitor.fold_expr_in_place(_binding_0))),
+        Expr::Array(_binding_0) => Expr::Array(full!(_visitor.fold_expr_array(_binding_0))),
+        Expr::Call(_binding_0) => Expr::Call(_visitor.fold_expr_call(_binding_0)),
+        Expr::MethodCall(_binding_0) => {
+            Expr::MethodCall(full!(_visitor.fold_expr_method_call(_binding_0)))
+        }
+        Expr::Tuple(_binding_0) => Expr::Tuple(full!(_visitor.fold_expr_tuple(_binding_0))),
+        Expr::Binary(_binding_0) => Expr::Binary(_visitor.fold_expr_binary(_binding_0)),
+        Expr::Unary(_binding_0) => Expr::Unary(_visitor.fold_expr_unary(_binding_0)),
+        Expr::Lit(_binding_0) => Expr::Lit(_visitor.fold_expr_lit(_binding_0)),
+        Expr::Cast(_binding_0) => Expr::Cast(_visitor.fold_expr_cast(_binding_0)),
+        Expr::Type(_binding_0) => Expr::Type(full!(_visitor.fold_expr_type(_binding_0))),
+        Expr::If(_binding_0) => Expr::If(full!(_visitor.fold_expr_if(_binding_0))),
+        Expr::IfLet(_binding_0) => Expr::IfLet(full!(_visitor.fold_expr_if_let(_binding_0))),
+        Expr::While(_binding_0) => Expr::While(full!(_visitor.fold_expr_while(_binding_0))),
+        Expr::WhileLet(_binding_0) => {
+            Expr::WhileLet(full!(_visitor.fold_expr_while_let(_binding_0)))
+        }
+        Expr::ForLoop(_binding_0) => Expr::ForLoop(full!(_visitor.fold_expr_for_loop(_binding_0))),
+        Expr::Loop(_binding_0) => Expr::Loop(full!(_visitor.fold_expr_loop(_binding_0))),
+        Expr::Match(_binding_0) => Expr::Match(full!(_visitor.fold_expr_match(_binding_0))),
+        Expr::Closure(_binding_0) => Expr::Closure(full!(_visitor.fold_expr_closure(_binding_0))),
+        Expr::Unsafe(_binding_0) => Expr::Unsafe(full!(_visitor.fold_expr_unsafe(_binding_0))),
+        Expr::Block(_binding_0) => Expr::Block(full!(_visitor.fold_expr_block(_binding_0))),
+        Expr::Assign(_binding_0) => Expr::Assign(full!(_visitor.fold_expr_assign(_binding_0))),
+        Expr::AssignOp(_binding_0) => {
+            Expr::AssignOp(full!(_visitor.fold_expr_assign_op(_binding_0)))
+        }
+        Expr::Field(_binding_0) => Expr::Field(_visitor.fold_expr_field(_binding_0)),
+        Expr::Index(_binding_0) => Expr::Index(_visitor.fold_expr_index(_binding_0)),
+        Expr::Range(_binding_0) => Expr::Range(full!(_visitor.fold_expr_range(_binding_0))),
+        Expr::Path(_binding_0) => Expr::Path(_visitor.fold_expr_path(_binding_0)),
+        Expr::Reference(_binding_0) => {
+            Expr::Reference(full!(_visitor.fold_expr_reference(_binding_0)))
+        }
+        Expr::Break(_binding_0) => Expr::Break(full!(_visitor.fold_expr_break(_binding_0))),
+        Expr::Continue(_binding_0) => {
+            Expr::Continue(full!(_visitor.fold_expr_continue(_binding_0)))
+        }
+        Expr::Return(_binding_0) => Expr::Return(full!(_visitor.fold_expr_return(_binding_0))),
+        Expr::Macro(_binding_0) => Expr::Macro(full!(_visitor.fold_expr_macro(_binding_0))),
+        Expr::Struct(_binding_0) => Expr::Struct(full!(_visitor.fold_expr_struct(_binding_0))),
+        Expr::Repeat(_binding_0) => Expr::Repeat(full!(_visitor.fold_expr_repeat(_binding_0))),
+        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::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)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        elems: FoldHelper::lift(_i.elems, |it| _visitor.fold_expr(it)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_assign<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprAssign) -> ExprAssign {
+    ExprAssign {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        left: Box::new(_visitor.fold_expr(*_i.left)),
+        eq_token: Token ! [ = ](tokens_helper(_visitor, &_i.eq_token.spans)),
+        right: Box::new(_visitor.fold_expr(*_i.right)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_assign_op<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprAssignOp) -> ExprAssignOp {
+    ExprAssignOp {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        left: Box::new(_visitor.fold_expr(*_i.left)),
+        op: _visitor.fold_bin_op(_i.op),
+        right: Box::new(_visitor.fold_expr(*_i.right)),
+    }
+}
+#[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 {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        left: Box::new(_visitor.fold_expr(*_i.left)),
+        op: _visitor.fold_bin_op(_i.op),
+        right: Box::new(_visitor.fold_expr(*_i.right)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        label: (_i.label).map(|it| _visitor.fold_lifetime(it)),
+        expr: (_i.expr).map(|it| Box::new(_visitor.fold_expr(*it))),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_call<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprCall) -> ExprCall {
+    ExprCall {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        func: Box::new(_visitor.fold_expr(*_i.func)),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
+        args: FoldHelper::lift(_i.args, |it| _visitor.fold_expr(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_cast<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprCast) -> ExprCast {
+    ExprCast {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        as_token: Token ! [ as ](tokens_helper(_visitor, &_i.as_token.span)),
+        ty: Box::new(_visitor.fold_type(*_i.ty)),
+    }
+}
+#[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)),
+        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.spans)),
+        output: _visitor.fold_return_type(_i.output),
+        body: Box::new(_visitor.fold_expr(*_i.body)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        label: (_i.label).map(|it| _visitor.fold_lifetime(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_field<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprField) -> ExprField {
+    ExprField {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        base: Box::new(_visitor.fold_expr(*_i.base)),
+        dot_token: Token ! [ . ](tokens_helper(_visitor, &_i.dot_token.spans)),
+        member: _visitor.fold_member(_i.member),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_for_loop<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprForLoop) -> ExprForLoop {
+    ExprForLoop {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        label: (_i.label).map(|it| _visitor.fold_label(it)),
+        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.span)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        body: _visitor.fold_block(_i.body),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.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.span)),
+                Box::new(_visitor.fold_expr(*(it).1)),
+            )
+        }),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.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.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.span)),
+                Box::new(_visitor.fold_expr(*(it).1)),
+            )
+        }),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_in_place<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprInPlace) -> ExprInPlace {
+    ExprInPlace {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        place: Box::new(_visitor.fold_expr(*_i.place)),
+        arrow_token: Token ! [ <- ](tokens_helper(_visitor, &_i.arrow_token.spans)),
+        value: Box::new(_visitor.fold_expr(*_i.value)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_index<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprIndex) -> ExprIndex {
+    ExprIndex {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        bracket_token: Bracket(tokens_helper(_visitor, &_i.bracket_token.span)),
+        index: Box::new(_visitor.fold_expr(*_i.index)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_lit<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprLit) -> ExprLit {
+    ExprLit {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        lit: _visitor.fold_lit(_i.lit),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_loop<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprLoop) -> ExprLoop {
+    ExprLoop {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        label: (_i.label).map(|it| _visitor.fold_label(it)),
+        loop_token: Token ! [ loop ](tokens_helper(_visitor, &_i.loop_token.span)),
+        body: _visitor.fold_block(_i.body),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_macro<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprMacro) -> ExprMacro {
+    ExprMacro {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        mac: _visitor.fold_macro(_i.mac),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
+        arms: FoldHelper::lift(_i.arms, |it| _visitor.fold_arm(it)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_method_call<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ExprMethodCall,
+) -> ExprMethodCall {
+    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.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.span)),
+        args: FoldHelper::lift(_i.args, |it| _visitor.fold_expr(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_path<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprPath) -> ExprPath {
+    ExprPath {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        qself: (_i.qself).map(|it| _visitor.fold_qself(it)),
+        path: _visitor.fold_path(_i.path),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_range<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprRange) -> ExprRange {
+    ExprRange {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        from: (_i.from).map(|it| Box::new(_visitor.fold_expr(*it))),
+        limits: _visitor.fold_range_limits(_i.limits),
+        to: (_i.to).map(|it| Box::new(_visitor.fold_expr(*it))),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+        len: Box::new(_visitor.fold_expr(*_i.len)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        expr: (_i.expr).map(|it| Box::new(_visitor.fold_expr(*it))),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_struct<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprStruct) -> ExprStruct {
+    ExprStruct {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        path: _visitor.fold_path(_i.path),
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
+        fields: FoldHelper::lift(_i.fields, |it| _visitor.fold_field_value(it)),
+        dot2_token: (_i.dot2_token).map(|it| Token![..](tokens_helper(_visitor, &it.spans))),
+        rest: (_i.rest).map(|it| Box::new(_visitor.fold_expr(*it))),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_try<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprTry) -> ExprTry {
+    ExprTry {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        question_token: Token ! [ ? ](tokens_helper(_visitor, &_i.question_token.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")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        elems: FoldHelper::lift(_i.elems, |it| _visitor.fold_expr(it)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_type<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprType) -> ExprType {
+    ExprType {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        colon_token: Token ! [ : ](tokens_helper(_visitor, &_i.colon_token.spans)),
+        ty: Box::new(_visitor.fold_type(*_i.ty)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_unary<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprUnary) -> ExprUnary {
+    ExprUnary {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        op: _visitor.fold_un_op(_i.op),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        block: _visitor.fold_block(_i.block),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_verbatim<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprVerbatim) -> ExprVerbatim {
+    ExprVerbatim { tts: _i.tts }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_while<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprWhile) -> ExprWhile {
+    ExprWhile {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        label: (_i.label).map(|it| _visitor.fold_label(it)),
+        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),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_expr_while_let<V: Fold + ?Sized>(_visitor: &mut V, _i: ExprWhileLet) -> ExprWhileLet {
+    ExprWhileLet {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        label: (_i.label).map(|it| _visitor.fold_label(it)),
+        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.spans)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        body: _visitor.fold_block(_i.body),
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        expr: (_i.expr).map(|it| Box::new(_visitor.fold_expr(*it))),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_field<V: Fold + ?Sized>(_visitor: &mut V, _i: Field) -> Field {
+    Field {
+        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.spans))),
+        ty: _visitor.fold_type(_i.ty),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_field_pat<V: Fold + ?Sized>(_visitor: &mut V, _i: FieldPat) -> FieldPat {
+    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.spans))),
+        pat: Box::new(_visitor.fold_pat(*_i.pat)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_field_value<V: Fold + ?Sized>(_visitor: &mut V, _i: FieldValue) -> FieldValue {
+    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.spans))),
+        expr: _visitor.fold_expr(_i.expr),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_fields<V: Fold + ?Sized>(_visitor: &mut V, _i: Fields) -> Fields {
+    match _i {
+        Fields::Named(_binding_0) => Fields::Named(_visitor.fold_fields_named(_binding_0)),
+        Fields::Unnamed(_binding_0) => Fields::Unnamed(_visitor.fold_fields_unnamed(_binding_0)),
+        Fields::Unit => Fields::Unit,
+    }
+}
+#[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.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.span)),
+        unnamed: FoldHelper::lift(_i.unnamed, |it| _visitor.fold_field(it)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_file<V: Fold + ?Sized>(_visitor: &mut V, _i: File) -> File {
+    File {
+        shebang: _i.shebang,
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        items: FoldHelper::lift(_i.items, |it| _visitor.fold_item(it)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_fn_arg<V: Fold + ?Sized>(_visitor: &mut V, _i: FnArg) -> FnArg {
+    match _i {
+        FnArg::SelfRef(_binding_0) => FnArg::SelfRef(_visitor.fold_arg_self_ref(_binding_0)),
+        FnArg::SelfValue(_binding_0) => FnArg::SelfValue(_visitor.fold_arg_self(_binding_0)),
+        FnArg::Captured(_binding_0) => FnArg::Captured(_visitor.fold_arg_captured(_binding_0)),
+        FnArg::Inferred(_binding_0) => FnArg::Inferred(_visitor.fold_pat(_binding_0)),
+        FnArg::Ignored(_binding_0) => FnArg::Ignored(_visitor.fold_type(_binding_0)),
+    }
+}
+#[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.span)),
+        generics: _visitor.fold_generics(_i.generics),
+        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.spans))),
+        output: _visitor.fold_return_type(_i.output),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_foreign_item<V: Fold + ?Sized>(_visitor: &mut V, _i: ForeignItem) -> ForeignItem {
+    match _i {
+        ForeignItem::Fn(_binding_0) => ForeignItem::Fn(_visitor.fold_foreign_item_fn(_binding_0)),
+        ForeignItem::Static(_binding_0) => {
+            ForeignItem::Static(_visitor.fold_foreign_item_static(_binding_0))
+        }
+        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))
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_foreign_item_fn<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ForeignItemFn,
+) -> ForeignItemFn {
+    ForeignItemFn {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        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.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")]
+pub fn fold_foreign_item_static<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ForeignItemStatic,
+) -> ForeignItemStatic {
+    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.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.spans)),
+        ty: Box::new(_visitor.fold_type(*_i.ty)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_foreign_item_type<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ForeignItemType,
+) -> ForeignItemType {
+    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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_foreign_item_verbatim<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ForeignItemVerbatim,
+) -> ForeignItemVerbatim {
+    ForeignItemVerbatim { tts: _i.tts }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_generic_argument<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: GenericArgument,
+) -> GenericArgument {
+    match _i {
+        GenericArgument::Lifetime(_binding_0) => {
+            GenericArgument::Lifetime(_visitor.fold_lifetime(_binding_0))
+        }
+        GenericArgument::Type(_binding_0) => GenericArgument::Type(_visitor.fold_type(_binding_0)),
+        GenericArgument::Binding(_binding_0) => {
+            GenericArgument::Binding(_visitor.fold_binding(_binding_0))
+        }
+        GenericArgument::Const(_binding_0) => {
+            GenericArgument::Const(_visitor.fold_expr(_binding_0))
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_generic_method_argument<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: GenericMethodArgument,
+) -> GenericMethodArgument {
+    match _i {
+        GenericMethodArgument::Type(_binding_0) => {
+            GenericMethodArgument::Type(_visitor.fold_type(_binding_0))
+        }
+        GenericMethodArgument::Const(_binding_0) => {
+            GenericMethodArgument::Const(_visitor.fold_expr(_binding_0))
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_generic_param<V: Fold + ?Sized>(_visitor: &mut V, _i: GenericParam) -> GenericParam {
+    match _i {
+        GenericParam::Type(_binding_0) => GenericParam::Type(_visitor.fold_type_param(_binding_0)),
+        GenericParam::Lifetime(_binding_0) => {
+            GenericParam::Lifetime(_visitor.fold_lifetime_def(_binding_0))
+        }
+        GenericParam::Const(_binding_0) => {
+            GenericParam::Const(_visitor.fold_const_param(_binding_0))
+        }
+    }
+}
+#[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.spans))),
+        params: FoldHelper::lift(_i.params, |it| _visitor.fold_generic_param(it)),
+        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)),
+    }
+}
+pub fn fold_ident<V: Fold + ?Sized>(_visitor: &mut V, _i: Ident) -> Ident {
+    let mut _i = _i;
+    let span = _visitor.fold_span(_i.span());
+    _i.set_span(span);
+    _i
+}
+#[cfg(feature = "full")]
+pub fn fold_impl_item<V: Fold + ?Sized>(_visitor: &mut V, _i: ImplItem) -> ImplItem {
+    match _i {
+        ImplItem::Const(_binding_0) => ImplItem::Const(_visitor.fold_impl_item_const(_binding_0)),
+        ImplItem::Method(_binding_0) => {
+            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))
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_impl_item_const<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ImplItemConst,
+) -> ImplItemConst {
+    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.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.spans)),
+        ty: _visitor.fold_type(_i.ty),
+        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.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")]
+pub fn fold_impl_item_macro<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ImplItemMacro,
+) -> ImplItemMacro {
+    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.spans))),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_impl_item_method<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ImplItemMethod,
+) -> ImplItemMethod {
+    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.span))),
+        sig: _visitor.fold_method_sig(_i.sig),
+        block: _visitor.fold_block(_i.block),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_impl_item_type<V: Fold + ?Sized>(_visitor: &mut V, _i: ImplItemType) -> ImplItemType {
+    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.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.spans)),
+        ty: _visitor.fold_type(_i.ty),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_impl_item_verbatim<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ImplItemVerbatim,
+) -> ImplItemVerbatim {
+    ImplItemVerbatim { tts: _i.tts }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_index<V: Fold + ?Sized>(_visitor: &mut V, _i: Index) -> Index {
+    Index {
+        index: _i.index,
+        span: _visitor.fold_span(_i.span),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item<V: Fold + ?Sized>(_visitor: &mut V, _i: Item) -> Item {
+    match _i {
+        Item::ExternCrate(_binding_0) => {
+            Item::ExternCrate(_visitor.fold_item_extern_crate(_binding_0))
+        }
+        Item::Use(_binding_0) => Item::Use(_visitor.fold_item_use(_binding_0)),
+        Item::Static(_binding_0) => Item::Static(_visitor.fold_item_static(_binding_0)),
+        Item::Const(_binding_0) => Item::Const(_visitor.fold_item_const(_binding_0)),
+        Item::Fn(_binding_0) => Item::Fn(_visitor.fold_item_fn(_binding_0)),
+        Item::Mod(_binding_0) => Item::Mod(_visitor.fold_item_mod(_binding_0)),
+        Item::ForeignMod(_binding_0) => {
+            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::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)),
+        Item::Verbatim(_binding_0) => Item::Verbatim(_visitor.fold_item_verbatim(_binding_0)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_const<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemConst) -> ItemConst {
+    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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        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.spans)),
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_enum<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemEnum) -> ItemEnum {
+    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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        generics: _visitor.fold_generics(_i.generics),
+        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,
+) -> ItemExternCrate {
+    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.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.span)),
+                _visitor.fold_ident((it).1),
+            )
+        }),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_fn<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemFn) -> ItemFn {
+    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.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)),
+        block: Box::new(_visitor.fold_block(*_i.block)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_foreign_mod<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ItemForeignMod,
+) -> ItemForeignMod {
+    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.span)),
+        items: FoldHelper::lift(_i.items, |it| _visitor.fold_foreign_item(it)),
+    }
+}
+#[cfg(feature = "full")]
+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.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.spans))),
+                _visitor.fold_path((it).1),
+                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.span)),
+        items: FoldHelper::lift(_i.items, |it| _visitor.fold_impl_item(it)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_macro<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemMacro) -> ItemMacro {
+    ItemMacro {
+        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.spans))),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_macro2<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemMacro2) -> ItemMacro2 {
+    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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        paren_token: Paren(tokens_helper(_visitor, &_i.paren_token.span)),
+        args: _i.args,
+        brace_token: Brace(tokens_helper(_visitor, &_i.brace_token.span)),
+        body: _i.body,
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_mod<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemMod) -> ItemMod {
+    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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        content: (_i.content).map(|it| {
+            (
+                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.spans))),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_static<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemStatic) -> ItemStatic {
+    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.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.spans)),
+        ty: Box::new(_visitor.fold_type(*_i.ty)),
+        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.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_struct<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemStruct) -> ItemStruct {
+    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.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.spans))),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_trait<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemTrait) -> ItemTrait {
+    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.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.spans))),
+        supertraits: FoldHelper::lift(_i.supertraits, |it| _visitor.fold_type_param_bound(it)),
+        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_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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        generics: _visitor.fold_generics(_i.generics),
+        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.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_union<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemUnion) -> ItemUnion {
+    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.span)),
+        ident: _visitor.fold_ident(_i.ident),
+        generics: _visitor.fold_generics(_i.generics),
+        fields: _visitor.fold_fields_named(_i.fields),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_use<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemUse) -> ItemUse {
+    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.span)),
+        leading_colon: (_i.leading_colon)
+            .map(|it| Token ! [ :: ](tokens_helper(_visitor, &it.spans))),
+        tree: _visitor.fold_use_tree(_i.tree),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_item_verbatim<V: Fold + ?Sized>(_visitor: &mut V, _i: ItemVerbatim) -> ItemVerbatim {
+    ItemVerbatim { tts: _i.tts }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+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.spans)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_lifetime<V: Fold + ?Sized>(_visitor: &mut V, _i: Lifetime) -> Lifetime {
+    Lifetime {
+        apostrophe: _i.apostrophe,
+        ident: _visitor.fold_ident(_i.ident),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_lifetime_def<V: Fold + ?Sized>(_visitor: &mut V, _i: LifetimeDef) -> LifetimeDef {
+    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.spans))),
+        bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_lifetime(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_lit<V: Fold + ?Sized>(_visitor: &mut V, _i: Lit) -> Lit {
+    match _i {
+        Lit::Str(_binding_0) => Lit::Str(_visitor.fold_lit_str(_binding_0)),
+        Lit::ByteStr(_binding_0) => Lit::ByteStr(_visitor.fold_lit_byte_str(_binding_0)),
+        Lit::Byte(_binding_0) => Lit::Byte(_visitor.fold_lit_byte(_binding_0)),
+        Lit::Char(_binding_0) => Lit::Char(_visitor.fold_lit_char(_binding_0)),
+        Lit::Int(_binding_0) => Lit::Int(_visitor.fold_lit_int(_binding_0)),
+        Lit::Float(_binding_0) => Lit::Float(_visitor.fold_lit_float(_binding_0)),
+        Lit::Bool(_binding_0) => Lit::Bool(_visitor.fold_lit_bool(_binding_0)),
+        Lit::Verbatim(_binding_0) => Lit::Verbatim(_visitor.fold_lit_verbatim(_binding_0)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_lit_bool<V: Fold + ?Sized>(_visitor: &mut V, _i: LitBool) -> LitBool {
+    LitBool {
+        value: _i.value,
+        span: _visitor.fold_span(_i.span),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_lit_verbatim<V: Fold + ?Sized>(_visitor: &mut V, _i: LitVerbatim) -> LitVerbatim {
+    LitVerbatim { token: _i.token }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+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.span)),
+        pats: FoldHelper::lift(_i.pats, |it| _visitor.fold_pat(it)),
+        ty: (_i.ty).map(|it| {
+            (
+                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.spans)),
+                Box::new(_visitor.fold_expr(*(it).1)),
+            )
+        }),
+        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.spans)),
+        delimiter: _visitor.fold_macro_delimiter(_i.delimiter),
+        tts: _i.tts,
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_macro_delimiter<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: MacroDelimiter,
+) -> MacroDelimiter {
+    match _i {
+        MacroDelimiter::Paren(_binding_0) => {
+            MacroDelimiter::Paren(Paren(tokens_helper(_visitor, &_binding_0.span)))
+        }
+        MacroDelimiter::Brace(_binding_0) => {
+            MacroDelimiter::Brace(Brace(tokens_helper(_visitor, &_binding_0.span)))
+        }
+        MacroDelimiter::Bracket(_binding_0) => {
+            MacroDelimiter::Bracket(Bracket(tokens_helper(_visitor, &_binding_0.span)))
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_member<V: Fold + ?Sized>(_visitor: &mut V, _i: Member) -> Member {
+    match _i {
+        Member::Named(_binding_0) => Member::Named(_visitor.fold_ident(_binding_0)),
+        Member::Unnamed(_binding_0) => Member::Unnamed(_visitor.fold_index(_binding_0)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_meta<V: Fold + ?Sized>(_visitor: &mut V, _i: Meta) -> Meta {
+    match _i {
+        Meta::Word(_binding_0) => Meta::Word(_visitor.fold_ident(_binding_0)),
+        Meta::List(_binding_0) => Meta::List(_visitor.fold_meta_list(_binding_0)),
+        Meta::NameValue(_binding_0) => Meta::NameValue(_visitor.fold_meta_name_value(_binding_0)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span)),
+        nested: FoldHelper::lift(_i.nested, |it| _visitor.fold_nested_meta(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_meta_name_value<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: MetaNameValue,
+) -> MetaNameValue {
+    MetaNameValue {
+        ident: _visitor.fold_ident(_i.ident),
+        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.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),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_method_turbofish<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: MethodTurbofish,
+) -> MethodTurbofish {
+    MethodTurbofish {
+        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.spans)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_nested_meta<V: Fold + ?Sized>(_visitor: &mut V, _i: NestedMeta) -> NestedMeta {
+    match _i {
+        NestedMeta::Meta(_binding_0) => NestedMeta::Meta(_visitor.fold_meta(_binding_0)),
+        NestedMeta::Literal(_binding_0) => NestedMeta::Literal(_visitor.fold_lit(_binding_0)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_parenthesized_generic_arguments<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: ParenthesizedGenericArguments,
+) -> ParenthesizedGenericArguments {
+    ParenthesizedGenericArguments {
+        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),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_pat<V: Fold + ?Sized>(_visitor: &mut V, _i: Pat) -> Pat {
+    match _i {
+        Pat::Wild(_binding_0) => Pat::Wild(_visitor.fold_pat_wild(_binding_0)),
+        Pat::Ident(_binding_0) => Pat::Ident(_visitor.fold_pat_ident(_binding_0)),
+        Pat::Struct(_binding_0) => Pat::Struct(_visitor.fold_pat_struct(_binding_0)),
+        Pat::TupleStruct(_binding_0) => {
+            Pat::TupleStruct(_visitor.fold_pat_tuple_struct(_binding_0))
+        }
+        Pat::Path(_binding_0) => Pat::Path(_visitor.fold_pat_path(_binding_0)),
+        Pat::Tuple(_binding_0) => Pat::Tuple(_visitor.fold_pat_tuple(_binding_0)),
+        Pat::Box(_binding_0) => Pat::Box(_visitor.fold_pat_box(_binding_0)),
+        Pat::Ref(_binding_0) => Pat::Ref(_visitor.fold_pat_ref(_binding_0)),
+        Pat::Lit(_binding_0) => Pat::Lit(_visitor.fold_pat_lit(_binding_0)),
+        Pat::Range(_binding_0) => Pat::Range(_visitor.fold_pat_range(_binding_0)),
+        Pat::Slice(_binding_0) => Pat::Slice(_visitor.fold_pat_slice(_binding_0)),
+        Pat::Macro(_binding_0) => Pat::Macro(_visitor.fold_pat_macro(_binding_0)),
+        Pat::Verbatim(_binding_0) => Pat::Verbatim(_visitor.fold_pat_verbatim(_binding_0)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.span)),
+        pat: Box::new(_visitor.fold_pat(*_i.pat)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.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.spans)),
+                Box::new(_visitor.fold_pat(*(it).1)),
+            )
+        }),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_pat_lit<V: Fold + ?Sized>(_visitor: &mut V, _i: PatLit) -> PatLit {
+    PatLit {
+        expr: Box::new(_visitor.fold_expr(*_i.expr)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_pat_macro<V: Fold + ?Sized>(_visitor: &mut V, _i: PatMacro) -> PatMacro {
+    PatMacro {
+        mac: _visitor.fold_macro(_i.mac),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_pat_path<V: Fold + ?Sized>(_visitor: &mut V, _i: PatPath) -> PatPath {
+    PatPath {
+        qself: (_i.qself).map(|it| _visitor.fold_qself(it)),
+        path: _visitor.fold_path(_i.path),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_pat_range<V: Fold + ?Sized>(_visitor: &mut V, _i: PatRange) -> PatRange {
+    PatRange {
+        lo: Box::new(_visitor.fold_expr(*_i.lo)),
+        limits: _visitor.fold_range_limits(_i.limits),
+        hi: Box::new(_visitor.fold_expr(*_i.hi)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.spans)),
+        mutability: (_i.mutability).map(|it| Token ! [ mut ](tokens_helper(_visitor, &it.span))),
+        pat: Box::new(_visitor.fold_pat(*_i.pat)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.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.spans))),
+        comma_token: (_i.comma_token).map(|it| Token ! [ , ](tokens_helper(_visitor, &it.spans))),
+        back: FoldHelper::lift(_i.back, |it| _visitor.fold_pat(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+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.span)),
+        fields: FoldHelper::lift(_i.fields, |it| _visitor.fold_field_pat(it)),
+        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.span)),
+        front: FoldHelper::lift(_i.front, |it| _visitor.fold_pat(it)),
+        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)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_pat_tuple_struct<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: PatTupleStruct,
+) -> PatTupleStruct {
+    PatTupleStruct {
+        path: _visitor.fold_path(_i.path),
+        pat: _visitor.fold_pat_tuple(_i.pat),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_pat_verbatim<V: Fold + ?Sized>(_visitor: &mut V, _i: PatVerbatim) -> PatVerbatim {
+    PatVerbatim { tts: _i.tts }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.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.spans))),
+        segments: FoldHelper::lift(_i.segments, |it| _visitor.fold_path_segment(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_path_arguments<V: Fold + ?Sized>(_visitor: &mut V, _i: PathArguments) -> PathArguments {
+    match _i {
+        PathArguments::None => PathArguments::None,
+        PathArguments::AngleBracketed(_binding_0) => PathArguments::AngleBracketed(
+            _visitor.fold_angle_bracketed_generic_arguments(_binding_0),
+        ),
+        PathArguments::Parenthesized(_binding_0) => {
+            PathArguments::Parenthesized(_visitor.fold_parenthesized_generic_arguments(_binding_0))
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_path_segment<V: Fold + ?Sized>(_visitor: &mut V, _i: PathSegment) -> PathSegment {
+    PathSegment {
+        ident: _visitor.fold_ident(_i.ident),
+        arguments: _visitor.fold_path_arguments(_i.arguments),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans)),
+        rhs_ty: _visitor.fold_type(_i.rhs_ty),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_predicate_lifetime<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: PredicateLifetime,
+) -> PredicateLifetime {
+    PredicateLifetime {
+        lifetime: _visitor.fold_lifetime(_i.lifetime),
+        colon_token: (_i.colon_token).map(|it| Token ! [ : ](tokens_helper(_visitor, &it.spans))),
+        bounds: FoldHelper::lift(_i.bounds, |it| _visitor.fold_lifetime(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_predicate_type<V: Fold + ?Sized>(_visitor: &mut V, _i: PredicateType) -> PredicateType {
+    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.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.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.span))),
+        gt_token: Token ! [ > ](tokens_helper(_visitor, &_i.gt_token.spans)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+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.spans)))
+        }
+        RangeLimits::Closed(_binding_0) => {
+            RangeLimits::Closed(Token ! [ ..= ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_return_type<V: Fold + ?Sized>(_visitor: &mut V, _i: ReturnType) -> ReturnType {
+    match _i {
+        ReturnType::Default => ReturnType::Default,
+        ReturnType::Type(_binding_0, _binding_1) => ReturnType::Type(
+            Token ! [ -> ](tokens_helper(_visitor, &_binding_0.spans)),
+            Box::new(_visitor.fold_type(*_binding_1)),
+        ),
+    }
+}
+pub fn fold_span<V: Fold + ?Sized>(_visitor: &mut V, _i: Span) -> Span {
+    _i
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn fold_stmt<V: Fold + ?Sized>(_visitor: &mut V, _i: Stmt) -> Stmt {
+    match _i {
+        Stmt::Local(_binding_0) => Stmt::Local(_visitor.fold_local(_binding_0)),
+        Stmt::Item(_binding_0) => Stmt::Item(_visitor.fold_item(_binding_0)),
+        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.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.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),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_trait_bound_modifier<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TraitBoundModifier,
+) -> TraitBoundModifier {
+    match _i {
+        TraitBoundModifier::None => TraitBoundModifier::None,
+        TraitBoundModifier::Maybe(_binding_0) => {
+            TraitBoundModifier::Maybe(Token ! [ ? ](tokens_helper(_visitor, &_binding_0.spans)))
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_trait_item<V: Fold + ?Sized>(_visitor: &mut V, _i: TraitItem) -> TraitItem {
+    match _i {
+        TraitItem::Const(_binding_0) => {
+            TraitItem::Const(_visitor.fold_trait_item_const(_binding_0))
+        }
+        TraitItem::Method(_binding_0) => {
+            TraitItem::Method(_visitor.fold_trait_item_method(_binding_0))
+        }
+        TraitItem::Type(_binding_0) => TraitItem::Type(_visitor.fold_trait_item_type(_binding_0)),
+        TraitItem::Existential(_binding_0) => {
+            TraitItem::Existential(_visitor.fold_trait_item_existential(_binding_0))
+        }
+        TraitItem::Macro(_binding_0) => {
+            TraitItem::Macro(_visitor.fold_trait_item_macro(_binding_0))
+        }
+        TraitItem::Verbatim(_binding_0) => {
+            TraitItem::Verbatim(_visitor.fold_trait_item_verbatim(_binding_0))
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_trait_item_const<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TraitItemConst,
+) -> TraitItemConst {
+    TraitItemConst {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        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.spans)),
+        ty: _visitor.fold_type(_i.ty),
+        default: (_i.default).map(|it| {
+            (
+                Token ! [ = ](tokens_helper(_visitor, &(it).0.spans)),
+                _visitor.fold_expr((it).1),
+            )
+        }),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_trait_item_existential<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TraitItemExistential,
+) -> TraitItemExistential {
+    TraitItemExistential {
+        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")]
+pub fn fold_trait_item_macro<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TraitItemMacro,
+) -> TraitItemMacro {
+    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.spans))),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_trait_item_method<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TraitItemMethod,
+) -> TraitItemMethod {
+    TraitItemMethod {
+        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.spans))),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_trait_item_type<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TraitItemType,
+) -> TraitItemType {
+    TraitItemType {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        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)),
+        default: (_i.default).map(|it| {
+            (
+                Token ! [ = ](tokens_helper(_visitor, &(it).0.spans)),
+                _visitor.fold_type((it).1),
+            )
+        }),
+        semi_token: Token ! [ ; ](tokens_helper(_visitor, &_i.semi_token.spans)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_trait_item_verbatim<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TraitItemVerbatim,
+) -> TraitItemVerbatim {
+    TraitItemVerbatim { tts: _i.tts }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type<V: Fold + ?Sized>(_visitor: &mut V, _i: Type) -> Type {
+    match _i {
+        Type::Slice(_binding_0) => Type::Slice(_visitor.fold_type_slice(_binding_0)),
+        Type::Array(_binding_0) => Type::Array(_visitor.fold_type_array(_binding_0)),
+        Type::Ptr(_binding_0) => Type::Ptr(_visitor.fold_type_ptr(_binding_0)),
+        Type::Reference(_binding_0) => Type::Reference(_visitor.fold_type_reference(_binding_0)),
+        Type::BareFn(_binding_0) => Type::BareFn(_visitor.fold_type_bare_fn(_binding_0)),
+        Type::Never(_binding_0) => Type::Never(_visitor.fold_type_never(_binding_0)),
+        Type::Tuple(_binding_0) => Type::Tuple(_visitor.fold_type_tuple(_binding_0)),
+        Type::Path(_binding_0) => Type::Path(_visitor.fold_type_path(_binding_0)),
+        Type::TraitObject(_binding_0) => {
+            Type::TraitObject(_visitor.fold_type_trait_object(_binding_0))
+        }
+        Type::ImplTrait(_binding_0) => Type::ImplTrait(_visitor.fold_type_impl_trait(_binding_0)),
+        Type::Paren(_binding_0) => Type::Paren(_visitor.fold_type_paren(_binding_0)),
+        Type::Group(_binding_0) => Type::Group(_visitor.fold_type_group(_binding_0)),
+        Type::Infer(_binding_0) => Type::Infer(_visitor.fold_type_infer(_binding_0)),
+        Type::Macro(_binding_0) => Type::Macro(_visitor.fold_type_macro(_binding_0)),
+        Type::Verbatim(_binding_0) => Type::Verbatim(_visitor.fold_type_verbatim(_binding_0)),
+    }
+}
+#[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.span)),
+        elem: Box::new(_visitor.fold_type(*_i.elem)),
+        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.span))),
+        abi: (_i.abi).map(|it| _visitor.fold_abi(it)),
+        fn_token: Token ! [ fn ](tokens_helper(_visitor, &_i.fn_token.span)),
+        lifetimes: (_i.lifetimes).map(|it| _visitor.fold_bound_lifetimes(it)),
+        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.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.span)),
+        elem: Box::new(_visitor.fold_type(*_i.elem)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type_impl_trait<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TypeImplTrait,
+) -> TypeImplTrait {
+    TypeImplTrait {
+        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.spans)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type_macro<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeMacro) -> TypeMacro {
+    TypeMacro {
+        mac: _visitor.fold_macro(_i.mac),
+    }
+}
+#[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.spans)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type_param<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeParam) -> TypeParam {
+    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.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.spans))),
+        default: (_i.default).map(|it| _visitor.fold_type(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type_param_bound<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TypeParamBound,
+) -> TypeParamBound {
+    match _i {
+        TypeParamBound::Trait(_binding_0) => {
+            TypeParamBound::Trait(_visitor.fold_trait_bound(_binding_0))
+        }
+        TypeParamBound::Lifetime(_binding_0) => {
+            TypeParamBound::Lifetime(_visitor.fold_lifetime(_binding_0))
+        }
+    }
+}
+#[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.span)),
+        elem: Box::new(_visitor.fold_type(*_i.elem)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type_path<V: Fold + ?Sized>(_visitor: &mut V, _i: TypePath) -> TypePath {
+    TypePath {
+        qself: (_i.qself).map(|it| _visitor.fold_qself(it)),
+        path: _visitor.fold_path(_i.path),
+    }
+}
+#[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.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.spans)),
+        lifetime: (_i.lifetime).map(|it| _visitor.fold_lifetime(it)),
+        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.span)),
+        elem: Box::new(_visitor.fold_type(*_i.elem)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type_trait_object<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: TypeTraitObject,
+) -> TypeTraitObject {
+    TypeTraitObject {
+        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.span)),
+        elems: FoldHelper::lift(_i.elems, |it| _visitor.fold_type(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_type_verbatim<V: Fold + ?Sized>(_visitor: &mut V, _i: TypeVerbatim) -> TypeVerbatim {
+    TypeVerbatim { tts: _i.tts }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans)))
+        }
+        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.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.span)),
+        items: FoldHelper::lift(_i.items, |it| _visitor.fold_use_tree(it)),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_use_name<V: Fold + ?Sized>(_visitor: &mut V, _i: UseName) -> UseName {
+    UseName {
+        ident: _visitor.fold_ident(_i.ident),
+    }
+}
+#[cfg(feature = "full")]
+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.spans)),
+        tree: Box::new(_visitor.fold_use_tree(*_i.tree)),
+    }
+}
+#[cfg(feature = "full")]
+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.span)),
+        rename: _visitor.fold_ident(_i.rename),
+    }
+}
+#[cfg(feature = "full")]
+pub fn fold_use_tree<V: Fold + ?Sized>(_visitor: &mut V, _i: UseTree) -> UseTree {
+    match _i {
+        UseTree::Path(_binding_0) => UseTree::Path(_visitor.fold_use_path(_binding_0)),
+        UseTree::Name(_binding_0) => UseTree::Name(_visitor.fold_use_name(_binding_0)),
+        UseTree::Rename(_binding_0) => UseTree::Rename(_visitor.fold_use_rename(_binding_0)),
+        UseTree::Glob(_binding_0) => UseTree::Glob(_visitor.fold_use_glob(_binding_0)),
+        UseTree::Group(_binding_0) => UseTree::Group(_visitor.fold_use_group(_binding_0)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_variant<V: Fold + ?Sized>(_visitor: &mut V, _i: Variant) -> Variant {
+    Variant {
+        attrs: FoldHelper::lift(_i.attrs, |it| _visitor.fold_attribute(it)),
+        ident: _visitor.fold_ident(_i.ident),
+        fields: _visitor.fold_fields(_i.fields),
+        discriminant: (_i.discriminant).map(|it| {
+            (
+                Token ! [ = ](tokens_helper(_visitor, &(it).0.spans)),
+                _visitor.fold_expr((it).1),
+            )
+        }),
+    }
+}
+#[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.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.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.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)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_visibility<V: Fold + ?Sized>(_visitor: &mut V, _i: Visibility) -> Visibility {
+    match _i {
+        Visibility::Public(_binding_0) => Visibility::Public(_visitor.fold_vis_public(_binding_0)),
+        Visibility::Crate(_binding_0) => Visibility::Crate(_visitor.fold_vis_crate(_binding_0)),
+        Visibility::Restricted(_binding_0) => {
+            Visibility::Restricted(_visitor.fold_vis_restricted(_binding_0))
+        }
+        Visibility::Inherited => Visibility::Inherited,
+    }
+}
+#[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.span)),
+        predicates: FoldHelper::lift(_i.predicates, |it| _visitor.fold_where_predicate(it)),
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn fold_where_predicate<V: Fold + ?Sized>(
+    _visitor: &mut V,
+    _i: WherePredicate,
+) -> WherePredicate {
+    match _i {
+        WherePredicate::Type(_binding_0) => {
+            WherePredicate::Type(_visitor.fold_predicate_type(_binding_0))
+        }
+        WherePredicate::Lifetime(_binding_0) => {
+            WherePredicate::Lifetime(_visitor.fold_predicate_lifetime(_binding_0))
+        }
+        WherePredicate::Eq(_binding_0) => {
+            WherePredicate::Eq(_visitor.fold_predicate_eq(_binding_0))
+        }
+    }
+}
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
new file mode 100644
index 0000000..7d15422
--- /dev/null
+++ b/src/gen/visit.rs
@@ -0,0 +1,3517 @@
+// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT
+
+#![cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
+#[cfg(any(feature = "full", feature = "derive"))]
+use gen::helper::visit::*;
+use proc_macro2::Span;
+#[cfg(any(feature = "full", feature = "derive"))]
+use punctuated::Punctuated;
+use *;
+#[cfg(feature = "full")]
+macro_rules! full {
+    ($e:expr) => {
+        $e
+    };
+}
+#[cfg(all(feature = "derive", not(feature = "full")))]
+macro_rules! full {
+    ($e:expr) => {
+        unreachable!()
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! skip {
+    ($($tt:tt)*) => {};
+}
+#[doc = r" Syntax tree traversal to walk a shared borrow of a syntax tree."]
+#[doc = r""]
+#[doc = r" See the [module documentation] for details."]
+#[doc = r""]
+#[doc = r" [module documentation]: index.html"]
+#[doc = r""]
+#[doc = r#" *This trait is available if Syn is built with the `"visit"` feature.*"#]
+pub trait Visit<'ast> {
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_abi(&mut self, i: &'ast Abi) {
+        visit_abi(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_angle_bracketed_generic_arguments(&mut self, i: &'ast AngleBracketedGenericArguments) {
+        visit_angle_bracketed_generic_arguments(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_arg_captured(&mut self, i: &'ast ArgCaptured) {
+        visit_arg_captured(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_arg_self(&mut self, i: &'ast ArgSelf) {
+        visit_arg_self(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_arg_self_ref(&mut self, i: &'ast ArgSelfRef) {
+        visit_arg_self_ref(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_arm(&mut self, i: &'ast Arm) {
+        visit_arm(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_attr_style(&mut self, i: &'ast AttrStyle) {
+        visit_attr_style(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_attribute(&mut self, i: &'ast Attribute) {
+        visit_attribute(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bare_fn_arg(&mut self, i: &'ast BareFnArg) {
+        visit_bare_fn_arg(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bare_fn_arg_name(&mut self, i: &'ast BareFnArgName) {
+        visit_bare_fn_arg_name(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bin_op(&mut self, i: &'ast BinOp) {
+        visit_bin_op(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_binding(&mut self, i: &'ast Binding) {
+        visit_binding(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_block(&mut self, i: &'ast Block) {
+        visit_block(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bound_lifetimes(&mut self, i: &'ast BoundLifetimes) {
+        visit_bound_lifetimes(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_const_param(&mut self, i: &'ast ConstParam) {
+        visit_const_param(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data(&mut self, i: &'ast Data) {
+        visit_data(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data_enum(&mut self, i: &'ast DataEnum) {
+        visit_data_enum(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data_struct(&mut self, i: &'ast DataStruct) {
+        visit_data_struct(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data_union(&mut self, i: &'ast DataUnion) {
+        visit_data_union(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_derive_input(&mut self, i: &'ast DeriveInput) {
+        visit_derive_input(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr(&mut self, i: &'ast Expr) {
+        visit_expr(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_array(&mut self, i: &'ast ExprArray) {
+        visit_expr_array(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_assign(&mut self, i: &'ast ExprAssign) {
+        visit_expr_assign(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_block(&mut self, i: &'ast ExprBlock) {
+        visit_expr_block(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_box(&mut self, i: &'ast ExprBox) {
+        visit_expr_box(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_break(&mut self, i: &'ast ExprBreak) {
+        visit_expr_break(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_call(&mut self, i: &'ast ExprCall) {
+        visit_expr_call(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_cast(&mut self, i: &'ast ExprCast) {
+        visit_expr_cast(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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_continue(&mut self, i: &'ast ExprContinue) {
+        visit_expr_continue(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_field(&mut self, i: &'ast ExprField) {
+        visit_expr_field(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_for_loop(&mut self, i: &'ast ExprForLoop) {
+        visit_expr_for_loop(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_group(&mut self, i: &'ast ExprGroup) {
+        visit_expr_group(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_if(&mut self, i: &'ast ExprIf) {
+        visit_expr_if(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_if_let(&mut self, i: &'ast ExprIfLet) {
+        visit_expr_if_let(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_in_place(&mut self, i: &'ast ExprInPlace) {
+        visit_expr_in_place(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_index(&mut self, i: &'ast ExprIndex) {
+        visit_expr_index(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_lit(&mut self, i: &'ast ExprLit) {
+        visit_expr_lit(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_loop(&mut self, i: &'ast ExprLoop) {
+        visit_expr_loop(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_macro(&mut self, i: &'ast ExprMacro) {
+        visit_expr_macro(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_match(&mut self, i: &'ast ExprMatch) {
+        visit_expr_match(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_method_call(&mut self, i: &'ast ExprMethodCall) {
+        visit_expr_method_call(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_paren(&mut self, i: &'ast ExprParen) {
+        visit_expr_paren(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_path(&mut self, i: &'ast ExprPath) {
+        visit_expr_path(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_range(&mut self, i: &'ast ExprRange) {
+        visit_expr_range(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_reference(&mut self, i: &'ast ExprReference) {
+        visit_expr_reference(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_repeat(&mut self, i: &'ast ExprRepeat) {
+        visit_expr_repeat(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_return(&mut self, i: &'ast ExprReturn) {
+        visit_expr_return(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_struct(&mut self, i: &'ast ExprStruct) {
+        visit_expr_struct(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_try(&mut self, i: &'ast ExprTry) {
+        visit_expr_try(self, i)
+    }
+    #[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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_type(&mut self, i: &'ast ExprType) {
+        visit_expr_type(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_unary(&mut self, i: &'ast ExprUnary) {
+        visit_expr_unary(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_unsafe(&mut self, i: &'ast ExprUnsafe) {
+        visit_expr_unsafe(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_verbatim(&mut self, i: &'ast ExprVerbatim) {
+        visit_expr_verbatim(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_while(&mut self, i: &'ast ExprWhile) {
+        visit_expr_while(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_while_let(&mut self, i: &'ast ExprWhileLet) {
+        visit_expr_while_let(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_yield(&mut self, i: &'ast ExprYield) {
+        visit_expr_yield(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_field(&mut self, i: &'ast Field) {
+        visit_field(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_field_pat(&mut self, i: &'ast FieldPat) {
+        visit_field_pat(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_field_value(&mut self, i: &'ast FieldValue) {
+        visit_field_value(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_fields(&mut self, i: &'ast Fields) {
+        visit_fields(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_fields_named(&mut self, i: &'ast FieldsNamed) {
+        visit_fields_named(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_fields_unnamed(&mut self, i: &'ast FieldsUnnamed) {
+        visit_fields_unnamed(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_file(&mut self, i: &'ast File) {
+        visit_file(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_fn_arg(&mut self, i: &'ast FnArg) {
+        visit_fn_arg(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_fn_decl(&mut self, i: &'ast FnDecl) {
+        visit_fn_decl(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item(&mut self, i: &'ast ForeignItem) {
+        visit_foreign_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item_fn(&mut self, i: &'ast ForeignItemFn) {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item_type(&mut self, i: &'ast ForeignItemType) {
+        visit_foreign_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item_verbatim(&mut self, i: &'ast ForeignItemVerbatim) {
+        visit_foreign_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_generic_argument(&mut self, i: &'ast GenericArgument) {
+        visit_generic_argument(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_generic_method_argument(&mut self, i: &'ast GenericMethodArgument) {
+        visit_generic_method_argument(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_generic_param(&mut self, i: &'ast GenericParam) {
+        visit_generic_param(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_generics(&mut self, i: &'ast Generics) {
+        visit_generics(self, i)
+    }
+    fn visit_ident(&mut self, i: &'ast Ident) {
+        visit_ident(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item(&mut self, i: &'ast ImplItem) {
+        visit_impl_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_const(&mut self, i: &'ast ImplItemConst) {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_method(&mut self, i: &'ast ImplItemMethod) {
+        visit_impl_item_method(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_type(&mut self, i: &'ast ImplItemType) {
+        visit_impl_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_verbatim(&mut self, i: &'ast ImplItemVerbatim) {
+        visit_impl_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_index(&mut self, i: &'ast Index) {
+        visit_index(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item(&mut self, i: &'ast Item) {
+        visit_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_const(&mut self, i: &'ast ItemConst) {
+        visit_item_const(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_enum(&mut self, i: &'ast ItemEnum) {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_fn(&mut self, i: &'ast ItemFn) {
+        visit_item_fn(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_foreign_mod(&mut self, i: &'ast ItemForeignMod) {
+        visit_item_foreign_mod(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_impl(&mut self, i: &'ast ItemImpl) {
+        visit_item_impl(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_macro(&mut self, i: &'ast ItemMacro) {
+        visit_item_macro(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_macro2(&mut self, i: &'ast ItemMacro2) {
+        visit_item_macro2(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_mod(&mut self, i: &'ast ItemMod) {
+        visit_item_mod(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_static(&mut self, i: &'ast ItemStatic) {
+        visit_item_static(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_struct(&mut self, i: &'ast ItemStruct) {
+        visit_item_struct(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_trait(&mut self, i: &'ast ItemTrait) {
+        visit_item_trait(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_type(&mut self, i: &'ast ItemType) {
+        visit_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_union(&mut self, i: &'ast ItemUnion) {
+        visit_item_union(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_use(&mut self, i: &'ast ItemUse) {
+        visit_item_use(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_verbatim(&mut self, i: &'ast ItemVerbatim) {
+        visit_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    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)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lifetime_def(&mut self, i: &'ast LifetimeDef) {
+        visit_lifetime_def(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit(&mut self, i: &'ast Lit) {
+        visit_lit(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_bool(&mut self, i: &'ast LitBool) {
+        visit_lit_bool(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_byte(&mut self, i: &'ast LitByte) {
+        visit_lit_byte(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_byte_str(&mut self, i: &'ast LitByteStr) {
+        visit_lit_byte_str(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_char(&mut self, i: &'ast LitChar) {
+        visit_lit_char(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_float(&mut self, i: &'ast LitFloat) {
+        visit_lit_float(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_int(&mut self, i: &'ast LitInt) {
+        visit_lit_int(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_str(&mut self, i: &'ast LitStr) {
+        visit_lit_str(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_verbatim(&mut self, i: &'ast LitVerbatim) {
+        visit_lit_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_local(&mut self, i: &'ast Local) {
+        visit_local(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_macro(&mut self, i: &'ast Macro) {
+        visit_macro(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_macro_delimiter(&mut self, i: &'ast MacroDelimiter) {
+        visit_macro_delimiter(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_member(&mut self, i: &'ast Member) {
+        visit_member(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_meta(&mut self, i: &'ast Meta) {
+        visit_meta(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_meta_list(&mut self, i: &'ast MetaList) {
+        visit_meta_list(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_meta_name_value(&mut self, i: &'ast MetaNameValue) {
+        visit_meta_name_value(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_method_sig(&mut self, i: &'ast MethodSig) {
+        visit_method_sig(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_method_turbofish(&mut self, i: &'ast MethodTurbofish) {
+        visit_method_turbofish(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_nested_meta(&mut self, i: &'ast NestedMeta) {
+        visit_nested_meta(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_parenthesized_generic_arguments(&mut self, i: &'ast ParenthesizedGenericArguments) {
+        visit_parenthesized_generic_arguments(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat(&mut self, i: &'ast Pat) {
+        visit_pat(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_box(&mut self, i: &'ast PatBox) {
+        visit_pat_box(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_ident(&mut self, i: &'ast PatIdent) {
+        visit_pat_ident(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_lit(&mut self, i: &'ast PatLit) {
+        visit_pat_lit(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_macro(&mut self, i: &'ast PatMacro) {
+        visit_pat_macro(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_path(&mut self, i: &'ast PatPath) {
+        visit_pat_path(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_range(&mut self, i: &'ast PatRange) {
+        visit_pat_range(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_ref(&mut self, i: &'ast PatRef) {
+        visit_pat_ref(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_slice(&mut self, i: &'ast PatSlice) {
+        visit_pat_slice(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_struct(&mut self, i: &'ast PatStruct) {
+        visit_pat_struct(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_tuple(&mut self, i: &'ast PatTuple) {
+        visit_pat_tuple(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_tuple_struct(&mut self, i: &'ast PatTupleStruct) {
+        visit_pat_tuple_struct(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_verbatim(&mut self, i: &'ast PatVerbatim) {
+        visit_pat_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_wild(&mut self, i: &'ast PatWild) {
+        visit_pat_wild(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_path(&mut self, i: &'ast Path) {
+        visit_path(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_path_arguments(&mut self, i: &'ast PathArguments) {
+        visit_path_arguments(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_path_segment(&mut self, i: &'ast PathSegment) {
+        visit_path_segment(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_predicate_eq(&mut self, i: &'ast PredicateEq) {
+        visit_predicate_eq(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_predicate_lifetime(&mut self, i: &'ast PredicateLifetime) {
+        visit_predicate_lifetime(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_predicate_type(&mut self, i: &'ast PredicateType) {
+        visit_predicate_type(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_qself(&mut self, i: &'ast QSelf) {
+        visit_qself(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_range_limits(&mut self, i: &'ast RangeLimits) {
+        visit_range_limits(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_return_type(&mut self, i: &'ast ReturnType) {
+        visit_return_type(self, i)
+    }
+    fn visit_span(&mut self, i: &'ast Span) {
+        visit_span(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_stmt(&mut self, i: &'ast Stmt) {
+        visit_stmt(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_trait_bound(&mut self, i: &'ast TraitBound) {
+        visit_trait_bound(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_trait_bound_modifier(&mut self, i: &'ast TraitBoundModifier) {
+        visit_trait_bound_modifier(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item(&mut self, i: &'ast TraitItem) {
+        visit_trait_item(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_const(&mut self, i: &'ast TraitItemConst) {
+        visit_trait_item_const(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_existential(&mut self, i: &'ast TraitItemExistential) {
+        visit_trait_item_existential(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_macro(&mut self, i: &'ast TraitItemMacro) {
+        visit_trait_item_macro(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_method(&mut self, i: &'ast TraitItemMethod) {
+        visit_trait_item_method(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_type(&mut self, i: &'ast TraitItemType) {
+        visit_trait_item_type(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_verbatim(&mut self, i: &'ast TraitItemVerbatim) {
+        visit_trait_item_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type(&mut self, i: &'ast Type) {
+        visit_type(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_array(&mut self, i: &'ast TypeArray) {
+        visit_type_array(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_bare_fn(&mut self, i: &'ast TypeBareFn) {
+        visit_type_bare_fn(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_group(&mut self, i: &'ast TypeGroup) {
+        visit_type_group(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_impl_trait(&mut self, i: &'ast TypeImplTrait) {
+        visit_type_impl_trait(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_infer(&mut self, i: &'ast TypeInfer) {
+        visit_type_infer(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_macro(&mut self, i: &'ast TypeMacro) {
+        visit_type_macro(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_never(&mut self, i: &'ast TypeNever) {
+        visit_type_never(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_param(&mut self, i: &'ast TypeParam) {
+        visit_type_param(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_param_bound(&mut self, i: &'ast TypeParamBound) {
+        visit_type_param_bound(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_paren(&mut self, i: &'ast TypeParen) {
+        visit_type_paren(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_path(&mut self, i: &'ast TypePath) {
+        visit_type_path(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_ptr(&mut self, i: &'ast TypePtr) {
+        visit_type_ptr(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_reference(&mut self, i: &'ast TypeReference) {
+        visit_type_reference(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_slice(&mut self, i: &'ast TypeSlice) {
+        visit_type_slice(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_trait_object(&mut self, i: &'ast TypeTraitObject) {
+        visit_type_trait_object(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_tuple(&mut self, i: &'ast TypeTuple) {
+        visit_type_tuple(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_verbatim(&mut self, i: &'ast TypeVerbatim) {
+        visit_type_verbatim(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_un_op(&mut self, i: &'ast UnOp) {
+        visit_un_op(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_glob(&mut self, i: &'ast UseGlob) {
+        visit_use_glob(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_group(&mut self, i: &'ast UseGroup) {
+        visit_use_group(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_name(&mut self, i: &'ast UseName) {
+        visit_use_name(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_path(&mut self, i: &'ast UsePath) {
+        visit_use_path(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_rename(&mut self, i: &'ast UseRename) {
+        visit_use_rename(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_tree(&mut self, i: &'ast UseTree) {
+        visit_use_tree(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_variant(&mut self, i: &'ast Variant) {
+        visit_variant(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_vis_crate(&mut self, i: &'ast VisCrate) {
+        visit_vis_crate(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_vis_public(&mut self, i: &'ast VisPublic) {
+        visit_vis_public(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_vis_restricted(&mut self, i: &'ast VisRestricted) {
+        visit_vis_restricted(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_visibility(&mut self, i: &'ast Visibility) {
+        visit_visibility(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_where_clause(&mut self, i: &'ast WhereClause) {
+        visit_where_clause(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_where_predicate(&mut self, i: &'ast WherePredicate) {
+        visit_where_predicate(self, i)
+    }
+}
+#[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.span);
+    if let Some(ref it) = _i.name {
+        _visitor.visit_lit_str(it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_angle_bracketed_generic_arguments<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast AngleBracketedGenericArguments,
+) {
+    if let Some(ref it) = _i.colon2_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    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.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.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.span)
+    };
+    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.spans);
+    if let Some(ref it) = _i.lifetime {
+        _visitor.visit_lifetime(it)
+    };
+    if let Some(ref it) = _i.mutability {
+        tokens_helper(_visitor, &it.span)
+    };
+    tokens_helper(_visitor, &_i.self_token.span);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_arm<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Arm) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.leading_vert {
+        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.span);
+        _visitor.visit_expr(&*(it).1);
+    };
+    tokens_helper(_visitor, &_i.fat_arrow_token.spans);
+    _visitor.visit_expr(&*_i.body);
+    if let Some(ref it) = _i.comma {
+        tokens_helper(_visitor, &it.spans)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_attr_style<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast AttrStyle) {
+    match *_i {
+        AttrStyle::Outer => {}
+        AttrStyle::Inner(ref _binding_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.spans);
+    _visitor.visit_attr_style(&_i.style);
+    tokens_helper(_visitor, &_i.bracket_token.span);
+    _visitor.visit_path(&_i.path);
+    skip!(_i.tts);
+}
+#[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.spans);
+    };
+    _visitor.visit_type(&_i.ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_bare_fn_arg_name<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast BareFnArgName,
+) {
+    match *_i {
+        BareFnArgName::Named(ref _binding_0) => {
+            _visitor.visit_ident(_binding_0);
+        }
+        BareFnArgName::Wild(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans);
+        }
+        BinOp::Sub(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Mul(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Div(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Rem(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::And(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Or(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::BitXor(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::BitAnd(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::BitOr(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Shl(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Shr(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Eq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Lt(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Le(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Ne(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Ge(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::Gt(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::AddEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::SubEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::MulEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::DivEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::RemEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::BitXorEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::BitAndEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::BitOrEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::ShlEq(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        BinOp::ShrEq(ref _binding_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.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.span);
+    for it in &_i.stmts {
+        _visitor.visit_stmt(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_bound_lifetimes<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast BoundLifetimes,
+) {
+    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.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.span);
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    _visitor.visit_type(&_i.ty);
+    if let Some(ref it) = _i.eq_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    if let Some(ref it) = _i.default {
+        _visitor.visit_expr(it)
+    };
+}
+#[cfg(feature = "derive")]
+pub fn visit_data<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Data) {
+    match *_i {
+        Data::Struct(ref _binding_0) => {
+            _visitor.visit_data_struct(_binding_0);
+        }
+        Data::Enum(ref _binding_0) => {
+            _visitor.visit_data_enum(_binding_0);
+        }
+        Data::Union(ref _binding_0) => {
+            _visitor.visit_data_union(_binding_0);
+        }
+    }
+}
+#[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.span);
+    tokens_helper(_visitor, &_i.brace_token.span);
+    for el in Punctuated::pairs(&_i.variants) {
+        let it = el.value();
+        _visitor.visit_variant(it)
+    }
+}
+#[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.span);
+    _visitor.visit_fields(&_i.fields);
+    if let Some(ref it) = _i.semi_token {
+        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.span);
+    _visitor.visit_fields_named(&_i.fields);
+}
+#[cfg(feature = "derive")]
+pub fn visit_derive_input<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast DeriveInput) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    _visitor.visit_data(&_i.data);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Expr) {
+    match *_i {
+        Expr::Box(ref _binding_0) => {
+            full!(_visitor.visit_expr_box(_binding_0));
+        }
+        Expr::InPlace(ref _binding_0) => {
+            full!(_visitor.visit_expr_in_place(_binding_0));
+        }
+        Expr::Array(ref _binding_0) => {
+            full!(_visitor.visit_expr_array(_binding_0));
+        }
+        Expr::Call(ref _binding_0) => {
+            _visitor.visit_expr_call(_binding_0);
+        }
+        Expr::MethodCall(ref _binding_0) => {
+            full!(_visitor.visit_expr_method_call(_binding_0));
+        }
+        Expr::Tuple(ref _binding_0) => {
+            full!(_visitor.visit_expr_tuple(_binding_0));
+        }
+        Expr::Binary(ref _binding_0) => {
+            _visitor.visit_expr_binary(_binding_0);
+        }
+        Expr::Unary(ref _binding_0) => {
+            _visitor.visit_expr_unary(_binding_0);
+        }
+        Expr::Lit(ref _binding_0) => {
+            _visitor.visit_expr_lit(_binding_0);
+        }
+        Expr::Cast(ref _binding_0) => {
+            _visitor.visit_expr_cast(_binding_0);
+        }
+        Expr::Type(ref _binding_0) => {
+            full!(_visitor.visit_expr_type(_binding_0));
+        }
+        Expr::If(ref _binding_0) => {
+            full!(_visitor.visit_expr_if(_binding_0));
+        }
+        Expr::IfLet(ref _binding_0) => {
+            full!(_visitor.visit_expr_if_let(_binding_0));
+        }
+        Expr::While(ref _binding_0) => {
+            full!(_visitor.visit_expr_while(_binding_0));
+        }
+        Expr::WhileLet(ref _binding_0) => {
+            full!(_visitor.visit_expr_while_let(_binding_0));
+        }
+        Expr::ForLoop(ref _binding_0) => {
+            full!(_visitor.visit_expr_for_loop(_binding_0));
+        }
+        Expr::Loop(ref _binding_0) => {
+            full!(_visitor.visit_expr_loop(_binding_0));
+        }
+        Expr::Match(ref _binding_0) => {
+            full!(_visitor.visit_expr_match(_binding_0));
+        }
+        Expr::Closure(ref _binding_0) => {
+            full!(_visitor.visit_expr_closure(_binding_0));
+        }
+        Expr::Unsafe(ref _binding_0) => {
+            full!(_visitor.visit_expr_unsafe(_binding_0));
+        }
+        Expr::Block(ref _binding_0) => {
+            full!(_visitor.visit_expr_block(_binding_0));
+        }
+        Expr::Assign(ref _binding_0) => {
+            full!(_visitor.visit_expr_assign(_binding_0));
+        }
+        Expr::AssignOp(ref _binding_0) => {
+            full!(_visitor.visit_expr_assign_op(_binding_0));
+        }
+        Expr::Field(ref _binding_0) => {
+            _visitor.visit_expr_field(_binding_0);
+        }
+        Expr::Index(ref _binding_0) => {
+            _visitor.visit_expr_index(_binding_0);
+        }
+        Expr::Range(ref _binding_0) => {
+            full!(_visitor.visit_expr_range(_binding_0));
+        }
+        Expr::Path(ref _binding_0) => {
+            _visitor.visit_expr_path(_binding_0);
+        }
+        Expr::Reference(ref _binding_0) => {
+            full!(_visitor.visit_expr_reference(_binding_0));
+        }
+        Expr::Break(ref _binding_0) => {
+            full!(_visitor.visit_expr_break(_binding_0));
+        }
+        Expr::Continue(ref _binding_0) => {
+            full!(_visitor.visit_expr_continue(_binding_0));
+        }
+        Expr::Return(ref _binding_0) => {
+            full!(_visitor.visit_expr_return(_binding_0));
+        }
+        Expr::Macro(ref _binding_0) => {
+            full!(_visitor.visit_expr_macro(_binding_0));
+        }
+        Expr::Struct(ref _binding_0) => {
+            full!(_visitor.visit_expr_struct(_binding_0));
+        }
+        Expr::Repeat(ref _binding_0) => {
+            full!(_visitor.visit_expr_repeat(_binding_0));
+        }
+        Expr::Paren(ref _binding_0) => {
+            _visitor.visit_expr_paren(_binding_0);
+        }
+        Expr::Group(ref _binding_0) => {
+            full!(_visitor.visit_expr_group(_binding_0));
+        }
+        Expr::Try(ref _binding_0) => {
+            full!(_visitor.visit_expr_try(_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));
+        }
+        Expr::Verbatim(ref _binding_0) => {
+            _visitor.visit_expr_verbatim(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_array<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprArray) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.bracket_token.span);
+    for el in Punctuated::pairs(&_i.elems) {
+        let it = el.value();
+        _visitor.visit_expr(it)
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_assign<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprAssign) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.left);
+    tokens_helper(_visitor, &_i.eq_token.spans);
+    _visitor.visit_expr(&*_i.right);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_assign_op<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ExprAssignOp,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.left);
+    _visitor.visit_bin_op(&_i.op);
+    _visitor.visit_expr(&*_i.right);
+}
+#[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 {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.left);
+    _visitor.visit_bin_op(&_i.op);
+    _visitor.visit_expr(&*_i.right);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_block<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBlock) {
+    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")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_box<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBox) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.box_token.span);
+    _visitor.visit_expr(&*_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_break<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprBreak) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.break_token.span);
+    if let Some(ref it) = _i.label {
+        _visitor.visit_lifetime(it)
+    };
+    if let Some(ref it) = _i.expr {
+        _visitor.visit_expr(&**it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_call<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCall) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.func);
+    tokens_helper(_visitor, &_i.paren_token.span);
+    for el in Punctuated::pairs(&_i.args) {
+        let it = el.value();
+        _visitor.visit_expr(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_cast<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprCast) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.expr);
+    tokens_helper(_visitor, &_i.as_token.span);
+    _visitor.visit_type(&*_i.ty);
+}
+#[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.span)
+    };
+    if let Some(ref it) = _i.capture {
+        tokens_helper(_visitor, &it.span)
+    };
+    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.spans);
+    _visitor.visit_return_type(&_i.output);
+    _visitor.visit_expr(&*_i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_continue<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ExprContinue,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.continue_token.span);
+    if let Some(ref it) = _i.label {
+        _visitor.visit_lifetime(it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_field<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprField) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.base);
+    tokens_helper(_visitor, &_i.dot_token.spans);
+    _visitor.visit_member(&_i.member);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_for_loop<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprForLoop) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.label {
+        _visitor.visit_label(it)
+    };
+    tokens_helper(_visitor, &_i.for_token.span);
+    _visitor.visit_pat(&*_i.pat);
+    tokens_helper(_visitor, &_i.in_token.span);
+    _visitor.visit_expr(&*_i.expr);
+    _visitor.visit_block(&_i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_group<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprGroup) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.group_token.span);
+    _visitor.visit_expr(&*_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_if<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIf) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    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.span);
+        _visitor.visit_expr(&*(it).1);
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_if_let<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIfLet) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    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.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.span);
+        _visitor.visit_expr(&*(it).1);
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_in_place<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprInPlace) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.place);
+    tokens_helper(_visitor, &_i.arrow_token.spans);
+    _visitor.visit_expr(&*_i.value);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_index<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprIndex) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.expr);
+    tokens_helper(_visitor, &_i.bracket_token.span);
+    _visitor.visit_expr(&*_i.index);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_lit<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprLit) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_lit(&_i.lit);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_loop<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprLoop) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.label {
+        _visitor.visit_label(it)
+    };
+    tokens_helper(_visitor, &_i.loop_token.span);
+    _visitor.visit_block(&_i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_macro<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprMacro) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_macro(&_i.mac);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_match<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprMatch) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.match_token.span);
+    _visitor.visit_expr(&*_i.expr);
+    tokens_helper(_visitor, &_i.brace_token.span);
+    for it in &_i.arms {
+        _visitor.visit_arm(it)
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_method_call<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ExprMethodCall,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.receiver);
+    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.span);
+    for el in Punctuated::pairs(&_i.args) {
+        let it = el.value();
+        _visitor.visit_expr(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_paren<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprParen) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.paren_token.span);
+    _visitor.visit_expr(&*_i.expr);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_path<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprPath) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.qself {
+        _visitor.visit_qself(it)
+    };
+    _visitor.visit_path(&_i.path);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_range<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprRange) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.from {
+        _visitor.visit_expr(&**it)
+    };
+    _visitor.visit_range_limits(&_i.limits);
+    if let Some(ref it) = _i.to {
+        _visitor.visit_expr(&**it)
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_reference<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ExprReference,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.and_token.spans);
+    if let Some(ref it) = _i.mutability {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_expr(&*_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_repeat<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprRepeat) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.bracket_token.span);
+    _visitor.visit_expr(&*_i.expr);
+    tokens_helper(_visitor, &_i.semi_token.spans);
+    _visitor.visit_expr(&*_i.len);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_return<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprReturn) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.return_token.span);
+    if let Some(ref it) = _i.expr {
+        _visitor.visit_expr(&**it)
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_struct<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprStruct) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_path(&_i.path);
+    tokens_helper(_visitor, &_i.brace_token.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.spans)
+    };
+    if let Some(ref it) = _i.rest {
+        _visitor.visit_expr(&**it)
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_try<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprTry) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.expr);
+    tokens_helper(_visitor, &_i.question_token.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"))]
+pub fn visit_expr_tuple<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprTuple) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.paren_token.span);
+    for el in Punctuated::pairs(&_i.elems) {
+        let it = el.value();
+        _visitor.visit_expr(it)
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_type<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprType) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_expr(&*_i.expr);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    _visitor.visit_type(&*_i.ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_unary<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprUnary) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_un_op(&_i.op);
+    _visitor.visit_expr(&*_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_unsafe<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprUnsafe) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.unsafe_token.span);
+    _visitor.visit_block(&_i.block);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_verbatim<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ExprVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_while<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprWhile) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.label {
+        _visitor.visit_label(it)
+    };
+    tokens_helper(_visitor, &_i.while_token.span);
+    _visitor.visit_expr(&*_i.cond);
+    _visitor.visit_block(&_i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_while_let<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ExprWhileLet,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.label {
+        _visitor.visit_label(it)
+    };
+    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.spans);
+    _visitor.visit_expr(&*_i.expr);
+    _visitor.visit_block(&_i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_yield<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ExprYield) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.yield_token.span);
+    if let Some(ref it) = _i.expr {
+        _visitor.visit_expr(&**it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_field<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Field) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    if let Some(ref it) = _i.ident {
+        _visitor.visit_ident(it)
+    };
+    if let Some(ref it) = _i.colon_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    _visitor.visit_type(&_i.ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_field_pat<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast FieldPat) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_member(&_i.member);
+    if let Some(ref it) = _i.colon_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    _visitor.visit_pat(&*_i.pat);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_field_value<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast FieldValue) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_member(&_i.member);
+    if let Some(ref it) = _i.colon_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    _visitor.visit_expr(&_i.expr);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_fields<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Fields) {
+    match *_i {
+        Fields::Named(ref _binding_0) => {
+            _visitor.visit_fields_named(_binding_0);
+        }
+        Fields::Unnamed(ref _binding_0) => {
+            _visitor.visit_fields_unnamed(_binding_0);
+        }
+        Fields::Unit => {}
+    }
+}
+#[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.span);
+    for el in Punctuated::pairs(&_i.named) {
+        let it = el.value();
+        _visitor.visit_field(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_fields_unnamed<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast FieldsUnnamed,
+) {
+    tokens_helper(_visitor, &_i.paren_token.span);
+    for el in Punctuated::pairs(&_i.unnamed) {
+        let it = el.value();
+        _visitor.visit_field(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_file<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast File) {
+    skip!(_i.shebang);
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    for it in &_i.items {
+        _visitor.visit_item(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_fn_arg<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast FnArg) {
+    match *_i {
+        FnArg::SelfRef(ref _binding_0) => {
+            _visitor.visit_arg_self_ref(_binding_0);
+        }
+        FnArg::SelfValue(ref _binding_0) => {
+            _visitor.visit_arg_self(_binding_0);
+        }
+        FnArg::Captured(ref _binding_0) => {
+            _visitor.visit_arg_captured(_binding_0);
+        }
+        FnArg::Inferred(ref _binding_0) => {
+            _visitor.visit_pat(_binding_0);
+        }
+        FnArg::Ignored(ref _binding_0) => {
+            _visitor.visit_type(_binding_0);
+        }
+    }
+}
+#[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.span);
+    _visitor.visit_generics(&_i.generics);
+    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.spans)
+    };
+    _visitor.visit_return_type(&_i.output);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ForeignItem) {
+    match *_i {
+        ForeignItem::Fn(ref _binding_0) => {
+            _visitor.visit_foreign_item_fn(_binding_0);
+        }
+        ForeignItem::Static(ref _binding_0) => {
+            _visitor.visit_foreign_item_static(_binding_0);
+        }
+        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);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_fn<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ForeignItemFn,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_fn_decl(&*_i.decl);
+    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>(
+    _visitor: &mut V,
+    _i: &'ast ForeignItemStatic,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.static_token.span);
+    if let Some(ref it) = _i.mutability {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    _visitor.visit_type(&*_i.ty);
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_type<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ForeignItemType,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.type_token.span);
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ForeignItemVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_generic_argument<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast GenericArgument,
+) {
+    match *_i {
+        GenericArgument::Lifetime(ref _binding_0) => {
+            _visitor.visit_lifetime(_binding_0);
+        }
+        GenericArgument::Type(ref _binding_0) => {
+            _visitor.visit_type(_binding_0);
+        }
+        GenericArgument::Binding(ref _binding_0) => {
+            _visitor.visit_binding(_binding_0);
+        }
+        GenericArgument::Const(ref _binding_0) => {
+            _visitor.visit_expr(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_generic_method_argument<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast GenericMethodArgument,
+) {
+    match *_i {
+        GenericMethodArgument::Type(ref _binding_0) => {
+            _visitor.visit_type(_binding_0);
+        }
+        GenericMethodArgument::Const(ref _binding_0) => {
+            _visitor.visit_expr(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_generic_param<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast GenericParam,
+) {
+    match *_i {
+        GenericParam::Type(ref _binding_0) => {
+            _visitor.visit_type_param(_binding_0);
+        }
+        GenericParam::Lifetime(ref _binding_0) => {
+            _visitor.visit_lifetime_def(_binding_0);
+        }
+        GenericParam::Const(ref _binding_0) => {
+            _visitor.visit_const_param(_binding_0);
+        }
+    }
+}
+#[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.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.spans)
+    };
+    if let Some(ref it) = _i.where_clause {
+        _visitor.visit_where_clause(it)
+    };
+}
+pub fn visit_ident<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Ident) {}
+#[cfg(feature = "full")]
+pub fn visit_impl_item<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ImplItem) {
+    match *_i {
+        ImplItem::Const(ref _binding_0) => {
+            _visitor.visit_impl_item_const(_binding_0);
+        }
+        ImplItem::Method(ref _binding_0) => {
+            _visitor.visit_impl_item_method(_binding_0);
+        }
+        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);
+        }
+        ImplItem::Verbatim(ref _binding_0) => {
+            _visitor.visit_impl_item_verbatim(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_const<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ImplItemConst,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    if let Some(ref it) = _i.defaultness {
+        tokens_helper(_visitor, &it.span)
+    };
+    tokens_helper(_visitor, &_i.const_token.span);
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    _visitor.visit_type(&_i.ty);
+    tokens_helper(_visitor, &_i.eq_token.spans);
+    _visitor.visit_expr(&_i.expr);
+    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>(
+    _visitor: &mut V,
+    _i: &'ast ImplItemMacro,
+) {
+    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_impl_item_method<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ImplItemMethod,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    if let Some(ref it) = _i.defaultness {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_method_sig(&_i.sig);
+    _visitor.visit_block(&_i.block);
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_type<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ImplItemType,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    if let Some(ref it) = _i.defaultness {
+        tokens_helper(_visitor, &it.span)
+    };
+    tokens_helper(_visitor, &_i.type_token.span);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    tokens_helper(_visitor, &_i.eq_token.spans);
+    _visitor.visit_type(&_i.ty);
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ImplItemVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_index<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Index) {
+    skip!(_i.index);
+    _visitor.visit_span(&_i.span);
+}
+#[cfg(feature = "full")]
+pub fn visit_item<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Item) {
+    match *_i {
+        Item::ExternCrate(ref _binding_0) => {
+            _visitor.visit_item_extern_crate(_binding_0);
+        }
+        Item::Use(ref _binding_0) => {
+            _visitor.visit_item_use(_binding_0);
+        }
+        Item::Static(ref _binding_0) => {
+            _visitor.visit_item_static(_binding_0);
+        }
+        Item::Const(ref _binding_0) => {
+            _visitor.visit_item_const(_binding_0);
+        }
+        Item::Fn(ref _binding_0) => {
+            _visitor.visit_item_fn(_binding_0);
+        }
+        Item::Mod(ref _binding_0) => {
+            _visitor.visit_item_mod(_binding_0);
+        }
+        Item::ForeignMod(ref _binding_0) => {
+            _visitor.visit_item_foreign_mod(_binding_0);
+        }
+        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);
+        }
+        Item::Enum(ref _binding_0) => {
+            _visitor.visit_item_enum(_binding_0);
+        }
+        Item::Union(ref _binding_0) => {
+            _visitor.visit_item_union(_binding_0);
+        }
+        Item::Trait(ref _binding_0) => {
+            _visitor.visit_item_trait(_binding_0);
+        }
+        Item::Impl(ref _binding_0) => {
+            _visitor.visit_item_impl(_binding_0);
+        }
+        Item::Macro(ref _binding_0) => {
+            _visitor.visit_item_macro(_binding_0);
+        }
+        Item::Macro2(ref _binding_0) => {
+            _visitor.visit_item_macro2(_binding_0);
+        }
+        Item::Verbatim(ref _binding_0) => {
+            _visitor.visit_item_verbatim(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_item_const<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemConst) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.const_token.span);
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    _visitor.visit_type(&*_i.ty);
+    tokens_helper(_visitor, &_i.eq_token.spans);
+    _visitor.visit_expr(&*_i.expr);
+    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) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.enum_token.span);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    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,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    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.span);
+        _visitor.visit_ident(&(it).1);
+    };
+    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) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    if let Some(ref it) = _i.constness {
+        tokens_helper(_visitor, &it.span)
+    };
+    if let Some(ref it) = _i.unsafety {
+        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)
+    };
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_fn_decl(&*_i.decl);
+    _visitor.visit_block(&*_i.block);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_foreign_mod<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ItemForeignMod,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_abi(&_i.abi);
+    tokens_helper(_visitor, &_i.brace_token.span);
+    for it in &_i.items {
+        _visitor.visit_foreign_item(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_item_impl<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemImpl) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.defaultness {
+        tokens_helper(_visitor, &it.span)
+    };
+    if let Some(ref it) = _i.unsafety {
+        tokens_helper(_visitor, &it.span)
+    };
+    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.spans)
+        };
+        _visitor.visit_path(&(it).1);
+        tokens_helper(_visitor, &(it).2.span);
+    };
+    _visitor.visit_type(&*_i.self_ty);
+    tokens_helper(_visitor, &_i.brace_token.span);
+    for it in &_i.items {
+        _visitor.visit_impl_item(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_item_macro<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemMacro) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    if let Some(ref it) = _i.ident {
+        _visitor.visit_ident(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_item_macro2<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemMacro2) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.macro_token.span);
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.paren_token.span);
+    skip!(_i.args);
+    tokens_helper(_visitor, &_i.brace_token.span);
+    skip!(_i.body);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_mod<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemMod) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.mod_token.span);
+    _visitor.visit_ident(&_i.ident);
+    if let Some(ref it) = _i.content {
+        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.spans)
+    };
+}
+#[cfg(feature = "full")]
+pub fn visit_item_static<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemStatic) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.static_token.span);
+    if let Some(ref it) = _i.mutability {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    _visitor.visit_type(&*_i.ty);
+    tokens_helper(_visitor, &_i.eq_token.spans);
+    _visitor.visit_expr(&*_i.expr);
+    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) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    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.spans)
+    };
+}
+#[cfg(feature = "full")]
+pub fn visit_item_trait<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemTrait) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    if let Some(ref it) = _i.unsafety {
+        tokens_helper(_visitor, &it.span)
+    };
+    if let Some(ref it) = _i.auto_token {
+        tokens_helper(_visitor, &it.span)
+    };
+    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.spans)
+    };
+    for el in Punctuated::pairs(&_i.supertraits) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+    tokens_helper(_visitor, &_i.brace_token.span);
+    for it in &_i.items {
+        _visitor.visit_trait_item(it)
+    }
+}
+#[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.span);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    tokens_helper(_visitor, &_i.eq_token.spans);
+    _visitor.visit_type(&*_i.ty);
+    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) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.union_token.span);
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_generics(&_i.generics);
+    _visitor.visit_fields_named(&_i.fields);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_use<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ItemUse) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_visibility(&_i.vis);
+    tokens_helper(_visitor, &_i.use_token.span);
+    if let Some(ref it) = _i.leading_colon {
+        tokens_helper(_visitor, &it.spans)
+    };
+    _visitor.visit_use_tree(&_i.tree);
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ItemVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.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_ident(&_i.ident);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lifetime_def<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LifetimeDef) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_lifetime(&_i.lifetime);
+    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_lifetime(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Lit) {
+    match *_i {
+        Lit::Str(ref _binding_0) => {
+            _visitor.visit_lit_str(_binding_0);
+        }
+        Lit::ByteStr(ref _binding_0) => {
+            _visitor.visit_lit_byte_str(_binding_0);
+        }
+        Lit::Byte(ref _binding_0) => {
+            _visitor.visit_lit_byte(_binding_0);
+        }
+        Lit::Char(ref _binding_0) => {
+            _visitor.visit_lit_char(_binding_0);
+        }
+        Lit::Int(ref _binding_0) => {
+            _visitor.visit_lit_int(_binding_0);
+        }
+        Lit::Float(ref _binding_0) => {
+            _visitor.visit_lit_float(_binding_0);
+        }
+        Lit::Bool(ref _binding_0) => {
+            _visitor.visit_lit_bool(_binding_0);
+        }
+        Lit::Verbatim(ref _binding_0) => {
+            _visitor.visit_lit_verbatim(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_bool<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitBool) {
+    skip!(_i.value);
+    _visitor.visit_span(&_i.span);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_byte<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitByte) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_byte_str<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitByteStr) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_char<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitChar) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_float<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitFloat) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_int<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitInt) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_str<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitStr) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_verbatim<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast LitVerbatim) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_local<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Local) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    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.spans);
+        _visitor.visit_type(&*(it).1);
+    };
+    if let Some(ref it) = _i.init {
+        tokens_helper(_visitor, &(it).0.spans);
+        _visitor.visit_expr(&*(it).1);
+    };
+    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.spans);
+    _visitor.visit_macro_delimiter(&_i.delimiter);
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_macro_delimiter<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast MacroDelimiter,
+) {
+    match *_i {
+        MacroDelimiter::Paren(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.span);
+        }
+        MacroDelimiter::Brace(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.span);
+        }
+        MacroDelimiter::Bracket(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.span);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_member<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Member) {
+    match *_i {
+        Member::Named(ref _binding_0) => {
+            _visitor.visit_ident(_binding_0);
+        }
+        Member::Unnamed(ref _binding_0) => {
+            _visitor.visit_index(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_meta<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Meta) {
+    match *_i {
+        Meta::Word(ref _binding_0) => {
+            _visitor.visit_ident(_binding_0);
+        }
+        Meta::List(ref _binding_0) => {
+            _visitor.visit_meta_list(_binding_0);
+        }
+        Meta::NameValue(ref _binding_0) => {
+            _visitor.visit_meta_name_value(_binding_0);
+        }
+    }
+}
+#[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.span);
+    for el in Punctuated::pairs(&_i.nested) {
+        let it = el.value();
+        _visitor.visit_nested_meta(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_meta_name_value<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast MetaNameValue,
+) {
+    _visitor.visit_ident(&_i.ident);
+    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.span)
+    };
+    if let Some(ref it) = _i.unsafety {
+        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)
+    };
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_fn_decl(&_i.decl);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_method_turbofish<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast MethodTurbofish,
+) {
+    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.spans);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_nested_meta<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast NestedMeta) {
+    match *_i {
+        NestedMeta::Meta(ref _binding_0) => {
+            _visitor.visit_meta(_binding_0);
+        }
+        NestedMeta::Literal(ref _binding_0) => {
+            _visitor.visit_lit(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_parenthesized_generic_arguments<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast ParenthesizedGenericArguments,
+) {
+    tokens_helper(_visitor, &_i.paren_token.span);
+    for el in Punctuated::pairs(&_i.inputs) {
+        let it = el.value();
+        _visitor.visit_type(it)
+    }
+    _visitor.visit_return_type(&_i.output);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Pat) {
+    match *_i {
+        Pat::Wild(ref _binding_0) => {
+            _visitor.visit_pat_wild(_binding_0);
+        }
+        Pat::Ident(ref _binding_0) => {
+            _visitor.visit_pat_ident(_binding_0);
+        }
+        Pat::Struct(ref _binding_0) => {
+            _visitor.visit_pat_struct(_binding_0);
+        }
+        Pat::TupleStruct(ref _binding_0) => {
+            _visitor.visit_pat_tuple_struct(_binding_0);
+        }
+        Pat::Path(ref _binding_0) => {
+            _visitor.visit_pat_path(_binding_0);
+        }
+        Pat::Tuple(ref _binding_0) => {
+            _visitor.visit_pat_tuple(_binding_0);
+        }
+        Pat::Box(ref _binding_0) => {
+            _visitor.visit_pat_box(_binding_0);
+        }
+        Pat::Ref(ref _binding_0) => {
+            _visitor.visit_pat_ref(_binding_0);
+        }
+        Pat::Lit(ref _binding_0) => {
+            _visitor.visit_pat_lit(_binding_0);
+        }
+        Pat::Range(ref _binding_0) => {
+            _visitor.visit_pat_range(_binding_0);
+        }
+        Pat::Slice(ref _binding_0) => {
+            _visitor.visit_pat_slice(_binding_0);
+        }
+        Pat::Macro(ref _binding_0) => {
+            _visitor.visit_pat_macro(_binding_0);
+        }
+        Pat::Verbatim(ref _binding_0) => {
+            _visitor.visit_pat_verbatim(_binding_0);
+        }
+    }
+}
+#[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.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.span)
+    };
+    if let Some(ref it) = _i.mutability {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_ident(&_i.ident);
+    if let Some(ref it) = _i.subpat {
+        tokens_helper(_visitor, &(it).0.spans);
+        _visitor.visit_pat(&*(it).1);
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_lit<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatLit) {
+    _visitor.visit_expr(&*_i.expr);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_macro<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatMacro) {
+    _visitor.visit_macro(&_i.mac);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_path<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatPath) {
+    if let Some(ref it) = _i.qself {
+        _visitor.visit_qself(it)
+    };
+    _visitor.visit_path(&_i.path);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_range<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatRange) {
+    _visitor.visit_expr(&*_i.lo);
+    _visitor.visit_range_limits(&_i.limits);
+    _visitor.visit_expr(&*_i.hi);
+}
+#[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.spans);
+    if let Some(ref it) = _i.mutability {
+        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.span);
+    for el in Punctuated::pairs(&_i.front) {
+        let it = el.value();
+        _visitor.visit_pat(it)
+    }
+    if let Some(ref it) = _i.middle {
+        _visitor.visit_pat(&**it)
+    };
+    if let Some(ref it) = _i.dot2_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    if let Some(ref it) = _i.comma_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    for el in Punctuated::pairs(&_i.back) {
+        let it = el.value();
+        _visitor.visit_pat(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.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.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.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.spans)
+    };
+    if let Some(ref it) = _i.comma_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    for el in Punctuated::pairs(&_i.back) {
+        let it = el.value();
+        _visitor.visit_pat(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_tuple_struct<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast PatTupleStruct,
+) {
+    _visitor.visit_path(&_i.path);
+    _visitor.visit_pat_tuple(&_i.pat);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_verbatim<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PatVerbatim) {
+    skip!(_i.tts);
+}
+#[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.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.spans)
+    };
+    for el in Punctuated::pairs(&_i.segments) {
+        let it = el.value();
+        _visitor.visit_path_segment(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_path_arguments<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast PathArguments,
+) {
+    match *_i {
+        PathArguments::None => {}
+        PathArguments::AngleBracketed(ref _binding_0) => {
+            _visitor.visit_angle_bracketed_generic_arguments(_binding_0);
+        }
+        PathArguments::Parenthesized(ref _binding_0) => {
+            _visitor.visit_parenthesized_generic_arguments(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_path_segment<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast PathSegment) {
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_path_arguments(&_i.arguments);
+}
+#[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.spans);
+    _visitor.visit_type(&_i.rhs_ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_predicate_lifetime<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast PredicateLifetime,
+) {
+    _visitor.visit_lifetime(&_i.lifetime);
+    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_lifetime(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_predicate_type<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast PredicateType,
+) {
+    if let Some(ref it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes(it)
+    };
+    _visitor.visit_type(&_i.bounded_ty);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    for el in Punctuated::pairs(&_i.bounds) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+}
+#[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.spans);
+    _visitor.visit_type(&*_i.ty);
+    skip!(_i.position);
+    if let Some(ref it) = _i.as_token {
+        tokens_helper(_visitor, &it.span)
+    };
+    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.spans);
+        }
+        RangeLimits::Closed(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_return_type<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast ReturnType) {
+    match *_i {
+        ReturnType::Default => {}
+        ReturnType::Type(ref _binding_0, ref _binding_1) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+            _visitor.visit_type(&**_binding_1);
+        }
+    }
+}
+pub fn visit_span<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Span) {}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_stmt<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Stmt) {
+    match *_i {
+        Stmt::Local(ref _binding_0) => {
+            _visitor.visit_local(_binding_0);
+        }
+        Stmt::Item(ref _binding_0) => {
+            _visitor.visit_item(_binding_0);
+        }
+        Stmt::Expr(ref _binding_0) => {
+            _visitor.visit_expr(_binding_0);
+        }
+        Stmt::Semi(ref _binding_0, ref _binding_1) => {
+            _visitor.visit_expr(_binding_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.span)
+    };
+    _visitor.visit_trait_bound_modifier(&_i.modifier);
+    if let Some(ref it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes(it)
+    };
+    _visitor.visit_path(&_i.path);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_trait_bound_modifier<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TraitBoundModifier,
+) {
+    match *_i {
+        TraitBoundModifier::None => {}
+        TraitBoundModifier::Maybe(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TraitItem) {
+    match *_i {
+        TraitItem::Const(ref _binding_0) => {
+            _visitor.visit_trait_item_const(_binding_0);
+        }
+        TraitItem::Method(ref _binding_0) => {
+            _visitor.visit_trait_item_method(_binding_0);
+        }
+        TraitItem::Type(ref _binding_0) => {
+            _visitor.visit_trait_item_type(_binding_0);
+        }
+        TraitItem::Existential(ref _binding_0) => {
+            _visitor.visit_trait_item_existential(_binding_0);
+        }
+        TraitItem::Macro(ref _binding_0) => {
+            _visitor.visit_trait_item_macro(_binding_0);
+        }
+        TraitItem::Verbatim(ref _binding_0) => {
+            _visitor.visit_trait_item_verbatim(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_const<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TraitItemConst,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    tokens_helper(_visitor, &_i.const_token.span);
+    _visitor.visit_ident(&_i.ident);
+    tokens_helper(_visitor, &_i.colon_token.spans);
+    _visitor.visit_type(&_i.ty);
+    if let Some(ref it) = _i.default {
+        tokens_helper(_visitor, &(it).0.spans);
+        _visitor.visit_expr(&(it).1);
+    };
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_existential<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TraitItemExistential,
+) {
+    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_trait_item_macro<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TraitItemMacro,
+) {
+    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_trait_item_method<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TraitItemMethod,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_method_sig(&_i.sig);
+    if let Some(ref it) = _i.default {
+        _visitor.visit_block(it)
+    };
+    if let Some(ref it) = _i.semi_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_type<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TraitItemType,
+) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    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)
+    }
+    if let Some(ref it) = _i.default {
+        tokens_helper(_visitor, &(it).0.spans);
+        _visitor.visit_type(&(it).1);
+    };
+    tokens_helper(_visitor, &_i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_verbatim<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TraitItemVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Type) {
+    match *_i {
+        Type::Slice(ref _binding_0) => {
+            _visitor.visit_type_slice(_binding_0);
+        }
+        Type::Array(ref _binding_0) => {
+            _visitor.visit_type_array(_binding_0);
+        }
+        Type::Ptr(ref _binding_0) => {
+            _visitor.visit_type_ptr(_binding_0);
+        }
+        Type::Reference(ref _binding_0) => {
+            _visitor.visit_type_reference(_binding_0);
+        }
+        Type::BareFn(ref _binding_0) => {
+            _visitor.visit_type_bare_fn(_binding_0);
+        }
+        Type::Never(ref _binding_0) => {
+            _visitor.visit_type_never(_binding_0);
+        }
+        Type::Tuple(ref _binding_0) => {
+            _visitor.visit_type_tuple(_binding_0);
+        }
+        Type::Path(ref _binding_0) => {
+            _visitor.visit_type_path(_binding_0);
+        }
+        Type::TraitObject(ref _binding_0) => {
+            _visitor.visit_type_trait_object(_binding_0);
+        }
+        Type::ImplTrait(ref _binding_0) => {
+            _visitor.visit_type_impl_trait(_binding_0);
+        }
+        Type::Paren(ref _binding_0) => {
+            _visitor.visit_type_paren(_binding_0);
+        }
+        Type::Group(ref _binding_0) => {
+            _visitor.visit_type_group(_binding_0);
+        }
+        Type::Infer(ref _binding_0) => {
+            _visitor.visit_type_infer(_binding_0);
+        }
+        Type::Macro(ref _binding_0) => {
+            _visitor.visit_type_macro(_binding_0);
+        }
+        Type::Verbatim(ref _binding_0) => {
+            _visitor.visit_type_verbatim(_binding_0);
+        }
+    }
+}
+#[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.span);
+    _visitor.visit_type(&*_i.elem);
+    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.unsafety {
+        tokens_helper(_visitor, &it.span)
+    };
+    if let Some(ref it) = _i.abi {
+        _visitor.visit_abi(it)
+    };
+    tokens_helper(_visitor, &_i.fn_token.span);
+    if let Some(ref it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes(it)
+    };
+    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.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.span);
+    _visitor.visit_type(&*_i.elem);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_impl_trait<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TypeImplTrait,
+) {
+    tokens_helper(_visitor, &_i.impl_token.span);
+    for el in Punctuated::pairs(&_i.bounds) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+}
+#[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.spans);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_macro<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeMacro) {
+    _visitor.visit_macro(&_i.mac);
+}
+#[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.spans);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_param<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypeParam) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_ident(&_i.ident);
+    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)
+    }
+    if let Some(ref it) = _i.eq_token {
+        tokens_helper(_visitor, &it.spans)
+    };
+    if let Some(ref it) = _i.default {
+        _visitor.visit_type(it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_param_bound<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TypeParamBound,
+) {
+    match *_i {
+        TypeParamBound::Trait(ref _binding_0) => {
+            _visitor.visit_trait_bound(_binding_0);
+        }
+        TypeParamBound::Lifetime(ref _binding_0) => {
+            _visitor.visit_lifetime(_binding_0);
+        }
+    }
+}
+#[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.span);
+    _visitor.visit_type(&*_i.elem);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_path<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast TypePath) {
+    if let Some(ref it) = _i.qself {
+        _visitor.visit_qself(it)
+    };
+    _visitor.visit_path(&_i.path);
+}
+#[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.spans);
+    if let Some(ref it) = _i.const_token {
+        tokens_helper(_visitor, &it.span)
+    };
+    if let Some(ref it) = _i.mutability {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_type(&*_i.elem);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_reference<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TypeReference,
+) {
+    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.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.span);
+    _visitor.visit_type(&*_i.elem);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_trait_object<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TypeTraitObject,
+) {
+    if let Some(ref it) = _i.dyn_token {
+        tokens_helper(_visitor, &it.span)
+    };
+    for el in Punctuated::pairs(&_i.bounds) {
+        let it = el.value();
+        _visitor.visit_type_param_bound(it)
+    }
+}
+#[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.span);
+    for el in Punctuated::pairs(&_i.elems) {
+        let it = el.value();
+        _visitor.visit_type(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_verbatim<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast TypeVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans);
+        }
+        UnOp::Not(ref _binding_0) => {
+            tokens_helper(_visitor, &_binding_0.spans);
+        }
+        UnOp::Neg(ref _binding_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.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.span);
+    for el in Punctuated::pairs(&_i.items) {
+        let it = el.value();
+        _visitor.visit_use_tree(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_use_name<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast UseName) {
+    _visitor.visit_ident(&_i.ident);
+}
+#[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.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.span);
+    _visitor.visit_ident(&_i.rename);
+}
+#[cfg(feature = "full")]
+pub fn visit_use_tree<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast UseTree) {
+    match *_i {
+        UseTree::Path(ref _binding_0) => {
+            _visitor.visit_use_path(_binding_0);
+        }
+        UseTree::Name(ref _binding_0) => {
+            _visitor.visit_use_name(_binding_0);
+        }
+        UseTree::Rename(ref _binding_0) => {
+            _visitor.visit_use_rename(_binding_0);
+        }
+        UseTree::Glob(ref _binding_0) => {
+            _visitor.visit_use_glob(_binding_0);
+        }
+        UseTree::Group(ref _binding_0) => {
+            _visitor.visit_use_group(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_variant<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Variant) {
+    for it in &_i.attrs {
+        _visitor.visit_attribute(it)
+    }
+    _visitor.visit_ident(&_i.ident);
+    _visitor.visit_fields(&_i.fields);
+    if let Some(ref it) = _i.discriminant {
+        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.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.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.span);
+    tokens_helper(_visitor, &_i.paren_token.span);
+    if let Some(ref it) = _i.in_token {
+        tokens_helper(_visitor, &it.span)
+    };
+    _visitor.visit_path(&*_i.path);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_visibility<'ast, V: Visit<'ast> + ?Sized>(_visitor: &mut V, _i: &'ast Visibility) {
+    match *_i {
+        Visibility::Public(ref _binding_0) => {
+            _visitor.visit_vis_public(_binding_0);
+        }
+        Visibility::Crate(ref _binding_0) => {
+            _visitor.visit_vis_crate(_binding_0);
+        }
+        Visibility::Restricted(ref _binding_0) => {
+            _visitor.visit_vis_restricted(_binding_0);
+        }
+        Visibility::Inherited => {}
+    }
+}
+#[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.span);
+    for el in Punctuated::pairs(&_i.predicates) {
+        let it = el.value();
+        _visitor.visit_where_predicate(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_where_predicate<'ast, V: Visit<'ast> + ?Sized>(
+    _visitor: &mut V,
+    _i: &'ast WherePredicate,
+) {
+    match *_i {
+        WherePredicate::Type(ref _binding_0) => {
+            _visitor.visit_predicate_type(_binding_0);
+        }
+        WherePredicate::Lifetime(ref _binding_0) => {
+            _visitor.visit_predicate_lifetime(_binding_0);
+        }
+        WherePredicate::Eq(ref _binding_0) => {
+            _visitor.visit_predicate_eq(_binding_0);
+        }
+    }
+}
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
new file mode 100644
index 0000000..8263b61
--- /dev/null
+++ b/src/gen/visit_mut.rs
@@ -0,0 +1,3425 @@
+// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT
+
+#![cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
+#[cfg(any(feature = "full", feature = "derive"))]
+use gen::helper::visit_mut::*;
+use proc_macro2::Span;
+#[cfg(any(feature = "full", feature = "derive"))]
+use punctuated::Punctuated;
+use *;
+#[cfg(feature = "full")]
+macro_rules! full {
+    ($e:expr) => {
+        $e
+    };
+}
+#[cfg(all(feature = "derive", not(feature = "full")))]
+macro_rules! full {
+    ($e:expr) => {
+        unreachable!()
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! skip {
+    ($($tt:tt)*) => {};
+}
+#[doc = r" Syntax tree traversal to mutate an exclusive borrow of a syntax tree in"]
+#[doc = r" place."]
+#[doc = r""]
+#[doc = r" See the [module documentation] for details."]
+#[doc = r""]
+#[doc = r" [module documentation]: index.html"]
+#[doc = r""]
+#[doc = r#" *This trait is available if Syn is built with the `"visit-mut"` feature.*"#]
+pub trait VisitMut {
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_abi_mut(&mut self, i: &mut Abi) {
+        visit_abi_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_angle_bracketed_generic_arguments_mut(
+        &mut self,
+        i: &mut AngleBracketedGenericArguments,
+    ) {
+        visit_angle_bracketed_generic_arguments_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_arg_captured_mut(&mut self, i: &mut ArgCaptured) {
+        visit_arg_captured_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_arg_self_mut(&mut self, i: &mut ArgSelf) {
+        visit_arg_self_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_arg_self_ref_mut(&mut self, i: &mut ArgSelfRef) {
+        visit_arg_self_ref_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_arm_mut(&mut self, i: &mut Arm) {
+        visit_arm_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_attr_style_mut(&mut self, i: &mut AttrStyle) {
+        visit_attr_style_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_attribute_mut(&mut self, i: &mut Attribute) {
+        visit_attribute_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bare_fn_arg_mut(&mut self, i: &mut BareFnArg) {
+        visit_bare_fn_arg_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bare_fn_arg_name_mut(&mut self, i: &mut BareFnArgName) {
+        visit_bare_fn_arg_name_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bin_op_mut(&mut self, i: &mut BinOp) {
+        visit_bin_op_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_binding_mut(&mut self, i: &mut Binding) {
+        visit_binding_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_block_mut(&mut self, i: &mut Block) {
+        visit_block_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_bound_lifetimes_mut(&mut self, i: &mut BoundLifetimes) {
+        visit_bound_lifetimes_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_const_param_mut(&mut self, i: &mut ConstParam) {
+        visit_const_param_mut(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data_mut(&mut self, i: &mut Data) {
+        visit_data_mut(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data_enum_mut(&mut self, i: &mut DataEnum) {
+        visit_data_enum_mut(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data_struct_mut(&mut self, i: &mut DataStruct) {
+        visit_data_struct_mut(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_data_union_mut(&mut self, i: &mut DataUnion) {
+        visit_data_union_mut(self, i)
+    }
+    #[cfg(feature = "derive")]
+    fn visit_derive_input_mut(&mut self, i: &mut DeriveInput) {
+        visit_derive_input_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_mut(&mut self, i: &mut Expr) {
+        visit_expr_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_array_mut(&mut self, i: &mut ExprArray) {
+        visit_expr_array_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_assign_mut(&mut self, i: &mut ExprAssign) {
+        visit_expr_assign_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_block_mut(&mut self, i: &mut ExprBlock) {
+        visit_expr_block_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_box_mut(&mut self, i: &mut ExprBox) {
+        visit_expr_box_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_break_mut(&mut self, i: &mut ExprBreak) {
+        visit_expr_break_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_call_mut(&mut self, i: &mut ExprCall) {
+        visit_expr_call_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_cast_mut(&mut self, i: &mut ExprCast) {
+        visit_expr_cast_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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_continue_mut(&mut self, i: &mut ExprContinue) {
+        visit_expr_continue_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_field_mut(&mut self, i: &mut ExprField) {
+        visit_expr_field_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_for_loop_mut(&mut self, i: &mut ExprForLoop) {
+        visit_expr_for_loop_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_group_mut(&mut self, i: &mut ExprGroup) {
+        visit_expr_group_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_if_mut(&mut self, i: &mut ExprIf) {
+        visit_expr_if_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_if_let_mut(&mut self, i: &mut ExprIfLet) {
+        visit_expr_if_let_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_in_place_mut(&mut self, i: &mut ExprInPlace) {
+        visit_expr_in_place_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_index_mut(&mut self, i: &mut ExprIndex) {
+        visit_expr_index_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_lit_mut(&mut self, i: &mut ExprLit) {
+        visit_expr_lit_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_loop_mut(&mut self, i: &mut ExprLoop) {
+        visit_expr_loop_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_macro_mut(&mut self, i: &mut ExprMacro) {
+        visit_expr_macro_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_match_mut(&mut self, i: &mut ExprMatch) {
+        visit_expr_match_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_method_call_mut(&mut self, i: &mut ExprMethodCall) {
+        visit_expr_method_call_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_paren_mut(&mut self, i: &mut ExprParen) {
+        visit_expr_paren_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_path_mut(&mut self, i: &mut ExprPath) {
+        visit_expr_path_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_range_mut(&mut self, i: &mut ExprRange) {
+        visit_expr_range_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_reference_mut(&mut self, i: &mut ExprReference) {
+        visit_expr_reference_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_repeat_mut(&mut self, i: &mut ExprRepeat) {
+        visit_expr_repeat_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_return_mut(&mut self, i: &mut ExprReturn) {
+        visit_expr_return_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_struct_mut(&mut self, i: &mut ExprStruct) {
+        visit_expr_struct_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_try_mut(&mut self, i: &mut ExprTry) {
+        visit_expr_try_mut(self, i)
+    }
+    #[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)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_type_mut(&mut self, i: &mut ExprType) {
+        visit_expr_type_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_unary_mut(&mut self, i: &mut ExprUnary) {
+        visit_expr_unary_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_unsafe_mut(&mut self, i: &mut ExprUnsafe) {
+        visit_expr_unsafe_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_verbatim_mut(&mut self, i: &mut ExprVerbatim) {
+        visit_expr_verbatim_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_while_mut(&mut self, i: &mut ExprWhile) {
+        visit_expr_while_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_while_let_mut(&mut self, i: &mut ExprWhileLet) {
+        visit_expr_while_let_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_expr_yield_mut(&mut self, i: &mut ExprYield) {
+        visit_expr_yield_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_field_mut(&mut self, i: &mut Field) {
+        visit_field_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_field_pat_mut(&mut self, i: &mut FieldPat) {
+        visit_field_pat_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_field_value_mut(&mut self, i: &mut FieldValue) {
+        visit_field_value_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_fields_mut(&mut self, i: &mut Fields) {
+        visit_fields_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_fields_named_mut(&mut self, i: &mut FieldsNamed) {
+        visit_fields_named_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_fields_unnamed_mut(&mut self, i: &mut FieldsUnnamed) {
+        visit_fields_unnamed_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_file_mut(&mut self, i: &mut File) {
+        visit_file_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_fn_arg_mut(&mut self, i: &mut FnArg) {
+        visit_fn_arg_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_fn_decl_mut(&mut self, i: &mut FnDecl) {
+        visit_fn_decl_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item_mut(&mut self, i: &mut ForeignItem) {
+        visit_foreign_item_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item_fn_mut(&mut self, i: &mut ForeignItemFn) {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item_type_mut(&mut self, i: &mut ForeignItemType) {
+        visit_foreign_item_type_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_foreign_item_verbatim_mut(&mut self, i: &mut ForeignItemVerbatim) {
+        visit_foreign_item_verbatim_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_generic_argument_mut(&mut self, i: &mut GenericArgument) {
+        visit_generic_argument_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_generic_method_argument_mut(&mut self, i: &mut GenericMethodArgument) {
+        visit_generic_method_argument_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_generic_param_mut(&mut self, i: &mut GenericParam) {
+        visit_generic_param_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_generics_mut(&mut self, i: &mut Generics) {
+        visit_generics_mut(self, i)
+    }
+    fn visit_ident_mut(&mut self, i: &mut Ident) {
+        visit_ident_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_mut(&mut self, i: &mut ImplItem) {
+        visit_impl_item_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_const_mut(&mut self, i: &mut ImplItemConst) {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_method_mut(&mut self, i: &mut ImplItemMethod) {
+        visit_impl_item_method_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_type_mut(&mut self, i: &mut ImplItemType) {
+        visit_impl_item_type_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_impl_item_verbatim_mut(&mut self, i: &mut ImplItemVerbatim) {
+        visit_impl_item_verbatim_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_index_mut(&mut self, i: &mut Index) {
+        visit_index_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_mut(&mut self, i: &mut Item) {
+        visit_item_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_const_mut(&mut self, i: &mut ItemConst) {
+        visit_item_const_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
+        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)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
+        visit_item_fn_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_foreign_mod_mut(&mut self, i: &mut ItemForeignMod) {
+        visit_item_foreign_mod_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_impl_mut(&mut self, i: &mut ItemImpl) {
+        visit_item_impl_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_macro_mut(&mut self, i: &mut ItemMacro) {
+        visit_item_macro_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_macro2_mut(&mut self, i: &mut ItemMacro2) {
+        visit_item_macro2_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_mod_mut(&mut self, i: &mut ItemMod) {
+        visit_item_mod_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_static_mut(&mut self, i: &mut ItemStatic) {
+        visit_item_static_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
+        visit_item_struct_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
+        visit_item_trait_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_type_mut(&mut self, i: &mut ItemType) {
+        visit_item_type_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
+        visit_item_union_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_use_mut(&mut self, i: &mut ItemUse) {
+        visit_item_use_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_item_verbatim_mut(&mut self, i: &mut ItemVerbatim) {
+        visit_item_verbatim_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    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)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lifetime_def_mut(&mut self, i: &mut LifetimeDef) {
+        visit_lifetime_def_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_mut(&mut self, i: &mut Lit) {
+        visit_lit_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_bool_mut(&mut self, i: &mut LitBool) {
+        visit_lit_bool_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_byte_mut(&mut self, i: &mut LitByte) {
+        visit_lit_byte_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_byte_str_mut(&mut self, i: &mut LitByteStr) {
+        visit_lit_byte_str_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_char_mut(&mut self, i: &mut LitChar) {
+        visit_lit_char_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_float_mut(&mut self, i: &mut LitFloat) {
+        visit_lit_float_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_int_mut(&mut self, i: &mut LitInt) {
+        visit_lit_int_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_str_mut(&mut self, i: &mut LitStr) {
+        visit_lit_str_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_lit_verbatim_mut(&mut self, i: &mut LitVerbatim) {
+        visit_lit_verbatim_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_local_mut(&mut self, i: &mut Local) {
+        visit_local_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_macro_mut(&mut self, i: &mut Macro) {
+        visit_macro_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_macro_delimiter_mut(&mut self, i: &mut MacroDelimiter) {
+        visit_macro_delimiter_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_member_mut(&mut self, i: &mut Member) {
+        visit_member_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_meta_mut(&mut self, i: &mut Meta) {
+        visit_meta_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_meta_list_mut(&mut self, i: &mut MetaList) {
+        visit_meta_list_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_meta_name_value_mut(&mut self, i: &mut MetaNameValue) {
+        visit_meta_name_value_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_method_sig_mut(&mut self, i: &mut MethodSig) {
+        visit_method_sig_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_method_turbofish_mut(&mut self, i: &mut MethodTurbofish) {
+        visit_method_turbofish_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_nested_meta_mut(&mut self, i: &mut NestedMeta) {
+        visit_nested_meta_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_parenthesized_generic_arguments_mut(&mut self, i: &mut ParenthesizedGenericArguments) {
+        visit_parenthesized_generic_arguments_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_mut(&mut self, i: &mut Pat) {
+        visit_pat_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_box_mut(&mut self, i: &mut PatBox) {
+        visit_pat_box_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_ident_mut(&mut self, i: &mut PatIdent) {
+        visit_pat_ident_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_lit_mut(&mut self, i: &mut PatLit) {
+        visit_pat_lit_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_macro_mut(&mut self, i: &mut PatMacro) {
+        visit_pat_macro_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_path_mut(&mut self, i: &mut PatPath) {
+        visit_pat_path_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_range_mut(&mut self, i: &mut PatRange) {
+        visit_pat_range_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_ref_mut(&mut self, i: &mut PatRef) {
+        visit_pat_ref_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_slice_mut(&mut self, i: &mut PatSlice) {
+        visit_pat_slice_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_struct_mut(&mut self, i: &mut PatStruct) {
+        visit_pat_struct_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_tuple_mut(&mut self, i: &mut PatTuple) {
+        visit_pat_tuple_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_tuple_struct_mut(&mut self, i: &mut PatTupleStruct) {
+        visit_pat_tuple_struct_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_verbatim_mut(&mut self, i: &mut PatVerbatim) {
+        visit_pat_verbatim_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_pat_wild_mut(&mut self, i: &mut PatWild) {
+        visit_pat_wild_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_path_mut(&mut self, i: &mut Path) {
+        visit_path_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_path_arguments_mut(&mut self, i: &mut PathArguments) {
+        visit_path_arguments_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_path_segment_mut(&mut self, i: &mut PathSegment) {
+        visit_path_segment_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_predicate_eq_mut(&mut self, i: &mut PredicateEq) {
+        visit_predicate_eq_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_predicate_lifetime_mut(&mut self, i: &mut PredicateLifetime) {
+        visit_predicate_lifetime_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_predicate_type_mut(&mut self, i: &mut PredicateType) {
+        visit_predicate_type_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_qself_mut(&mut self, i: &mut QSelf) {
+        visit_qself_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_range_limits_mut(&mut self, i: &mut RangeLimits) {
+        visit_range_limits_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_return_type_mut(&mut self, i: &mut ReturnType) {
+        visit_return_type_mut(self, i)
+    }
+    fn visit_span_mut(&mut self, i: &mut Span) {
+        visit_span_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[cfg(feature = "full")]
+    fn visit_stmt_mut(&mut self, i: &mut Stmt) {
+        visit_stmt_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_trait_bound_mut(&mut self, i: &mut TraitBound) {
+        visit_trait_bound_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_trait_bound_modifier_mut(&mut self, i: &mut TraitBoundModifier) {
+        visit_trait_bound_modifier_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_mut(&mut self, i: &mut TraitItem) {
+        visit_trait_item_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_const_mut(&mut self, i: &mut TraitItemConst) {
+        visit_trait_item_const_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_existential_mut(&mut self, i: &mut TraitItemExistential) {
+        visit_trait_item_existential_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_macro_mut(&mut self, i: &mut TraitItemMacro) {
+        visit_trait_item_macro_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_method_mut(&mut self, i: &mut TraitItemMethod) {
+        visit_trait_item_method_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_type_mut(&mut self, i: &mut TraitItemType) {
+        visit_trait_item_type_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_trait_item_verbatim_mut(&mut self, i: &mut TraitItemVerbatim) {
+        visit_trait_item_verbatim_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_mut(&mut self, i: &mut Type) {
+        visit_type_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_array_mut(&mut self, i: &mut TypeArray) {
+        visit_type_array_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_bare_fn_mut(&mut self, i: &mut TypeBareFn) {
+        visit_type_bare_fn_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_group_mut(&mut self, i: &mut TypeGroup) {
+        visit_type_group_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_impl_trait_mut(&mut self, i: &mut TypeImplTrait) {
+        visit_type_impl_trait_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_infer_mut(&mut self, i: &mut TypeInfer) {
+        visit_type_infer_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_macro_mut(&mut self, i: &mut TypeMacro) {
+        visit_type_macro_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_never_mut(&mut self, i: &mut TypeNever) {
+        visit_type_never_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_param_mut(&mut self, i: &mut TypeParam) {
+        visit_type_param_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_param_bound_mut(&mut self, i: &mut TypeParamBound) {
+        visit_type_param_bound_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_paren_mut(&mut self, i: &mut TypeParen) {
+        visit_type_paren_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_path_mut(&mut self, i: &mut TypePath) {
+        visit_type_path_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_ptr_mut(&mut self, i: &mut TypePtr) {
+        visit_type_ptr_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_reference_mut(&mut self, i: &mut TypeReference) {
+        visit_type_reference_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_slice_mut(&mut self, i: &mut TypeSlice) {
+        visit_type_slice_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_trait_object_mut(&mut self, i: &mut TypeTraitObject) {
+        visit_type_trait_object_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_tuple_mut(&mut self, i: &mut TypeTuple) {
+        visit_type_tuple_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_type_verbatim_mut(&mut self, i: &mut TypeVerbatim) {
+        visit_type_verbatim_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_un_op_mut(&mut self, i: &mut UnOp) {
+        visit_un_op_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_glob_mut(&mut self, i: &mut UseGlob) {
+        visit_use_glob_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_group_mut(&mut self, i: &mut UseGroup) {
+        visit_use_group_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_name_mut(&mut self, i: &mut UseName) {
+        visit_use_name_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_path_mut(&mut self, i: &mut UsePath) {
+        visit_use_path_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_rename_mut(&mut self, i: &mut UseRename) {
+        visit_use_rename_mut(self, i)
+    }
+    #[cfg(feature = "full")]
+    fn visit_use_tree_mut(&mut self, i: &mut UseTree) {
+        visit_use_tree_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_variant_mut(&mut self, i: &mut Variant) {
+        visit_variant_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_vis_crate_mut(&mut self, i: &mut VisCrate) {
+        visit_vis_crate_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_vis_public_mut(&mut self, i: &mut VisPublic) {
+        visit_vis_public_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_vis_restricted_mut(&mut self, i: &mut VisRestricted) {
+        visit_vis_restricted_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_visibility_mut(&mut self, i: &mut Visibility) {
+        visit_visibility_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_where_clause_mut(&mut self, i: &mut WhereClause) {
+        visit_where_clause_mut(self, i)
+    }
+    #[cfg(any(feature = "full", feature = "derive"))]
+    fn visit_where_predicate_mut(&mut self, i: &mut WherePredicate) {
+        visit_where_predicate_mut(self, i)
+    }
+}
+#[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.span);
+    if let Some(ref mut it) = _i.name {
+        _visitor.visit_lit_str_mut(it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_angle_bracketed_generic_arguments_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut AngleBracketedGenericArguments,
+) {
+    if let Some(ref mut it) = _i.colon2_token {
+        tokens_helper(_visitor, &mut it.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_argument_mut(it)
+    }
+    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.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.span)
+    };
+    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.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.span)
+    };
+    tokens_helper(_visitor, &mut _i.self_token.span);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_arm_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Arm) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.leading_vert {
+        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.span);
+        _visitor.visit_expr_mut(&mut *(it).1);
+    };
+    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.spans)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_attr_style_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut AttrStyle) {
+    match *_i {
+        AttrStyle::Outer => {}
+        AttrStyle::Inner(ref mut _binding_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.spans);
+    _visitor.visit_attr_style_mut(&mut _i.style);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
+    _visitor.visit_path_mut(&mut _i.path);
+    skip!(_i.tts);
+}
+#[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.spans);
+    };
+    _visitor.visit_type_mut(&mut _i.ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_bare_fn_arg_name_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut BareFnArgName) {
+    match *_i {
+        BareFnArgName::Named(ref mut _binding_0) => {
+            _visitor.visit_ident_mut(_binding_0);
+        }
+        BareFnArgName::Wild(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans);
+        }
+        BinOp::Sub(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Mul(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Div(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Rem(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::And(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Or(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::BitXor(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::BitAnd(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::BitOr(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Shl(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Shr(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Eq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Lt(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Le(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Ne(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Ge(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::Gt(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::AddEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::SubEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::MulEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::DivEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::RemEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::BitXorEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::BitAndEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::BitOrEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::ShlEq(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        BinOp::ShrEq(ref mut _binding_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.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.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.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.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.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    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.spans)
+    };
+    if let Some(ref mut it) = _i.default {
+        _visitor.visit_expr_mut(it)
+    };
+}
+#[cfg(feature = "derive")]
+pub fn visit_data_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Data) {
+    match *_i {
+        Data::Struct(ref mut _binding_0) => {
+            _visitor.visit_data_struct_mut(_binding_0);
+        }
+        Data::Enum(ref mut _binding_0) => {
+            _visitor.visit_data_enum_mut(_binding_0);
+        }
+        Data::Union(ref mut _binding_0) => {
+            _visitor.visit_data_union_mut(_binding_0);
+        }
+    }
+}
+#[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.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)
+    }
+}
+#[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.span);
+    _visitor.visit_fields_mut(&mut _i.fields);
+    if let Some(ref mut it) = _i.semi_token {
+        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.span);
+    _visitor.visit_fields_named_mut(&mut _i.fields);
+}
+#[cfg(feature = "derive")]
+pub fn visit_derive_input_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut DeriveInput) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_generics_mut(&mut _i.generics);
+    _visitor.visit_data_mut(&mut _i.data);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Expr) {
+    match *_i {
+        Expr::Box(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_box_mut(_binding_0));
+        }
+        Expr::InPlace(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_in_place_mut(_binding_0));
+        }
+        Expr::Array(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_array_mut(_binding_0));
+        }
+        Expr::Call(ref mut _binding_0) => {
+            _visitor.visit_expr_call_mut(_binding_0);
+        }
+        Expr::MethodCall(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_method_call_mut(_binding_0));
+        }
+        Expr::Tuple(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_tuple_mut(_binding_0));
+        }
+        Expr::Binary(ref mut _binding_0) => {
+            _visitor.visit_expr_binary_mut(_binding_0);
+        }
+        Expr::Unary(ref mut _binding_0) => {
+            _visitor.visit_expr_unary_mut(_binding_0);
+        }
+        Expr::Lit(ref mut _binding_0) => {
+            _visitor.visit_expr_lit_mut(_binding_0);
+        }
+        Expr::Cast(ref mut _binding_0) => {
+            _visitor.visit_expr_cast_mut(_binding_0);
+        }
+        Expr::Type(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_type_mut(_binding_0));
+        }
+        Expr::If(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_if_mut(_binding_0));
+        }
+        Expr::IfLet(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_if_let_mut(_binding_0));
+        }
+        Expr::While(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_while_mut(_binding_0));
+        }
+        Expr::WhileLet(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_while_let_mut(_binding_0));
+        }
+        Expr::ForLoop(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_for_loop_mut(_binding_0));
+        }
+        Expr::Loop(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_loop_mut(_binding_0));
+        }
+        Expr::Match(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_match_mut(_binding_0));
+        }
+        Expr::Closure(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_closure_mut(_binding_0));
+        }
+        Expr::Unsafe(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_unsafe_mut(_binding_0));
+        }
+        Expr::Block(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_block_mut(_binding_0));
+        }
+        Expr::Assign(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_assign_mut(_binding_0));
+        }
+        Expr::AssignOp(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_assign_op_mut(_binding_0));
+        }
+        Expr::Field(ref mut _binding_0) => {
+            _visitor.visit_expr_field_mut(_binding_0);
+        }
+        Expr::Index(ref mut _binding_0) => {
+            _visitor.visit_expr_index_mut(_binding_0);
+        }
+        Expr::Range(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_range_mut(_binding_0));
+        }
+        Expr::Path(ref mut _binding_0) => {
+            _visitor.visit_expr_path_mut(_binding_0);
+        }
+        Expr::Reference(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_reference_mut(_binding_0));
+        }
+        Expr::Break(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_break_mut(_binding_0));
+        }
+        Expr::Continue(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_continue_mut(_binding_0));
+        }
+        Expr::Return(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_return_mut(_binding_0));
+        }
+        Expr::Macro(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_macro_mut(_binding_0));
+        }
+        Expr::Struct(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_struct_mut(_binding_0));
+        }
+        Expr::Repeat(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_repeat_mut(_binding_0));
+        }
+        Expr::Paren(ref mut _binding_0) => {
+            _visitor.visit_expr_paren_mut(_binding_0);
+        }
+        Expr::Group(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_group_mut(_binding_0));
+        }
+        Expr::Try(ref mut _binding_0) => {
+            full!(_visitor.visit_expr_try_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));
+        }
+        Expr::Verbatim(ref mut _binding_0) => {
+            _visitor.visit_expr_verbatim_mut(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_array_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprArray) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    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)
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_assign_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAssign) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.left);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
+    _visitor.visit_expr_mut(&mut *_i.right);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_assign_op_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprAssignOp) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.left);
+    _visitor.visit_bin_op_mut(&mut _i.op);
+    _visitor.visit_expr_mut(&mut *_i.right);
+}
+#[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 {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.left);
+    _visitor.visit_bin_op_mut(&mut _i.op);
+    _visitor.visit_expr_mut(&mut *_i.right);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_block_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBlock) {
+    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")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_box_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBox) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.box_token.span);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_break_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprBreak) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.break_token.span);
+    if let Some(ref mut it) = _i.label {
+        _visitor.visit_lifetime_mut(it)
+    };
+    if let Some(ref mut it) = _i.expr {
+        _visitor.visit_expr_mut(&mut **it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_call_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCall) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.func);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.args) {
+        let it = el.value_mut();
+        _visitor.visit_expr_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_cast_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprCast) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    tokens_helper(_visitor, &mut _i.as_token.span);
+    _visitor.visit_type_mut(&mut *_i.ty);
+}
+#[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.span)
+    };
+    if let Some(ref mut it) = _i.capture {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    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.spans);
+    _visitor.visit_return_type_mut(&mut _i.output);
+    _visitor.visit_expr_mut(&mut *_i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_continue_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprContinue) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.continue_token.span);
+    if let Some(ref mut it) = _i.label {
+        _visitor.visit_lifetime_mut(it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_field_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprField) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.base);
+    tokens_helper(_visitor, &mut _i.dot_token.spans);
+    _visitor.visit_member_mut(&mut _i.member);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_for_loop_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprForLoop) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.label {
+        _visitor.visit_label_mut(it)
+    };
+    tokens_helper(_visitor, &mut _i.for_token.span);
+    _visitor.visit_pat_mut(&mut *_i.pat);
+    tokens_helper(_visitor, &mut _i.in_token.span);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    _visitor.visit_block_mut(&mut _i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_group_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprGroup) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.group_token.span);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_if_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIf) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    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.span);
+        _visitor.visit_expr_mut(&mut *(it).1);
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_if_let_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIfLet) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    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.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.span);
+        _visitor.visit_expr_mut(&mut *(it).1);
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_in_place_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprInPlace) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.place);
+    tokens_helper(_visitor, &mut _i.arrow_token.spans);
+    _visitor.visit_expr_mut(&mut *_i.value);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_index_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprIndex) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
+    _visitor.visit_expr_mut(&mut *_i.index);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_lit_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprLit) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_lit_mut(&mut _i.lit);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_loop_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprLoop) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.label {
+        _visitor.visit_label_mut(it)
+    };
+    tokens_helper(_visitor, &mut _i.loop_token.span);
+    _visitor.visit_block_mut(&mut _i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprMacro) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_macro_mut(&mut _i.mac);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_match_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprMatch) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.match_token.span);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
+    for it in &mut _i.arms {
+        _visitor.visit_arm_mut(it)
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_method_call_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprMethodCall) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.receiver);
+    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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.args) {
+        let it = el.value_mut();
+        _visitor.visit_expr_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_paren_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprParen) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.paren_token.span);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_path_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprPath) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.qself {
+        _visitor.visit_qself_mut(it)
+    };
+    _visitor.visit_path_mut(&mut _i.path);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_range_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprRange) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.from {
+        _visitor.visit_expr_mut(&mut **it)
+    };
+    _visitor.visit_range_limits_mut(&mut _i.limits);
+    if let Some(ref mut it) = _i.to {
+        _visitor.visit_expr_mut(&mut **it)
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_reference_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprReference) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.and_token.spans);
+    if let Some(ref mut it) = _i.mutability {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    _visitor.visit_expr_mut(&mut *_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_repeat_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprRepeat) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.bracket_token.span);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+    _visitor.visit_expr_mut(&mut *_i.len);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_return_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprReturn) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.return_token.span);
+    if let Some(ref mut it) = _i.expr {
+        _visitor.visit_expr_mut(&mut **it)
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_struct_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprStruct) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_path_mut(&mut _i.path);
+    tokens_helper(_visitor, &mut _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.spans)
+    };
+    if let Some(ref mut it) = _i.rest {
+        _visitor.visit_expr_mut(&mut **it)
+    };
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_try_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprTry) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    tokens_helper(_visitor, &mut _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"))]
+pub fn visit_expr_tuple_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprTuple) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    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)
+    }
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_type_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprType) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
+    _visitor.visit_type_mut(&mut *_i.ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_unary_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprUnary) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_un_op_mut(&mut _i.op);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_unsafe_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprUnsafe) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.unsafe_token.span);
+    _visitor.visit_block_mut(&mut _i.block);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_verbatim_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprVerbatim) {
+    skip!(_i.tts);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_while_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprWhile) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.label {
+        _visitor.visit_label_mut(it)
+    };
+    tokens_helper(_visitor, &mut _i.while_token.span);
+    _visitor.visit_expr_mut(&mut *_i.cond);
+    _visitor.visit_block_mut(&mut _i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_while_let_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprWhileLet) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.label {
+        _visitor.visit_label_mut(it)
+    };
+    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.spans);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    _visitor.visit_block_mut(&mut _i.body);
+}
+#[cfg(feature = "full")]
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_expr_yield_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ExprYield) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.yield_token.span);
+    if let Some(ref mut it) = _i.expr {
+        _visitor.visit_expr_mut(&mut **it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_field_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Field) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    if let Some(ref mut it) = _i.ident {
+        _visitor.visit_ident_mut(it)
+    };
+    if let Some(ref mut it) = _i.colon_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    _visitor.visit_type_mut(&mut _i.ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_field_pat_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut FieldPat) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_member_mut(&mut _i.member);
+    if let Some(ref mut it) = _i.colon_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    _visitor.visit_pat_mut(&mut *_i.pat);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_field_value_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut FieldValue) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_member_mut(&mut _i.member);
+    if let Some(ref mut it) = _i.colon_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    _visitor.visit_expr_mut(&mut _i.expr);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_fields_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Fields) {
+    match *_i {
+        Fields::Named(ref mut _binding_0) => {
+            _visitor.visit_fields_named_mut(_binding_0);
+        }
+        Fields::Unnamed(ref mut _binding_0) => {
+            _visitor.visit_fields_unnamed_mut(_binding_0);
+        }
+        Fields::Unit => {}
+    }
+}
+#[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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.named) {
+        let it = el.value_mut();
+        _visitor.visit_field_mut(it)
+    }
+}
+#[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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.unnamed) {
+        let it = el.value_mut();
+        _visitor.visit_field_mut(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_file_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut File) {
+    skip!(_i.shebang);
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    for it in &mut _i.items {
+        _visitor.visit_item_mut(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_fn_arg_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut FnArg) {
+    match *_i {
+        FnArg::SelfRef(ref mut _binding_0) => {
+            _visitor.visit_arg_self_ref_mut(_binding_0);
+        }
+        FnArg::SelfValue(ref mut _binding_0) => {
+            _visitor.visit_arg_self_mut(_binding_0);
+        }
+        FnArg::Captured(ref mut _binding_0) => {
+            _visitor.visit_arg_captured_mut(_binding_0);
+        }
+        FnArg::Inferred(ref mut _binding_0) => {
+            _visitor.visit_pat_mut(_binding_0);
+        }
+        FnArg::Ignored(ref mut _binding_0) => {
+            _visitor.visit_type_mut(_binding_0);
+        }
+    }
+}
+#[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.span);
+    _visitor.visit_generics_mut(&mut _i.generics);
+    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.spans)
+    };
+    _visitor.visit_return_type_mut(&mut _i.output);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ForeignItem) {
+    match *_i {
+        ForeignItem::Fn(ref mut _binding_0) => {
+            _visitor.visit_foreign_item_fn_mut(_binding_0);
+        }
+        ForeignItem::Static(ref mut _binding_0) => {
+            _visitor.visit_foreign_item_static_mut(_binding_0);
+        }
+        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);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_fn_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ForeignItemFn) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_fn_decl_mut(&mut *_i.decl);
+    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>(
+    _visitor: &mut V,
+    _i: &mut ForeignItemStatic,
+) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    tokens_helper(_visitor, &mut _i.static_token.span);
+    if let Some(ref mut it) = _i.mutability {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    _visitor.visit_ident_mut(&mut _i.ident);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
+    _visitor.visit_type_mut(&mut *_i.ty);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_type_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut ForeignItemType,
+) {
+    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.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_foreign_item_verbatim_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut ForeignItemVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_generic_argument_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut GenericArgument,
+) {
+    match *_i {
+        GenericArgument::Lifetime(ref mut _binding_0) => {
+            _visitor.visit_lifetime_mut(_binding_0);
+        }
+        GenericArgument::Type(ref mut _binding_0) => {
+            _visitor.visit_type_mut(_binding_0);
+        }
+        GenericArgument::Binding(ref mut _binding_0) => {
+            _visitor.visit_binding_mut(_binding_0);
+        }
+        GenericArgument::Const(ref mut _binding_0) => {
+            _visitor.visit_expr_mut(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_generic_method_argument_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut GenericMethodArgument,
+) {
+    match *_i {
+        GenericMethodArgument::Type(ref mut _binding_0) => {
+            _visitor.visit_type_mut(_binding_0);
+        }
+        GenericMethodArgument::Const(ref mut _binding_0) => {
+            _visitor.visit_expr_mut(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_generic_param_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut GenericParam) {
+    match *_i {
+        GenericParam::Type(ref mut _binding_0) => {
+            _visitor.visit_type_param_mut(_binding_0);
+        }
+        GenericParam::Lifetime(ref mut _binding_0) => {
+            _visitor.visit_lifetime_def_mut(_binding_0);
+        }
+        GenericParam::Const(ref mut _binding_0) => {
+            _visitor.visit_const_param_mut(_binding_0);
+        }
+    }
+}
+#[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.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.spans)
+    };
+    if let Some(ref mut it) = _i.where_clause {
+        _visitor.visit_where_clause_mut(it)
+    };
+}
+pub fn visit_ident_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Ident) {}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ImplItem) {
+    match *_i {
+        ImplItem::Const(ref mut _binding_0) => {
+            _visitor.visit_impl_item_const_mut(_binding_0);
+        }
+        ImplItem::Method(ref mut _binding_0) => {
+            _visitor.visit_impl_item_method_mut(_binding_0);
+        }
+        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);
+        }
+        ImplItem::Verbatim(ref mut _binding_0) => {
+            _visitor.visit_impl_item_verbatim_mut(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_const_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ImplItemConst) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    if let Some(ref mut it) = _i.defaultness {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    tokens_helper(_visitor, &mut _i.const_token.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
+    _visitor.visit_type_mut(&mut _i.ty);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
+    _visitor.visit_expr_mut(&mut _i.expr);
+    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) {
+    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_impl_item_method_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ImplItemMethod) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    if let Some(ref mut it) = _i.defaultness {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    _visitor.visit_method_sig_mut(&mut _i.sig);
+    _visitor.visit_block_mut(&mut _i.block);
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_type_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ImplItemType) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    if let Some(ref mut it) = _i.defaultness {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    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.spans);
+    _visitor.visit_type_mut(&mut _i.ty);
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_impl_item_verbatim_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut ImplItemVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_index_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Index) {
+    skip!(_i.index);
+    _visitor.visit_span_mut(&mut _i.span);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Item) {
+    match *_i {
+        Item::ExternCrate(ref mut _binding_0) => {
+            _visitor.visit_item_extern_crate_mut(_binding_0);
+        }
+        Item::Use(ref mut _binding_0) => {
+            _visitor.visit_item_use_mut(_binding_0);
+        }
+        Item::Static(ref mut _binding_0) => {
+            _visitor.visit_item_static_mut(_binding_0);
+        }
+        Item::Const(ref mut _binding_0) => {
+            _visitor.visit_item_const_mut(_binding_0);
+        }
+        Item::Fn(ref mut _binding_0) => {
+            _visitor.visit_item_fn_mut(_binding_0);
+        }
+        Item::Mod(ref mut _binding_0) => {
+            _visitor.visit_item_mod_mut(_binding_0);
+        }
+        Item::ForeignMod(ref mut _binding_0) => {
+            _visitor.visit_item_foreign_mod_mut(_binding_0);
+        }
+        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);
+        }
+        Item::Enum(ref mut _binding_0) => {
+            _visitor.visit_item_enum_mut(_binding_0);
+        }
+        Item::Union(ref mut _binding_0) => {
+            _visitor.visit_item_union_mut(_binding_0);
+        }
+        Item::Trait(ref mut _binding_0) => {
+            _visitor.visit_item_trait_mut(_binding_0);
+        }
+        Item::Impl(ref mut _binding_0) => {
+            _visitor.visit_item_impl_mut(_binding_0);
+        }
+        Item::Macro(ref mut _binding_0) => {
+            _visitor.visit_item_macro_mut(_binding_0);
+        }
+        Item::Macro2(ref mut _binding_0) => {
+            _visitor.visit_item_macro2_mut(_binding_0);
+        }
+        Item::Verbatim(ref mut _binding_0) => {
+            _visitor.visit_item_verbatim_mut(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_item_const_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemConst) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    tokens_helper(_visitor, &mut _i.const_token.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
+    _visitor.visit_type_mut(&mut *_i.ty);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    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) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    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.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,
+) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    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.span);
+        _visitor.visit_ident_mut(&mut (it).1);
+    };
+    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) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    if let Some(ref mut it) = _i.constness {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    if let Some(ref mut it) = _i.unsafety {
+        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)
+    };
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_fn_decl_mut(&mut *_i.decl);
+    _visitor.visit_block_mut(&mut *_i.block);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_foreign_mod_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemForeignMod) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_abi_mut(&mut _i.abi);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
+    for it in &mut _i.items {
+        _visitor.visit_foreign_item_mut(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_item_impl_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemImpl) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.defaultness {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    if let Some(ref mut it) = _i.unsafety {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    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.spans)
+        };
+        _visitor.visit_path_mut(&mut (it).1);
+        tokens_helper(_visitor, &mut (it).2.span);
+    };
+    _visitor.visit_type_mut(&mut *_i.self_ty);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
+    for it in &mut _i.items {
+        _visitor.visit_impl_item_mut(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_item_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemMacro) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    if let Some(ref mut it) = _i.ident {
+        _visitor.visit_ident_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_item_macro2_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemMacro2) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    tokens_helper(_visitor, &mut _i.macro_token.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
+    skip!(_i.args);
+    tokens_helper(_visitor, &mut _i.brace_token.span);
+    skip!(_i.body);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_mod_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemMod) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    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.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.spans)
+    };
+}
+#[cfg(feature = "full")]
+pub fn visit_item_static_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemStatic) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    tokens_helper(_visitor, &mut _i.static_token.span);
+    if let Some(ref mut it) = _i.mutability {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    _visitor.visit_ident_mut(&mut _i.ident);
+    tokens_helper(_visitor, &mut _i.colon_token.spans);
+    _visitor.visit_type_mut(&mut *_i.ty);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
+    _visitor.visit_expr_mut(&mut *_i.expr);
+    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) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    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.spans)
+    };
+}
+#[cfg(feature = "full")]
+pub fn visit_item_trait_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemTrait) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    if let Some(ref mut it) = _i.unsafety {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    if let Some(ref mut it) = _i.auto_token {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    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.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.span);
+    for it in &mut _i.items {
+        _visitor.visit_trait_item_mut(it)
+    }
+}
+#[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.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_generics_mut(&mut _i.generics);
+    tokens_helper(_visitor, &mut _i.eq_token.spans);
+    _visitor.visit_type_mut(&mut *_i.ty);
+    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) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    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);
+}
+#[cfg(feature = "full")]
+pub fn visit_item_use_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ItemUse) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_visibility_mut(&mut _i.vis);
+    tokens_helper(_visitor, &mut _i.use_token.span);
+    if let Some(ref mut it) = _i.leading_colon {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    _visitor.visit_use_tree_mut(&mut _i.tree);
+    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) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.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_ident_mut(&mut _i.ident);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lifetime_def_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LifetimeDef) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_lifetime_mut(&mut _i.lifetime);
+    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_lifetime_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Lit) {
+    match *_i {
+        Lit::Str(ref mut _binding_0) => {
+            _visitor.visit_lit_str_mut(_binding_0);
+        }
+        Lit::ByteStr(ref mut _binding_0) => {
+            _visitor.visit_lit_byte_str_mut(_binding_0);
+        }
+        Lit::Byte(ref mut _binding_0) => {
+            _visitor.visit_lit_byte_mut(_binding_0);
+        }
+        Lit::Char(ref mut _binding_0) => {
+            _visitor.visit_lit_char_mut(_binding_0);
+        }
+        Lit::Int(ref mut _binding_0) => {
+            _visitor.visit_lit_int_mut(_binding_0);
+        }
+        Lit::Float(ref mut _binding_0) => {
+            _visitor.visit_lit_float_mut(_binding_0);
+        }
+        Lit::Bool(ref mut _binding_0) => {
+            _visitor.visit_lit_bool_mut(_binding_0);
+        }
+        Lit::Verbatim(ref mut _binding_0) => {
+            _visitor.visit_lit_verbatim_mut(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_bool_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitBool) {
+    skip!(_i.value);
+    _visitor.visit_span_mut(&mut _i.span);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_byte_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitByte) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_byte_str_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitByteStr) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_char_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitChar) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_float_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitFloat) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_int_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitInt) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_str_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitStr) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_lit_verbatim_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut LitVerbatim) {
+    skip!(_i.token);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_local_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Local) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    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.spans);
+        _visitor.visit_type_mut(&mut *(it).1);
+    };
+    if let Some(ref mut it) = _i.init {
+        tokens_helper(_visitor, &mut (it).0.spans);
+        _visitor.visit_expr_mut(&mut *(it).1);
+    };
+    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.spans);
+    _visitor.visit_macro_delimiter_mut(&mut _i.delimiter);
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.span);
+        }
+        MacroDelimiter::Brace(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.span);
+        }
+        MacroDelimiter::Bracket(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.span);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_member_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Member) {
+    match *_i {
+        Member::Named(ref mut _binding_0) => {
+            _visitor.visit_ident_mut(_binding_0);
+        }
+        Member::Unnamed(ref mut _binding_0) => {
+            _visitor.visit_index_mut(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_meta_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Meta) {
+    match *_i {
+        Meta::Word(ref mut _binding_0) => {
+            _visitor.visit_ident_mut(_binding_0);
+        }
+        Meta::List(ref mut _binding_0) => {
+            _visitor.visit_meta_list_mut(_binding_0);
+        }
+        Meta::NameValue(ref mut _binding_0) => {
+            _visitor.visit_meta_name_value_mut(_binding_0);
+        }
+    }
+}
+#[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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.nested) {
+        let it = el.value_mut();
+        _visitor.visit_nested_meta_mut(it)
+    }
+}
+#[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.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.span)
+    };
+    if let Some(ref mut it) = _i.unsafety {
+        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)
+    };
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_fn_decl_mut(&mut _i.decl);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_method_turbofish_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut MethodTurbofish,
+) {
+    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.spans);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_nested_meta_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut NestedMeta) {
+    match *_i {
+        NestedMeta::Meta(ref mut _binding_0) => {
+            _visitor.visit_meta_mut(_binding_0);
+        }
+        NestedMeta::Literal(ref mut _binding_0) => {
+            _visitor.visit_lit_mut(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_parenthesized_generic_arguments_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut ParenthesizedGenericArguments,
+) {
+    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)
+    }
+    _visitor.visit_return_type_mut(&mut _i.output);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Pat) {
+    match *_i {
+        Pat::Wild(ref mut _binding_0) => {
+            _visitor.visit_pat_wild_mut(_binding_0);
+        }
+        Pat::Ident(ref mut _binding_0) => {
+            _visitor.visit_pat_ident_mut(_binding_0);
+        }
+        Pat::Struct(ref mut _binding_0) => {
+            _visitor.visit_pat_struct_mut(_binding_0);
+        }
+        Pat::TupleStruct(ref mut _binding_0) => {
+            _visitor.visit_pat_tuple_struct_mut(_binding_0);
+        }
+        Pat::Path(ref mut _binding_0) => {
+            _visitor.visit_pat_path_mut(_binding_0);
+        }
+        Pat::Tuple(ref mut _binding_0) => {
+            _visitor.visit_pat_tuple_mut(_binding_0);
+        }
+        Pat::Box(ref mut _binding_0) => {
+            _visitor.visit_pat_box_mut(_binding_0);
+        }
+        Pat::Ref(ref mut _binding_0) => {
+            _visitor.visit_pat_ref_mut(_binding_0);
+        }
+        Pat::Lit(ref mut _binding_0) => {
+            _visitor.visit_pat_lit_mut(_binding_0);
+        }
+        Pat::Range(ref mut _binding_0) => {
+            _visitor.visit_pat_range_mut(_binding_0);
+        }
+        Pat::Slice(ref mut _binding_0) => {
+            _visitor.visit_pat_slice_mut(_binding_0);
+        }
+        Pat::Macro(ref mut _binding_0) => {
+            _visitor.visit_pat_macro_mut(_binding_0);
+        }
+        Pat::Verbatim(ref mut _binding_0) => {
+            _visitor.visit_pat_verbatim_mut(_binding_0);
+        }
+    }
+}
+#[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.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.span)
+    };
+    if let Some(ref mut it) = _i.mutability {
+        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.spans);
+        _visitor.visit_pat_mut(&mut *(it).1);
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_lit_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatLit) {
+    _visitor.visit_expr_mut(&mut *_i.expr);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatMacro) {
+    _visitor.visit_macro_mut(&mut _i.mac);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_path_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatPath) {
+    if let Some(ref mut it) = _i.qself {
+        _visitor.visit_qself_mut(it)
+    };
+    _visitor.visit_path_mut(&mut _i.path);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_range_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatRange) {
+    _visitor.visit_expr_mut(&mut *_i.lo);
+    _visitor.visit_range_limits_mut(&mut _i.limits);
+    _visitor.visit_expr_mut(&mut *_i.hi);
+}
+#[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.spans);
+    if let Some(ref mut it) = _i.mutability {
+        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.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.middle {
+        _visitor.visit_pat_mut(&mut **it)
+    };
+    if let Some(ref mut it) = _i.dot2_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    if let Some(ref mut it) = _i.comma_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    for mut el in Punctuated::pairs_mut(&mut _i.back) {
+        let it = el.value_mut();
+        _visitor.visit_pat_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[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.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.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.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.spans)
+    };
+    if let Some(ref mut it) = _i.comma_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    for mut el in Punctuated::pairs_mut(&mut _i.back) {
+        let it = el.value_mut();
+        _visitor.visit_pat_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_tuple_struct_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatTupleStruct) {
+    _visitor.visit_path_mut(&mut _i.path);
+    _visitor.visit_pat_tuple_mut(&mut _i.pat);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_pat_verbatim_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PatVerbatim) {
+    skip!(_i.tts);
+}
+#[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.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.spans)
+    };
+    for mut el in Punctuated::pairs_mut(&mut _i.segments) {
+        let it = el.value_mut();
+        _visitor.visit_path_segment_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_path_arguments_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PathArguments) {
+    match *_i {
+        PathArguments::None => {}
+        PathArguments::AngleBracketed(ref mut _binding_0) => {
+            _visitor.visit_angle_bracketed_generic_arguments_mut(_binding_0);
+        }
+        PathArguments::Parenthesized(ref mut _binding_0) => {
+            _visitor.visit_parenthesized_generic_arguments_mut(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_path_segment_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PathSegment) {
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_path_arguments_mut(&mut _i.arguments);
+}
+#[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.spans);
+    _visitor.visit_type_mut(&mut _i.rhs_ty);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_predicate_lifetime_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut PredicateLifetime,
+) {
+    _visitor.visit_lifetime_mut(&mut _i.lifetime);
+    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_lifetime_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_predicate_type_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut PredicateType) {
+    if let Some(ref mut it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes_mut(it)
+    };
+    _visitor.visit_type_mut(&mut _i.bounded_ty);
+    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)
+    }
+}
+#[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.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.span)
+    };
+    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.spans);
+        }
+        RangeLimits::Closed(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_return_type_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut ReturnType) {
+    match *_i {
+        ReturnType::Default => {}
+        ReturnType::Type(ref mut _binding_0, ref mut _binding_1) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+            _visitor.visit_type_mut(&mut **_binding_1);
+        }
+    }
+}
+pub fn visit_span_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Span) {}
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg(feature = "full")]
+pub fn visit_stmt_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Stmt) {
+    match *_i {
+        Stmt::Local(ref mut _binding_0) => {
+            _visitor.visit_local_mut(_binding_0);
+        }
+        Stmt::Item(ref mut _binding_0) => {
+            _visitor.visit_item_mut(_binding_0);
+        }
+        Stmt::Expr(ref mut _binding_0) => {
+            _visitor.visit_expr_mut(_binding_0);
+        }
+        Stmt::Semi(ref mut _binding_0, ref mut _binding_1) => {
+            _visitor.visit_expr_mut(_binding_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.span)
+    };
+    _visitor.visit_trait_bound_modifier_mut(&mut _i.modifier);
+    if let Some(ref mut it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes_mut(it)
+    };
+    _visitor.visit_path_mut(&mut _i.path);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_trait_bound_modifier_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut TraitBoundModifier,
+) {
+    match *_i {
+        TraitBoundModifier::None => {}
+        TraitBoundModifier::Maybe(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TraitItem) {
+    match *_i {
+        TraitItem::Const(ref mut _binding_0) => {
+            _visitor.visit_trait_item_const_mut(_binding_0);
+        }
+        TraitItem::Method(ref mut _binding_0) => {
+            _visitor.visit_trait_item_method_mut(_binding_0);
+        }
+        TraitItem::Type(ref mut _binding_0) => {
+            _visitor.visit_trait_item_type_mut(_binding_0);
+        }
+        TraitItem::Existential(ref mut _binding_0) => {
+            _visitor.visit_trait_item_existential_mut(_binding_0);
+        }
+        TraitItem::Macro(ref mut _binding_0) => {
+            _visitor.visit_trait_item_macro_mut(_binding_0);
+        }
+        TraitItem::Verbatim(ref mut _binding_0) => {
+            _visitor.visit_trait_item_verbatim_mut(_binding_0);
+        }
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_const_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TraitItemConst) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    tokens_helper(_visitor, &mut _i.const_token.span);
+    _visitor.visit_ident_mut(&mut _i.ident);
+    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.spans);
+        _visitor.visit_expr_mut(&mut (it).1);
+    };
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_existential_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut TraitItemExistential,
+) {
+    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_trait_item_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TraitItemMacro) {
+    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_trait_item_method_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut TraitItemMethod,
+) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_method_sig_mut(&mut _i.sig);
+    if let Some(ref mut it) = _i.default {
+        _visitor.visit_block_mut(it)
+    };
+    if let Some(ref mut it) = _i.semi_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_type_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TraitItemType) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    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)
+    }
+    if let Some(ref mut it) = _i.default {
+        tokens_helper(_visitor, &mut (it).0.spans);
+        _visitor.visit_type_mut(&mut (it).1);
+    };
+    tokens_helper(_visitor, &mut _i.semi_token.spans);
+}
+#[cfg(feature = "full")]
+pub fn visit_trait_item_verbatim_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut TraitItemVerbatim,
+) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Type) {
+    match *_i {
+        Type::Slice(ref mut _binding_0) => {
+            _visitor.visit_type_slice_mut(_binding_0);
+        }
+        Type::Array(ref mut _binding_0) => {
+            _visitor.visit_type_array_mut(_binding_0);
+        }
+        Type::Ptr(ref mut _binding_0) => {
+            _visitor.visit_type_ptr_mut(_binding_0);
+        }
+        Type::Reference(ref mut _binding_0) => {
+            _visitor.visit_type_reference_mut(_binding_0);
+        }
+        Type::BareFn(ref mut _binding_0) => {
+            _visitor.visit_type_bare_fn_mut(_binding_0);
+        }
+        Type::Never(ref mut _binding_0) => {
+            _visitor.visit_type_never_mut(_binding_0);
+        }
+        Type::Tuple(ref mut _binding_0) => {
+            _visitor.visit_type_tuple_mut(_binding_0);
+        }
+        Type::Path(ref mut _binding_0) => {
+            _visitor.visit_type_path_mut(_binding_0);
+        }
+        Type::TraitObject(ref mut _binding_0) => {
+            _visitor.visit_type_trait_object_mut(_binding_0);
+        }
+        Type::ImplTrait(ref mut _binding_0) => {
+            _visitor.visit_type_impl_trait_mut(_binding_0);
+        }
+        Type::Paren(ref mut _binding_0) => {
+            _visitor.visit_type_paren_mut(_binding_0);
+        }
+        Type::Group(ref mut _binding_0) => {
+            _visitor.visit_type_group_mut(_binding_0);
+        }
+        Type::Infer(ref mut _binding_0) => {
+            _visitor.visit_type_infer_mut(_binding_0);
+        }
+        Type::Macro(ref mut _binding_0) => {
+            _visitor.visit_type_macro_mut(_binding_0);
+        }
+        Type::Verbatim(ref mut _binding_0) => {
+            _visitor.visit_type_verbatim_mut(_binding_0);
+        }
+    }
+}
+#[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.span);
+    _visitor.visit_type_mut(&mut *_i.elem);
+    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.unsafety {
+        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.span);
+    if let Some(ref mut it) = _i.lifetimes {
+        _visitor.visit_bound_lifetimes_mut(it)
+    };
+    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.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.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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
+        let it = el.value_mut();
+        _visitor.visit_type_param_bound_mut(it)
+    }
+}
+#[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.spans);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_macro_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeMacro) {
+    _visitor.visit_macro_mut(&mut _i.mac);
+}
+#[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.spans);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_param_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeParam) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_ident_mut(&mut _i.ident);
+    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)
+    }
+    if let Some(ref mut it) = _i.eq_token {
+        tokens_helper(_visitor, &mut it.spans)
+    };
+    if let Some(ref mut it) = _i.default {
+        _visitor.visit_type_mut(it)
+    };
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_param_bound_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeParamBound) {
+    match *_i {
+        TypeParamBound::Trait(ref mut _binding_0) => {
+            _visitor.visit_trait_bound_mut(_binding_0);
+        }
+        TypeParamBound::Lifetime(ref mut _binding_0) => {
+            _visitor.visit_lifetime_mut(_binding_0);
+        }
+    }
+}
+#[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.span);
+    _visitor.visit_type_mut(&mut *_i.elem);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_path_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypePath) {
+    if let Some(ref mut it) = _i.qself {
+        _visitor.visit_qself_mut(it)
+    };
+    _visitor.visit_path_mut(&mut _i.path);
+}
+#[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.spans);
+    if let Some(ref mut it) = _i.const_token {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    if let Some(ref mut it) = _i.mutability {
+        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.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.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.span);
+    _visitor.visit_type_mut(&mut *_i.elem);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_trait_object_mut<V: VisitMut + ?Sized>(
+    _visitor: &mut V,
+    _i: &mut TypeTraitObject,
+) {
+    if let Some(ref mut it) = _i.dyn_token {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    for mut el in Punctuated::pairs_mut(&mut _i.bounds) {
+        let it = el.value_mut();
+        _visitor.visit_type_param_bound_mut(it)
+    }
+}
+#[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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.elems) {
+        let it = el.value_mut();
+        _visitor.visit_type_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_type_verbatim_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut TypeVerbatim) {
+    skip!(_i.tts);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+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.spans);
+        }
+        UnOp::Not(ref mut _binding_0) => {
+            tokens_helper(_visitor, &mut _binding_0.spans);
+        }
+        UnOp::Neg(ref mut _binding_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.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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.items) {
+        let it = el.value_mut();
+        _visitor.visit_use_tree_mut(it)
+    }
+}
+#[cfg(feature = "full")]
+pub fn visit_use_name_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut UseName) {
+    _visitor.visit_ident_mut(&mut _i.ident);
+}
+#[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.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.span);
+    _visitor.visit_ident_mut(&mut _i.rename);
+}
+#[cfg(feature = "full")]
+pub fn visit_use_tree_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut UseTree) {
+    match *_i {
+        UseTree::Path(ref mut _binding_0) => {
+            _visitor.visit_use_path_mut(_binding_0);
+        }
+        UseTree::Name(ref mut _binding_0) => {
+            _visitor.visit_use_name_mut(_binding_0);
+        }
+        UseTree::Rename(ref mut _binding_0) => {
+            _visitor.visit_use_rename_mut(_binding_0);
+        }
+        UseTree::Glob(ref mut _binding_0) => {
+            _visitor.visit_use_glob_mut(_binding_0);
+        }
+        UseTree::Group(ref mut _binding_0) => {
+            _visitor.visit_use_group_mut(_binding_0);
+        }
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_variant_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Variant) {
+    for it in &mut _i.attrs {
+        _visitor.visit_attribute_mut(it)
+    }
+    _visitor.visit_ident_mut(&mut _i.ident);
+    _visitor.visit_fields_mut(&mut _i.fields);
+    if let Some(ref mut it) = _i.discriminant {
+        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.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.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.span);
+    tokens_helper(_visitor, &mut _i.paren_token.span);
+    if let Some(ref mut it) = _i.in_token {
+        tokens_helper(_visitor, &mut it.span)
+    };
+    _visitor.visit_path_mut(&mut *_i.path);
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_visibility_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut Visibility) {
+    match *_i {
+        Visibility::Public(ref mut _binding_0) => {
+            _visitor.visit_vis_public_mut(_binding_0);
+        }
+        Visibility::Crate(ref mut _binding_0) => {
+            _visitor.visit_vis_crate_mut(_binding_0);
+        }
+        Visibility::Restricted(ref mut _binding_0) => {
+            _visitor.visit_vis_restricted_mut(_binding_0);
+        }
+        Visibility::Inherited => {}
+    }
+}
+#[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.span);
+    for mut el in Punctuated::pairs_mut(&mut _i.predicates) {
+        let it = el.value_mut();
+        _visitor.visit_where_predicate_mut(it)
+    }
+}
+#[cfg(any(feature = "full", feature = "derive"))]
+pub fn visit_where_predicate_mut<V: VisitMut + ?Sized>(_visitor: &mut V, _i: &mut WherePredicate) {
+    match *_i {
+        WherePredicate::Type(ref mut _binding_0) => {
+            _visitor.visit_predicate_type_mut(_binding_0);
+        }
+        WherePredicate::Lifetime(ref mut _binding_0) => {
+            _visitor.visit_predicate_lifetime_mut(_binding_0);
+        }
+        WherePredicate::Eq(ref mut _binding_0) => {
+            _visitor.visit_predicate_eq_mut(_binding_0);
+        }
+    }
+}
diff --git a/src/gen_helper.rs b/src/gen_helper.rs
new file mode 100644
index 0000000..fe00c8f
--- /dev/null
+++ b/src/gen_helper.rs
@@ -0,0 +1,162 @@
+// 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 = "fold")]
+pub mod fold {
+    use fold::Fold;
+    use proc_macro2::Span;
+    use punctuated::{Pair, Punctuated};
+
+    pub trait FoldHelper {
+        type Item;
+        fn lift<F>(self, f: F) -> Self
+        where
+            F: FnMut(Self::Item) -> Self::Item;
+    }
+
+    impl<T> FoldHelper for Vec<T> {
+        type Item = T;
+        fn lift<F>(self, f: F) -> Self
+        where
+            F: FnMut(Self::Item) -> Self::Item,
+        {
+            self.into_iter().map(f).collect()
+        }
+    }
+
+    impl<T, U> FoldHelper for Punctuated<T, U> {
+        type Item = T;
+        fn lift<F>(self, mut f: F) -> Self
+        where
+            F: FnMut(Self::Item) -> Self::Item,
+        {
+            self.into_pairs()
+                .map(Pair::into_tuple)
+                .map(|(t, u)| Pair::new(f(t), u))
+                .collect()
+        }
+    }
+
+    pub fn tokens_helper<F: Fold + ?Sized, S: Spans>(folder: &mut F, spans: &S) -> S {
+        spans.fold(folder)
+    }
+
+    pub trait Spans {
+        fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self;
+    }
+
+    impl Spans for Span {
+        fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
+            folder.fold_span(*self)
+        }
+    }
+
+    impl Spans for [Span; 1] {
+        fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
+            [folder.fold_span(self[0])]
+        }
+    }
+
+    impl Spans for [Span; 2] {
+        fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
+            [folder.fold_span(self[0]), folder.fold_span(self[1])]
+        }
+    }
+
+    impl Spans for [Span; 3] {
+        fn fold<F: Fold + ?Sized>(&self, folder: &mut F) -> Self {
+            [
+                folder.fold_span(self[0]),
+                folder.fold_span(self[1]),
+                folder.fold_span(self[2]),
+            ]
+        }
+    }
+}
+
+#[cfg(feature = "visit")]
+pub mod visit {
+    use proc_macro2::Span;
+    use visit::Visit;
+
+    pub fn tokens_helper<'ast, V: Visit<'ast> + ?Sized, S: Spans>(visitor: &mut V, spans: &'ast S) {
+        spans.visit(visitor);
+    }
+
+    pub trait Spans {
+        fn visit<'ast, V: Visit<'ast> + ?Sized>(&'ast self, visitor: &mut V);
+    }
+
+    impl Spans for Span {
+        fn visit<'ast, V: Visit<'ast> + ?Sized>(&'ast self, visitor: &mut V) {
+            visitor.visit_span(self);
+        }
+    }
+
+    impl Spans for [Span; 1] {
+        fn visit<'ast, V: Visit<'ast> + ?Sized>(&'ast self, visitor: &mut V) {
+            visitor.visit_span(&self[0]);
+        }
+    }
+
+    impl Spans for [Span; 2] {
+        fn visit<'ast, V: Visit<'ast> + ?Sized>(&'ast self, visitor: &mut V) {
+            visitor.visit_span(&self[0]);
+            visitor.visit_span(&self[1]);
+        }
+    }
+
+    impl Spans for [Span; 3] {
+        fn visit<'ast, V: Visit<'ast> + ?Sized>(&'ast self, visitor: &mut V) {
+            visitor.visit_span(&self[0]);
+            visitor.visit_span(&self[1]);
+            visitor.visit_span(&self[2]);
+        }
+    }
+}
+
+#[cfg(feature = "visit-mut")]
+pub mod visit_mut {
+    use proc_macro2::Span;
+    use visit_mut::VisitMut;
+
+    pub fn tokens_helper<V: VisitMut + ?Sized, S: Spans>(visitor: &mut V, spans: &mut S) {
+        spans.visit_mut(visitor);
+    }
+
+    pub trait Spans {
+        fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V);
+    }
+
+    impl Spans for Span {
+        fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
+            visitor.visit_span_mut(self);
+        }
+    }
+
+    impl Spans for [Span; 1] {
+        fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
+            visitor.visit_span_mut(&mut self[0]);
+        }
+    }
+
+    impl Spans for [Span; 2] {
+        fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
+            visitor.visit_span_mut(&mut self[0]);
+            visitor.visit_span_mut(&mut self[1]);
+        }
+    }
+
+    impl Spans for [Span; 3] {
+        fn visit_mut<V: VisitMut + ?Sized>(&mut self, visitor: &mut V) {
+            visitor.visit_span_mut(&mut self[0]);
+            visitor.visit_span_mut(&mut self[1]);
+            visitor.visit_span_mut(&mut self[2]);
+        }
+    }
+}
diff --git a/src/generics.rs b/src/generics.rs
new file mode 100644
index 0000000..fb8d672
--- /dev/null
+++ b/src/generics.rs
@@ -0,0 +1,1015 @@
+// 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 super::*;
+use punctuated::{Iter, IterMut, Punctuated};
+
+ast_struct! {
+    /// Lifetimes and type parameters attached to a declaration of a function,
+    /// enum, trait, etc.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    #[derive(Default)]
+    pub struct Generics {
+        pub lt_token: Option<Token![<]>,
+        pub params: Punctuated<GenericParam, Token![,]>,
+        pub gt_token: Option<Token![>]>,
+        pub where_clause: Option<WhereClause>,
+    }
+}
+
+ast_enum_of_structs! {
+    /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
+    /// `'a: 'b`, `const LEN: usize`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum GenericParam {
+        /// A generic type parameter: `T: Into<String>`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Type(TypeParam {
+            pub attrs: Vec<Attribute>,
+            pub ident: Ident,
+            pub colon_token: Option<Token![:]>,
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+            pub eq_token: Option<Token![=]>,
+            pub default: Option<Type>,
+        }),
+
+        /// A lifetime definition: `'a: 'b + 'c + 'd`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Lifetime(LifetimeDef {
+            pub attrs: Vec<Attribute>,
+            pub lifetime: Lifetime,
+            pub colon_token: Option<Token![:]>,
+            pub bounds: Punctuated<Lifetime, Token![+]>,
+        }),
+
+        /// A const generic parameter: `const LENGTH: usize`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Const(ConstParam {
+            pub attrs: Vec<Attribute>,
+            pub const_token: Token![const],
+            pub ident: Ident,
+            pub colon_token: Token![:],
+            pub ty: Type,
+            pub eq_token: Option<Token![=]>,
+            pub default: Option<Expr>,
+        }),
+    }
+}
+
+impl Generics {
+    /// Returns an
+    /// <code
+    ///   style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
+    ///   href="struct.TypeParam.html"><code
+    ///   style="padding-left:0;padding-right:0;">TypeParam</code></a><code
+    ///   style="padding-left:0;">&gt;</code>
+    /// over the type parameters in `self.params`.
+    pub fn type_params(&self) -> TypeParams {
+        TypeParams(self.params.iter())
+    }
+
+    /// Returns an
+    /// <code
+    ///   style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
+    ///   href="struct.TypeParam.html"><code
+    ///   style="padding-left:0;padding-right:0;">TypeParam</code></a><code
+    ///   style="padding-left:0;">&gt;</code>
+    /// over the type parameters in `self.params`.
+    pub fn type_params_mut(&mut self) -> TypeParamsMut {
+        TypeParamsMut(self.params.iter_mut())
+    }
+
+    /// Returns an
+    /// <code
+    ///   style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
+    ///   href="struct.LifetimeDef.html"><code
+    ///   style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
+    ///   style="padding-left:0;">&gt;</code>
+    /// over the lifetime parameters in `self.params`.
+    pub fn lifetimes(&self) -> Lifetimes {
+        Lifetimes(self.params.iter())
+    }
+
+    /// Returns an
+    /// <code
+    ///   style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
+    ///   href="struct.LifetimeDef.html"><code
+    ///   style="padding-left:0;padding-right:0;">LifetimeDef</code></a><code
+    ///   style="padding-left:0;">&gt;</code>
+    /// over the lifetime parameters in `self.params`.
+    pub fn lifetimes_mut(&mut self) -> LifetimesMut {
+        LifetimesMut(self.params.iter_mut())
+    }
+
+    /// Returns an
+    /// <code
+    ///   style="padding-right:0;">Iterator&lt;Item = &amp;</code><a
+    ///   href="struct.ConstParam.html"><code
+    ///   style="padding-left:0;padding-right:0;">ConstParam</code></a><code
+    ///   style="padding-left:0;">&gt;</code>
+    /// over the constant parameters in `self.params`.
+    pub fn const_params(&self) -> ConstParams {
+        ConstParams(self.params.iter())
+    }
+
+    /// Returns an
+    /// <code
+    ///   style="padding-right:0;">Iterator&lt;Item = &amp;mut </code><a
+    ///   href="struct.ConstParam.html"><code
+    ///   style="padding-left:0;padding-right:0;">ConstParam</code></a><code
+    ///   style="padding-left:0;">&gt;</code>
+    /// over the constant parameters in `self.params`.
+    pub fn const_params_mut(&mut self) -> ConstParamsMut {
+        ConstParamsMut(self.params.iter_mut())
+    }
+
+    /// Initializes an empty `where`-clause if there is not one present already.
+    pub fn make_where_clause(&mut self) -> &mut WhereClause {
+        // This is Option::get_or_insert_with in Rust 1.20.
+        if self.where_clause.is_none() {
+            self.where_clause = Some(WhereClause {
+                where_token: <Token![where]>::default(),
+                predicates: Punctuated::new(),
+            });
+        }
+        match self.where_clause {
+            Some(ref mut where_clause) => where_clause,
+            None => unreachable!(),
+        }
+    }
+}
+
+pub struct TypeParams<'a>(Iter<'a, GenericParam>);
+
+impl<'a> Iterator for TypeParams<'a> {
+    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,
+        };
+        if let GenericParam::Type(ref type_param) = *next {
+            Some(type_param)
+        } else {
+            self.next()
+        }
+    }
+}
+
+pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
+
+impl<'a> Iterator for TypeParamsMut<'a> {
+    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,
+        };
+        if let GenericParam::Type(ref mut type_param) = *next {
+            Some(type_param)
+        } else {
+            self.next()
+        }
+    }
+}
+
+pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
+
+impl<'a> Iterator for Lifetimes<'a> {
+    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,
+        };
+        if let GenericParam::Lifetime(ref lifetime) = *next {
+            Some(lifetime)
+        } else {
+            self.next()
+        }
+    }
+}
+
+pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
+
+impl<'a> Iterator for LifetimesMut<'a> {
+    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,
+        };
+        if let GenericParam::Lifetime(ref mut lifetime) = *next {
+            Some(lifetime)
+        } else {
+            self.next()
+        }
+    }
+}
+
+pub struct ConstParams<'a>(Iter<'a, GenericParam>);
+
+impl<'a> Iterator for ConstParams<'a> {
+    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,
+        };
+        if let GenericParam::Const(ref const_param) = *next {
+            Some(const_param)
+        } else {
+            self.next()
+        }
+    }
+}
+
+pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
+
+impl<'a> Iterator for ConstParamsMut<'a> {
+    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,
+        };
+        if let GenericParam::Const(ref mut const_param) = *next {
+            Some(const_param)
+        } else {
+            self.next()
+        }
+    }
+}
+
+/// Returned by `Generics::split_for_impl`.
+///
+/// *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 ImplGenerics<'a>(&'a Generics);
+
+/// Returned by `Generics::split_for_impl`.
+///
+/// *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 TypeGenerics<'a>(&'a Generics);
+
+/// Returned by `TypeGenerics::as_turbofish`.
+///
+/// *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 Turbofish<'a>(&'a Generics);
+
+#[cfg(feature = "printing")]
+impl Generics {
+    /// Split a type's generics into the pieces required for impl'ing a trait
+    /// for that type.
+    ///
+    /// ```
+    /// # extern crate proc_macro2;
+    /// # extern crate syn;
+    /// # #[macro_use]
+    /// # extern crate quote;
+    /// # use proc_macro2::{Span, Ident};
+    /// # fn main() {
+    /// # 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 {
+    ///         // ...
+    ///     }
+    /// }
+    /// # ;
+    /// # }
+    /// ```
+    ///
+    /// *This method is available if Syn is built with the `"derive"` or
+    /// `"full"` feature and the `"printing"` feature.*
+    pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
+        (
+            ImplGenerics(self),
+            TypeGenerics(self),
+            self.where_clause.as_ref(),
+        )
+    }
+}
+
+#[cfg(feature = "printing")]
+impl<'a> TypeGenerics<'a> {
+    /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
+    ///
+    /// *This method is available if Syn is built with the `"derive"` or
+    /// `"full"` feature and the `"printing"` feature.*
+    pub fn as_turbofish(&self) -> Turbofish {
+        Turbofish(self.0)
+    }
+}
+
+ast_struct! {
+    /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    #[derive(Default)]
+    pub struct BoundLifetimes {
+        pub for_token: Token![for],
+        pub lt_token: Token![<],
+        pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
+        pub gt_token: Token![>],
+    }
+}
+
+impl LifetimeDef {
+    pub fn new(lifetime: Lifetime) -> Self {
+        LifetimeDef {
+            attrs: Vec::new(),
+            lifetime: lifetime,
+            colon_token: None,
+            bounds: Punctuated::new(),
+        }
+    }
+}
+
+impl From<Ident> for TypeParam {
+    fn from(ident: Ident) -> Self {
+        TypeParam {
+            attrs: vec![],
+            ident: ident,
+            colon_token: None,
+            bounds: Punctuated::new(),
+            eq_token: None,
+            default: None,
+        }
+    }
+}
+
+ast_enum_of_structs! {
+    /// A trait or lifetime used as a bound on a type parameter.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum TypeParamBound {
+        pub Trait(TraitBound),
+        pub Lifetime(Lifetime),
+    }
+}
+
+ast_struct! {
+    /// A trait used as a bound on a type parameter.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct TraitBound {
+        pub paren_token: Option<token::Paren>,
+        pub modifier: TraitBoundModifier,
+        /// The `for<'a>` in `for<'a> Foo<&'a T>`
+        pub lifetimes: Option<BoundLifetimes>,
+        /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
+        pub path: Path,
+    }
+}
+
+ast_enum! {
+    /// A modifier on a trait bound, currently only used for the `?` in
+    /// `?Sized`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    #[cfg_attr(feature = "clone-impls", derive(Copy))]
+    pub enum TraitBoundModifier {
+        None,
+        Maybe(Token![?]),
+    }
+}
+
+ast_struct! {
+    /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
+    /// 'static`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct WhereClause {
+        pub where_token: Token![where],
+        pub predicates: Punctuated<WherePredicate, Token![,]>,
+    }
+}
+
+ast_enum_of_structs! {
+    /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum WherePredicate {
+        /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Type(PredicateType {
+            /// Any lifetimes from a `for` binding
+            pub lifetimes: Option<BoundLifetimes>,
+            /// The type being bounded
+            pub bounded_ty: Type,
+            pub colon_token: Token![:],
+            /// Trait and lifetime bounds (`Clone+Send+'static`)
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+        }),
+
+        /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Lifetime(PredicateLifetime {
+            pub lifetime: Lifetime,
+            pub colon_token: Option<Token![:]>,
+            pub bounds: Punctuated<Lifetime, Token![+]>,
+        }),
+
+        /// An equality predicate in a `where` clause (unsupported).
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Eq(PredicateEq {
+            pub lhs_ty: Type,
+            pub eq_token: Token![=],
+            pub rhs_ty: Type,
+        }),
+    }
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+
+    use punctuated::Pair;
+    use synom::Synom;
+
+    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,
+            }
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("generic parameters in declaration")
+        }
+    }
+
+    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.spans)),
+                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;
+                }
+                TraitBound {
+                    paren_token: None,
+                    modifier: modifier,
+                    lifetimes: lifetimes,
+                    path: path,
+                }
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("trait bound")
+        }
+    }
+
+    impl Synom for TraitBoundModifier {
+        named!(parse -> Self, alt!(
+            punct!(?) => { TraitBoundModifier::Maybe }
+            |
+            epsilon!() => { |_| TraitBoundModifier::None }
+        ));
+
+        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 {
+                    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")
+        }
+    }
+
+    impl Synom for WhereClause {
+        named!(parse -> Self, do_parse!(
+            where_: keyword!(where) >>
+            predicates: call!(Punctuated::parse_terminated) >>
+            (WhereClause {
+                predicates: predicates,
+                where_token: where_,
+            })
+        ));
+
+        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,
+                }))
+            )
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("predicate in where clause")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use attr::FilterAttrs;
+    use proc_macro2::TokenStream;
+    use quote::{ToTokens, TokenStreamExt};
+
+    impl ToTokens for Generics {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            if self.params.is_empty() {
+                return;
+            }
+
+            TokensOrDefault(&self.lt_token).to_tokens(tokens);
+
+            // Print lifetimes before types and consts, regardless of their
+            // order in self.params.
+            //
+            // TODO: ordering rules for const parameters vs type parameters have
+            // not been settled yet. https://github.com/rust-lang/rust/issues/44580
+            let mut trailing_or_empty = true;
+            for param in self.params.pairs() {
+                if let GenericParam::Lifetime(_) = **param.value() {
+                    param.to_tokens(tokens);
+                    trailing_or_empty = param.punct().is_some();
+                }
+            }
+            for param in self.params.pairs() {
+                match **param.value() {
+                    GenericParam::Type(_) | GenericParam::Const(_) => {
+                        if !trailing_or_empty {
+                            <Token![,]>::default().to_tokens(tokens);
+                            trailing_or_empty = true;
+                        }
+                        param.to_tokens(tokens);
+                    }
+                    GenericParam::Lifetime(_) => {}
+                }
+            }
+
+            TokensOrDefault(&self.gt_token).to_tokens(tokens);
+        }
+    }
+
+    impl<'a> ToTokens for ImplGenerics<'a> {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            if self.0.params.is_empty() {
+                return;
+            }
+
+            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
+
+            // Print lifetimes before types and consts, regardless of their
+            // order in self.params.
+            //
+            // TODO: ordering rules for const parameters vs type parameters have
+            // not been settled yet. https://github.com/rust-lang/rust/issues/44580
+            let mut trailing_or_empty = true;
+            for param in self.0.params.pairs() {
+                if let GenericParam::Lifetime(_) = **param.value() {
+                    param.to_tokens(tokens);
+                    trailing_or_empty = param.punct().is_some();
+                }
+            }
+            for param in self.0.params.pairs() {
+                if let GenericParam::Lifetime(_) = **param.value() {
+                    continue;
+                }
+                if !trailing_or_empty {
+                    <Token![,]>::default().to_tokens(tokens);
+                    trailing_or_empty = true;
+                }
+                match **param.value() {
+                    GenericParam::Lifetime(_) => unreachable!(),
+                    GenericParam::Type(ref param) => {
+                        // Leave off the type parameter defaults
+                        tokens.append_all(param.attrs.outer());
+                        param.ident.to_tokens(tokens);
+                        if !param.bounds.is_empty() {
+                            TokensOrDefault(&param.colon_token).to_tokens(tokens);
+                            param.bounds.to_tokens(tokens);
+                        }
+                    }
+                    GenericParam::Const(ref param) => {
+                        // Leave off the const parameter defaults
+                        tokens.append_all(param.attrs.outer());
+                        param.const_token.to_tokens(tokens);
+                        param.ident.to_tokens(tokens);
+                        param.colon_token.to_tokens(tokens);
+                        param.ty.to_tokens(tokens);
+                    }
+                }
+                param.punct().to_tokens(tokens);
+            }
+
+            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
+        }
+    }
+
+    impl<'a> ToTokens for TypeGenerics<'a> {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            if self.0.params.is_empty() {
+                return;
+            }
+
+            TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
+
+            // Print lifetimes before types and consts, regardless of their
+            // order in self.params.
+            //
+            // TODO: ordering rules for const parameters vs type parameters have
+            // not been settled yet. https://github.com/rust-lang/rust/issues/44580
+            let mut trailing_or_empty = true;
+            for param in self.0.params.pairs() {
+                if let GenericParam::Lifetime(ref def) = **param.value() {
+                    // Leave off the lifetime bounds and attributes
+                    def.lifetime.to_tokens(tokens);
+                    param.punct().to_tokens(tokens);
+                    trailing_or_empty = param.punct().is_some();
+                }
+            }
+            for param in self.0.params.pairs() {
+                if let GenericParam::Lifetime(_) = **param.value() {
+                    continue;
+                }
+                if !trailing_or_empty {
+                    <Token![,]>::default().to_tokens(tokens);
+                    trailing_or_empty = true;
+                }
+                match **param.value() {
+                    GenericParam::Lifetime(_) => unreachable!(),
+                    GenericParam::Type(ref param) => {
+                        // Leave off the type parameter defaults
+                        param.ident.to_tokens(tokens);
+                    }
+                    GenericParam::Const(ref param) => {
+                        // Leave off the const parameter defaults
+                        param.ident.to_tokens(tokens);
+                    }
+                }
+                param.punct().to_tokens(tokens);
+            }
+
+            TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
+        }
+    }
+
+    impl<'a> ToTokens for Turbofish<'a> {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            if !self.0.params.is_empty() {
+                <Token![::]>::default().to_tokens(tokens);
+                TypeGenerics(self.0).to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for BoundLifetimes {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.for_token.to_tokens(tokens);
+            self.lt_token.to_tokens(tokens);
+            self.lifetimes.to_tokens(tokens);
+            self.gt_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for LifetimeDef {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.lifetime.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                TokensOrDefault(&self.colon_token).to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for TypeParam {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.ident.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                TokensOrDefault(&self.colon_token).to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
+            if self.default.is_some() {
+                TokensOrDefault(&self.eq_token).to_tokens(tokens);
+                self.default.to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for TraitBound {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            let to_tokens = |tokens: &mut TokenStream| {
+                self.modifier.to_tokens(tokens);
+                self.lifetimes.to_tokens(tokens);
+                self.path.to_tokens(tokens);
+            };
+            match self.paren_token {
+                Some(ref paren) => paren.surround(tokens, to_tokens),
+                None => to_tokens(tokens),
+            }
+        }
+    }
+
+    impl ToTokens for TraitBoundModifier {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                TraitBoundModifier::None => {}
+                TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
+            }
+        }
+    }
+
+    impl ToTokens for ConstParam {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.const_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            if self.default.is_some() {
+                TokensOrDefault(&self.eq_token).to_tokens(tokens);
+                self.default.to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for WhereClause {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            if !self.predicates.is_empty() {
+                self.where_token.to_tokens(tokens);
+                self.predicates.to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for PredicateType {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.lifetimes.to_tokens(tokens);
+            self.bounded_ty.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.bounds.to_tokens(tokens);
+        }
+    }
+
+    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);
+            }
+        }
+    }
+
+    impl ToTokens for PredicateEq {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.lhs_ty.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.rhs_ty.to_tokens(tokens);
+        }
+    }
+}
diff --git a/src/item.rs b/src/item.rs
new file mode 100644
index 0000000..cb6184d
--- /dev/null
+++ b/src/item.rs
@@ -0,0 +1,2249 @@
+// 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 super::*;
+use derive::{Data, DeriveInput};
+use proc_macro2::TokenStream;
+use punctuated::Punctuated;
+use token::{Brace, Paren};
+
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+#[cfg(feature = "extra-traits")]
+use tt::TokenStreamHelper;
+
+ast_enum_of_structs! {
+    /// Things that can appear directly inside of a module or scope.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum Item {
+        /// An `extern crate` item: `extern crate serde`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub ExternCrate(ItemExternCrate {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub extern_token: Token![extern],
+            pub crate_token: Token![crate],
+            pub ident: Ident,
+            pub rename: Option<(Token![as], Ident)>,
+            pub semi_token: Token![;],
+        }),
+
+        /// A use declaration: `use std::collections::HashMap`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Use(ItemUse {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub use_token: Token![use],
+            pub leading_colon: Option<Token![::]>,
+            pub tree: UseTree,
+            pub semi_token: Token![;],
+        }),
+
+        /// A static item: `static BIKE: Shed = Shed(42)`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Static(ItemStatic {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub static_token: Token![static],
+            pub mutability: Option<Token![mut]>,
+            pub ident: Ident,
+            pub colon_token: Token![:],
+            pub ty: Box<Type>,
+            pub eq_token: Token![=],
+            pub expr: Box<Expr>,
+            pub semi_token: Token![;],
+        }),
+
+        /// A constant item: `const MAX: u16 = 65535`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Const(ItemConst {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub const_token: Token![const],
+            pub ident: Ident,
+            pub colon_token: Token![:],
+            pub ty: Box<Type>,
+            pub eq_token: Token![=],
+            pub expr: Box<Expr>,
+            pub semi_token: Token![;],
+        }),
+
+        /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
+        /// }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Fn(ItemFn {
+            pub attrs: Vec<Attribute>,
+            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>,
+            pub block: Box<Block>,
+        }),
+
+        /// A module or module declaration: `mod m` or `mod m { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Mod(ItemMod {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub mod_token: Token![mod],
+            pub ident: Ident,
+            pub content: Option<(token::Brace, Vec<Item>)>,
+            pub semi: Option<Token![;]>,
+        }),
+
+        /// A block of foreign items: `extern "C" { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub ForeignMod(ItemForeignMod {
+            pub attrs: Vec<Attribute>,
+            pub abi: Abi,
+            pub brace_token: token::Brace,
+            pub items: Vec<ForeignItem>,
+        }),
+
+        /// A type alias: `type Result<T> = std::result::Result<T, MyError>`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Type(ItemType {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub type_token: Token![type],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub eq_token: Token![=],
+            pub ty: Box<Type>,
+            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.*
+        pub Struct(ItemStruct {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub struct_token: Token![struct],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub fields: Fields,
+            pub semi_token: Option<Token![;]>,
+        }),
+
+        /// An enum definition: `enum Foo<A, B> { C<A>, D<B> }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Enum(ItemEnum {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub enum_token: Token![enum],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub brace_token: token::Brace,
+            pub variants: Punctuated<Variant, Token![,]>,
+        }),
+
+        /// A union definition: `union Foo<A, B> { x: A, y: B }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Union(ItemUnion {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub union_token: Token![union],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub fields: FieldsNamed,
+        }),
+
+        /// A trait definition: `pub trait Iterator { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Trait(ItemTrait {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub unsafety: Option<Token![unsafe]>,
+            pub auto_token: Option<Token![auto]>,
+            pub trait_token: Token![trait],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub colon_token: Option<Token![:]>,
+            pub supertraits: Punctuated<TypeParamBound, Token![+]>,
+            pub brace_token: token::Brace,
+            pub items: Vec<TraitItem>,
+        }),
+
+        /// An impl block providing trait or associated items: `impl<A> Trait
+        /// for Data<A> { ... }`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Impl(ItemImpl {
+            pub attrs: Vec<Attribute>,
+            pub defaultness: Option<Token![default]>,
+            pub unsafety: Option<Token![unsafe]>,
+            pub impl_token: Token![impl],
+            pub generics: Generics,
+            /// Trait this impl implements.
+            pub trait_: Option<(Option<Token![!]>, Path, Token![for])>,
+            /// The Self type of the impl.
+            pub self_ty: Box<Type>,
+            pub brace_token: token::Brace,
+            pub items: Vec<ImplItem>,
+        }),
+
+        /// A macro invocation, which includes `macro_rules!` definitions.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Macro(ItemMacro {
+            pub attrs: Vec<Attribute>,
+            /// The `example` in `macro_rules! example { ... }`.
+            pub ident: Option<Ident>,
+            pub mac: Macro,
+            pub semi_token: Option<Token![;]>,
+        }),
+
+        /// A 2.0-style declarative macro introduced by the `macro` keyword.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Macro2(ItemMacro2 #manual_extra_traits {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub macro_token: Token![macro],
+            pub ident: Ident,
+            pub paren_token: Paren,
+            pub args: TokenStream,
+            pub brace_token: Brace,
+            pub body: TokenStream,
+        }),
+
+        /// Tokens forming an item not interpreted by Syn.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Verbatim(ItemVerbatim #manual_extra_traits {
+            pub tts: TokenStream,
+        }),
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for ItemMacro2 {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for ItemMacro2 {
+    fn eq(&self, other: &Self) -> bool {
+        self.attrs == other.attrs
+            && self.vis == other.vis
+            && self.macro_token == other.macro_token
+            && self.ident == other.ident
+            && self.paren_token == other.paren_token
+            && TokenStreamHelper(&self.args) == TokenStreamHelper(&other.args)
+            && self.brace_token == other.brace_token
+            && TokenStreamHelper(&self.body) == TokenStreamHelper(&other.body)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for ItemMacro2 {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        self.attrs.hash(state);
+        self.vis.hash(state);
+        self.macro_token.hash(state);
+        self.ident.hash(state);
+        self.paren_token.hash(state);
+        TokenStreamHelper(&self.args).hash(state);
+        self.brace_token.hash(state);
+        TokenStreamHelper(&self.body).hash(state);
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for ItemVerbatim {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for ItemVerbatim {
+    fn eq(&self, other: &Self) -> bool {
+        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for ItemVerbatim {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+impl From<DeriveInput> for Item {
+    fn from(input: DeriveInput) -> Item {
+        match input.data {
+            Data::Struct(data) => Item::Struct(ItemStruct {
+                attrs: input.attrs,
+                vis: input.vis,
+                struct_token: data.struct_token,
+                ident: input.ident,
+                generics: input.generics,
+                fields: data.fields,
+                semi_token: data.semi_token,
+            }),
+            Data::Enum(data) => Item::Enum(ItemEnum {
+                attrs: input.attrs,
+                vis: input.vis,
+                enum_token: data.enum_token,
+                ident: input.ident,
+                generics: input.generics,
+                brace_token: data.brace_token,
+                variants: data.variants,
+            }),
+            Data::Union(data) => Item::Union(ItemUnion {
+                attrs: input.attrs,
+                vis: input.vis,
+                union_token: data.union_token,
+                ident: input.ident,
+                generics: input.generics,
+                fields: data.fields,
+            }),
+        }
+    }
+}
+
+ast_enum_of_structs! {
+    /// A suffix of an import tree in a `use` item: `Type as Renamed` or `*`.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum UseTree {
+        /// A path prefix of imports in a `use` item: `std::...`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Path(UsePath {
+            pub ident: Ident,
+            pub colon2_token: Token![::],
+            pub tree: Box<UseTree>,
+        }),
+
+        /// An identifier imported by a `use` item: `HashMap`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Name(UseName {
+            pub ident: Ident,
+        }),
+
+        /// An renamed identifier imported by a `use` item: `HashMap as Map`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Rename(UseRename {
+            pub ident: Ident,
+            pub as_token: Token![as],
+            pub rename: Ident,
+        }),
+
+        /// A glob import in a `use` item: `*`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Glob(UseGlob {
+            pub star_token: Token![*],
+        }),
+
+        /// A braced group of imports in a `use` item: `{A, B, C}`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Group(UseGroup {
+            pub brace_token: token::Brace,
+            pub items: Punctuated<UseTree, Token![,]>,
+        }),
+    }
+}
+
+ast_enum_of_structs! {
+    /// An item within an `extern` block.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum ForeignItem {
+        /// A foreign function in an `extern` block.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Fn(ForeignItemFn {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub ident: Ident,
+            pub decl: Box<FnDecl>,
+            pub semi_token: Token![;],
+        }),
+
+        /// A foreign static item in an `extern` block: `static ext: u8`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Static(ForeignItemStatic {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub static_token: Token![static],
+            pub mutability: Option<Token![mut]>,
+            pub ident: Ident,
+            pub colon_token: Token![:],
+            pub ty: Box<Type>,
+            pub semi_token: Token![;],
+        }),
+
+        /// A foreign type in an `extern` block: `type void`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Type(ForeignItemType {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub type_token: Token![type],
+            pub ident: Ident,
+            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.*
+        pub Verbatim(ForeignItemVerbatim #manual_extra_traits {
+            pub tts: TokenStream,
+        }),
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for ForeignItemVerbatim {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for ForeignItemVerbatim {
+    fn eq(&self, other: &Self) -> bool {
+        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for ForeignItemVerbatim {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+ast_enum_of_structs! {
+    /// An item declaration within the definition of a trait.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum TraitItem {
+        /// An associated constant within the definition of a trait.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Const(TraitItemConst {
+            pub attrs: Vec<Attribute>,
+            pub const_token: Token![const],
+            pub ident: Ident,
+            pub colon_token: Token![:],
+            pub ty: Type,
+            pub default: Option<(Token![=], Expr)>,
+            pub semi_token: Token![;],
+        }),
+
+        /// A trait method within the definition of a trait.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Method(TraitItemMethod {
+            pub attrs: Vec<Attribute>,
+            pub sig: MethodSig,
+            pub default: Option<Block>,
+            pub semi_token: Option<Token![;]>,
+        }),
+
+        /// An associated type within the definition of a trait.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Type(TraitItemType {
+            pub attrs: Vec<Attribute>,
+            pub type_token: Token![type],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub colon_token: Option<Token![:]>,
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+            pub default: Option<(Token![=], Type)>,
+            pub semi_token: Token![;],
+        }),
+
+        /// An existential type within the definition of a trait.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Existential(TraitItemExistential {
+            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 the definition of a trait.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Macro(TraitItemMacro {
+            pub attrs: Vec<Attribute>,
+            pub mac: Macro,
+            pub semi_token: Option<Token![;]>,
+        }),
+
+        /// Tokens within the definition of a trait not interpreted by Syn.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Verbatim(TraitItemVerbatim #manual_extra_traits {
+            pub tts: TokenStream,
+        }),
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for TraitItemVerbatim {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for TraitItemVerbatim {
+    fn eq(&self, other: &Self) -> bool {
+        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for TraitItemVerbatim {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+ast_enum_of_structs! {
+    /// An item within an impl block.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum ImplItem {
+        /// An associated constant within an impl block.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Const(ImplItemConst {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub defaultness: Option<Token![default]>,
+            pub const_token: Token![const],
+            pub ident: Ident,
+            pub colon_token: Token![:],
+            pub ty: Type,
+            pub eq_token: Token![=],
+            pub expr: Expr,
+            pub semi_token: Token![;],
+        }),
+
+        /// A method within an impl block.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Method(ImplItemMethod {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub defaultness: Option<Token![default]>,
+            pub sig: MethodSig,
+            pub block: Block,
+        }),
+
+        /// An associated type within an impl block.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Type(ImplItemType {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub defaultness: Option<Token![default]>,
+            pub type_token: Token![type],
+            pub ident: Ident,
+            pub generics: Generics,
+            pub eq_token: Token![=],
+            pub ty: Type,
+            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.*
+        pub Macro(ImplItemMacro {
+            pub attrs: Vec<Attribute>,
+            pub mac: Macro,
+            pub semi_token: Option<Token![;]>,
+        }),
+
+        /// Tokens within an impl block not interpreted by Syn.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Verbatim(ImplItemVerbatim #manual_extra_traits {
+            pub tts: TokenStream,
+        }),
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for ImplItemVerbatim {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for ImplItemVerbatim {
+    fn eq(&self, other: &Self) -> bool {
+        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for ImplItemVerbatim {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+ast_struct! {
+    /// A method's signature in a trait or implementation: `unsafe fn
+    /// initialize(&self)`.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    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,
+    }
+}
+
+ast_struct! {
+    /// Header of a function declaration, without including the body.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    pub struct FnDecl {
+        pub fn_token: Token![fn],
+        pub generics: Generics,
+        pub paren_token: token::Paren,
+        pub inputs: Punctuated<FnArg, Token![,]>,
+        pub variadic: Option<Token![...]>,
+        pub output: ReturnType,
+    }
+}
+
+ast_enum_of_structs! {
+    /// An argument in a function signature: the `n: usize` in `fn f(n: usize)`.
+    ///
+    /// *This type is available if Syn is built with the `"full"` feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum FnArg {
+        /// Self captured by reference in a function signature: `&self` or `&mut
+        /// self`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub SelfRef(ArgSelfRef {
+            pub and_token: Token![&],
+            pub lifetime: Option<Lifetime>,
+            pub mutability: Option<Token![mut]>,
+            pub self_token: Token![self],
+        }),
+
+        /// Self captured by value in a function signature: `self` or `mut
+        /// self`.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub SelfValue(ArgSelf {
+            pub mutability: Option<Token![mut]>,
+            pub self_token: Token![self],
+        }),
+
+        /// An explicitly typed pattern captured by a function signature.
+        ///
+        /// *This type is available if Syn is built with the `"full"` feature.*
+        pub Captured(ArgCaptured {
+            pub pat: Pat,
+            pub colon_token: Token![:],
+            pub ty: Type,
+        }),
+
+        /// A pattern whose type is inferred captured by a function signature.
+        pub Inferred(Pat),
+        /// A type not bound to any pattern in a function signature.
+        pub Ignored(Type),
+    }
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+
+    use synom::Synom;
+
+    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 }
+        |
+        syn!(ItemMod) => { Item::Mod }
+        |
+        syn!(ItemForeignMod) => { Item::ForeignMod }
+        |
+        syn!(ItemType) => { Item::Type }
+        |
+        syn!(ItemExistential) => { Item::Existential }
+        |
+        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_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)) >>
+        asyncness: option!(keyword!(async)) >>
+        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,
+            asyncness: asyncness,
+            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,
+            }),
+        })
+    ));
+
+    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")
+        }
+    }
+
+    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 }
+        |
+        syn!(ForeignItemMacro) => { ForeignItem::Macro }
+    ));
+
+    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,
+                attrs: attrs,
+                semi_token: semi,
+                decl: Box::new(FnDecl {
+                    fn_token: fn_,
+                    paren_token: parens,
+                    inputs: inputs,
+                    variadic: variadic,
+                    output: ret,
+                    generics: Generics {
+                        where_clause: where_clause,
+                        ..generics
+                    },
+                }),
+                vis: vis,
+            }
+        })
+    ));
+
+    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,
+        })
+    ));
+
+    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,
+        })
+    ));
+
+    impl_synom!(ForeignItemMacro "macro in extern block" do_parse!(
+        attrs: many0!(Attribute::parse_outer) >>
+        mac: syn!(Macro) >>
+        semi: cond!(!is_brace(&mac.delimiter), punct!(;)) >>
+        (ForeignItemMacro {
+            attrs: attrs,
+            mac: mac,
+            semi_token: semi,
+        })
+    ));
+
+    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(vis: bool) -> ItemExistential, do_parse!(
+        attrs: many0!(Attribute::parse_outer) >>
+        vis: cond_reduce!(vis, syn!(Visibility)) >>
+        existential_token: keyword!(existential) >>
+        type_token: keyword!(type) >>
+        ident: syn!(Ident) >>
+        generics: syn!(Generics) >>
+        where_clause: option!(syn!(WhereClause)) >>
+        colon: option!(punct!(:)) >>
+        bounds: cond!(
+            colon.is_some(),
+            Punctuated::<TypeParamBound, Token![+]>::parse_separated_nonempty
+        ) >>
+        semi: punct!(;) >>
+        (ItemExistential {
+            attrs: attrs,
+            vis: vis,
+            existential_token: existential_token,
+            type_token: type_token,
+            ident: ident,
+            generics: Generics {
+                where_clause: where_clause,
+                ..generics
+            },
+            colon_token: colon,
+            bounds: bounds.unwrap_or_else(Punctuated::new),
+            semi_token: semi,
+        })
+    ));
+
+    impl_synom!(ItemExistential "existential type" call!(existential_type, true));
+
+    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 }
+        |
+        syn!(TraitItemExistential) => { TraitItem::Existential }
+        |
+        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),
+            };
+            TraitItemMethod {
+                attrs: {
+                    let mut attrs = outer_attrs;
+                    attrs.extend(inner_attrs);
+                    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,
+                        variadic: None,
+                        generics: Generics {
+                            where_clause: where_clause,
+                            ..generics
+                        },
+                    },
+                },
+                default: stmts.map(|stmts| {
+                    Block {
+                        stmts: stmts.0,
+                        brace_token: stmts.1,
+                    }
+                }),
+                semi_token: semi,
+            }
+        })
+    ));
+
+    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,
+        })
+    ));
+
+    impl_synom!(TraitItemExistential "trait item existential type" map!(
+        call!(existential_type, false),
+        |ety| TraitItemExistential {
+            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_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 }
+        |
+        syn!(ImplItemType) => { ImplItem::Type }
+        |
+        syn!(ImplItemExistential) => { ImplItem::Existential }
+        |
+        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)) >>
+        asyncness: option!(keyword!(async)) >>
+        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,
+                asyncness: asyncness,
+                abi: abi,
+                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,
+                },
+            },
+            block: Block {
+                brace_token: inner_attrs_stmts.0,
+                stmts: (inner_attrs_stmts.1).1,
+            },
+        })
+    ));
+
+    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,
+        })
+    ));
+
+    impl_synom!(ImplItemExistential "existential type in impl block" map!(
+        call!(existential_type, true),
+        |ety| 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_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,
+        })
+    ));
+
+    fn is_brace(delimiter: &MacroDelimiter) -> bool {
+        match *delimiter {
+            MacroDelimiter::Brace(_) => true,
+            MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false,
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use attr::FilterAttrs;
+    use proc_macro2::TokenStream;
+    use quote::{ToTokens, TokenStreamExt};
+
+    impl ToTokens for ItemExternCrate {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.extern_token.to_tokens(tokens);
+            self.crate_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            if let Some((ref as_token, ref rename)) = self.rename {
+                as_token.to_tokens(tokens);
+                rename.to_tokens(tokens);
+            }
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ItemUse {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.use_token.to_tokens(tokens);
+            self.leading_colon.to_tokens(tokens);
+            self.tree.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ItemStatic {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.static_token.to_tokens(tokens);
+            self.mutability.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ItemConst {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.const_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ItemFn {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            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| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.block.stmts);
+            });
+        }
+    }
+
+    impl ToTokens for ItemMod {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.mod_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            if let Some((ref brace, ref items)) = self.content {
+                brace.surround(tokens, |tokens| {
+                    tokens.append_all(self.attrs.inner());
+                    tokens.append_all(items);
+                });
+            } else {
+                TokensOrDefault(&self.semi).to_tokens(tokens);
+            }
+        }
+    }
+
+    impl ToTokens for ItemForeignMod {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.abi.to_tokens(tokens);
+            self.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.items);
+            });
+        }
+    }
+
+    impl ToTokens for ItemType {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.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);
+            self.eq_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    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());
+            self.vis.to_tokens(tokens);
+            self.enum_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            self.generics.where_clause.to_tokens(tokens);
+            self.brace_token.surround(tokens, |tokens| {
+                self.variants.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for ItemStruct {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.struct_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            match self.fields {
+                Fields::Named(ref fields) => {
+                    self.generics.where_clause.to_tokens(tokens);
+                    fields.to_tokens(tokens);
+                }
+                Fields::Unnamed(ref fields) => {
+                    fields.to_tokens(tokens);
+                    self.generics.where_clause.to_tokens(tokens);
+                    TokensOrDefault(&self.semi_token).to_tokens(tokens);
+                }
+                Fields::Unit => {
+                    self.generics.where_clause.to_tokens(tokens);
+                    TokensOrDefault(&self.semi_token).to_tokens(tokens);
+                }
+            }
+        }
+    }
+
+    impl ToTokens for ItemUnion {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.union_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            self.generics.where_clause.to_tokens(tokens);
+            self.fields.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ItemTrait {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.unsafety.to_tokens(tokens);
+            self.auto_token.to_tokens(tokens);
+            self.trait_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            if !self.supertraits.is_empty() {
+                TokensOrDefault(&self.colon_token).to_tokens(tokens);
+                self.supertraits.to_tokens(tokens);
+            }
+            self.generics.where_clause.to_tokens(tokens);
+            self.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(&self.items);
+            });
+        }
+    }
+
+    impl ToTokens for ItemImpl {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.defaultness.to_tokens(tokens);
+            self.unsafety.to_tokens(tokens);
+            self.impl_token.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            if let Some((ref polarity, ref path, ref for_token)) = self.trait_ {
+                polarity.to_tokens(tokens);
+                path.to_tokens(tokens);
+                for_token.to_tokens(tokens);
+            }
+            self.self_ty.to_tokens(tokens);
+            self.generics.where_clause.to_tokens(tokens);
+            self.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.items);
+            });
+        }
+    }
+
+    impl ToTokens for ItemMacro {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.mac.path.to_tokens(tokens);
+            self.mac.bang_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            match self.mac.delimiter {
+                MacroDelimiter::Paren(ref paren) => {
+                    paren.surround(tokens, |tokens| self.mac.tts.to_tokens(tokens));
+                }
+                MacroDelimiter::Brace(ref brace) => {
+                    brace.surround(tokens, |tokens| self.mac.tts.to_tokens(tokens));
+                }
+                MacroDelimiter::Bracket(ref bracket) => {
+                    bracket.surround(tokens, |tokens| self.mac.tts.to_tokens(tokens));
+                }
+            }
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ItemMacro2 {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.macro_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                self.args.to_tokens(tokens);
+            });
+            self.brace_token.surround(tokens, |tokens| {
+                self.body.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for ItemVerbatim {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.tts.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for UsePath {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+            self.colon2_token.to_tokens(tokens);
+            self.tree.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for UseName {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for UseRename {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+            self.as_token.to_tokens(tokens);
+            self.rename.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for UseGlob {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.star_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for UseGroup {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.brace_token.surround(tokens, |tokens| {
+                self.items.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for TraitItemConst {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.const_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            if let Some((ref eq_token, ref default)) = self.default {
+                eq_token.to_tokens(tokens);
+                default.to_tokens(tokens);
+            }
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TraitItemMethod {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.sig.to_tokens(tokens);
+            match self.default {
+                Some(ref block) => {
+                    block.brace_token.surround(tokens, |tokens| {
+                        tokens.append_all(self.attrs.inner());
+                        tokens.append_all(&block.stmts);
+                    });
+                }
+                None => {
+                    TokensOrDefault(&self.semi_token).to_tokens(tokens);
+                }
+            }
+        }
+    }
+
+    impl ToTokens for TraitItemType {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.type_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.generics.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                TokensOrDefault(&self.colon_token).to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
+            self.generics.where_clause.to_tokens(tokens);
+            if let Some((ref eq_token, ref default)) = self.default {
+                eq_token.to_tokens(tokens);
+                default.to_tokens(tokens);
+            }
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TraitItemExistential {
+        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 TraitItemMacro {
+        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 TraitItemVerbatim {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.tts.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ImplItemConst {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.defaultness.to_tokens(tokens);
+            self.const_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.expr.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ImplItemMethod {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.defaultness.to_tokens(tokens);
+            self.sig.to_tokens(tokens);
+            self.block.brace_token.surround(tokens, |tokens| {
+                tokens.append_all(self.attrs.inner());
+                tokens.append_all(&self.block.stmts);
+            });
+        }
+    }
+
+    impl ToTokens for ImplItemType {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.defaultness.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);
+            self.eq_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    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());
+            self.mac.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ImplItemVerbatim {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.tts.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ForeignItemFn {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            NamedDecl(&self.decl, &self.ident).to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ForeignItemStatic {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.static_token.to_tokens(tokens);
+            self.mutability.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ForeignItemType {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.type_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    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);
+        }
+    }
+
+    impl ToTokens for MethodSig {
+        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);
+        }
+    }
+
+    struct NamedDecl<'a>(&'a FnDecl, &'a Ident);
+
+    impl<'a> ToTokens for NamedDecl<'a> {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.0.fn_token.to_tokens(tokens);
+            self.1.to_tokens(tokens);
+            self.0.generics.to_tokens(tokens);
+            self.0.paren_token.surround(tokens, |tokens| {
+                self.0.inputs.to_tokens(tokens);
+                if self.0.variadic.is_some() && !self.0.inputs.empty_or_trailing() {
+                    <Token![,]>::default().to_tokens(tokens);
+                }
+                self.0.variadic.to_tokens(tokens);
+            });
+            self.0.output.to_tokens(tokens);
+            self.0.generics.where_clause.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ArgSelfRef {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.and_token.to_tokens(tokens);
+            self.lifetime.to_tokens(tokens);
+            self.mutability.to_tokens(tokens);
+            self.self_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ArgSelf {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.mutability.to_tokens(tokens);
+            self.self_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ArgCaptured {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.pat.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 028ae2e..f917e30 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,9 +1,791 @@
-#![doc(html_root_url = "https://docs.rs/syn-error-experiment/0.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.
 
-extern crate proc_macro2;
-extern crate syn;
+//! Syn is a parsing library for parsing a stream of Rust tokens into a syntax
+//! tree of Rust source code.
+//!
+//! Currently this library is geared toward the [custom derive] use case but
+//! contains some APIs that may be useful for Rust procedural macros more
+//! generally.
+//!
+//! [custom derive]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
+//!
+//! - **Data structures** — Syn provides a complete syntax tree that can
+//!   represent any valid Rust source code. The syntax tree is rooted at
+//!   [`syn::File`] which represents a full source file, but there are other
+//!   entry points that may be useful to procedural macros including
+//!   [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
+//!
+//! - **Custom derives** — Of particular interest to custom derives is
+//!   [`syn::DeriveInput`] which is any of the three legal input items to a
+//!   derive macro. An example below shows using this type in a library that can
+//!   derive implementations of a trait of your own.
+//!
+//! - **Parser combinators** — Parsing in Syn is built on a suite of public
+//!   parser combinator macros that you can use for parsing any token-based
+//!   syntax you dream up within a `functionlike!(...)` procedural macro. Every
+//!   syntax tree node defined by Syn is individually parsable and may be used
+//!   as a building block for custom syntaxes, or you may do it all yourself
+//!   working from the most primitive tokens.
+//!
+//! - **Location information** — Every token parsed by Syn is associated with a
+//!   `Span` that tracks line and column information back to the source of that
+//!   token. These spans allow a procedural macro to display detailed error
+//!   messages pointing to all the right places in the user's code. There is an
+//!   example of this below.
+//!
+//! - **Feature flags** — Functionality is aggressively feature gated so your
+//!   procedural macros enable only what they need, and do not pay in compile
+//!   time for all the rest.
+//!
+//! [`syn::File`]: struct.File.html
+//! [`syn::Item`]: enum.Item.html
+//! [`syn::Expr`]: enum.Expr.html
+//! [`syn::Type`]: enum.Type.html
+//! [`syn::DeriveInput`]: struct.DeriveInput.html
+//!
+//! *Version requirement: Syn supports any compiler version back to Rust's very
+//! first support for procedural macros in Rust 1.15.0. Some features especially
+//! around error reporting are only available in newer compilers or on the
+//! nightly channel.*
+//!
+//! ## Example of a custom derive
+//!
+//! The canonical custom derive using Syn looks like this. We write an ordinary
+//! Rust function tagged with a `proc_macro_derive` attribute and the name of
+//! the trait we are deriving. Any time that derive appears in the user's code,
+//! the Rust compiler passes their data structure as tokens into our macro. We
+//! get to execute arbitrary Rust code to figure out what to do with those
+//! tokens, then hand some tokens back to the compiler to compile into the
+//! user's crate.
+//!
+//! [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html
+//!
+//! ```toml
+//! [dependencies]
+//! syn = "0.14"
+//! quote = "0.6"
+//!
+//! [lib]
+//! proc-macro = true
+//! ```
+//!
+//! ```rust
+//! extern crate proc_macro;
+//! extern crate syn;
+//!
+//! #[macro_use]
+//! extern crate quote;
+//!
+//! use proc_macro::TokenStream;
+//! use syn::DeriveInput;
+//!
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[proc_macro_derive(MyMacro)]
+//! # };
+//! pub fn my_macro(input: TokenStream) -> TokenStream {
+//!     // Parse the input tokens into a syntax tree
+//!     let input: DeriveInput = syn::parse(input).unwrap();
+//!
+//!     // Build the output, possibly using quasi-quotation
+//!     let expanded = quote! {
+//!         // ...
+//!     };
+//!
+//!     // Hand the output tokens back to the compiler
+//!     expanded.into()
+//! }
+//! #
+//! # fn main() {}
+//! ```
+//!
+//! The [`heapsize`] example directory shows a complete working Macros 1.1
+//! implementation of a custom derive. It works on any Rust compiler \>=1.15.0.
+//! The example derives a `HeapSize` trait which computes an estimate of the
+//! amount of heap memory owned by a value.
+//!
+//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
+//!
+//! ```rust
+//! pub trait HeapSize {
+//!     /// Total number of bytes of heap memory owned by `self`.
+//!     fn heap_size_of_children(&self) -> usize;
+//! }
+//! ```
+//!
+//! The custom derive allows users to write `#[derive(HeapSize)]` on data
+//! structures in their program.
+//!
+//! ```rust
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[derive(HeapSize)]
+//! # };
+//! struct Demo<'a, T: ?Sized> {
+//!     a: Box<T>,
+//!     b: u8,
+//!     c: &'a str,
+//!     d: String,
+//! }
+//! ```
+//!
+//! ## Spans and error reporting
+//!
+//! The [`heapsize2`] example directory is an extension of the `heapsize`
+//! example that demonstrates some of the hygiene and error reporting properties
+//! of Macros 2.0. This example currently requires a nightly Rust compiler
+//! \>=1.24.0-nightly but we are working to stabilize all of the APIs involved.
+//!
+//! [`heapsize2`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize2
+//!
+//! The token-based procedural macro API provides great control over where the
+//! compiler's error messages are displayed in user code. Consider the error the
+//! user sees if one of their field types does not implement `HeapSize`.
+//!
+//! ```rust
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[derive(HeapSize)]
+//! # };
+//! struct Broken {
+//!     ok: String,
+//!     bad: std::thread::Thread,
+//! }
+//! ```
+//!
+//! In the Macros 1.1 string-based procedural macro world, the resulting error
+//! would point unhelpfully to the invocation of the derive macro and not to the
+//! actual problematic field.
+//!
+//! ```text
+//! error[E0599]: no method named `heap_size_of_children` found for type `std::thread::Thread` in the current scope
+//!  --> src/main.rs:4:10
+//!   |
+//! 4 | #[derive(HeapSize)]
+//!   |          ^^^^^^^^
+//! ```
+//!
+//! By tracking span information all the way through the expansion of a
+//! procedural macro as shown in the `heapsize2` example, token-based macros in
+//! Syn are able to trigger errors that directly pinpoint the source of the
+//! problem.
+//!
+//! ```text
+//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
+//!  --> src/main.rs:7:5
+//!   |
+//! 7 |     bad: std::thread::Thread,
+//!   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
+//! ```
+//!
+//! ## Parsing a custom syntax using combinators
+//!
+//! The [`lazy-static`] example directory shows the implementation of a
+//! `functionlike!(...)` procedural macro in which the input tokens are parsed
+//! using [`nom`]-style parser combinators.
+//!
+//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
+//! [`nom`]: https://github.com/Geal/nom
+//!
+//! The example reimplements the popular `lazy_static` crate from crates.io as a
+//! procedural macro.
+//!
+//! ```
+//! # macro_rules! lazy_static {
+//! #     ($($tt:tt)*) => {}
+//! # }
+//! #
+//! lazy_static! {
+//!     static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
+//! }
+//! ```
+//!
+//! The implementation shows how to trigger custom warnings and error messages
+//! on the macro input.
+//!
+//! ```text
+//! warning: come on, pick a more creative name
+//!   --> src/main.rs:10:16
+//!    |
+//! 10 |     static ref FOO: String = "lazy_static".to_owned();
+//!    |                ^^^
+//! ```
+//!
+//! ## Debugging
+//!
+//! When developing a procedural macro it can be helpful to look at what the
+//! generated code looks like. Use `cargo rustc -- -Zunstable-options
+//! --pretty=expanded` or the [`cargo expand`] subcommand.
+//!
+//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
+//!
+//! To show the expanded code for some crate that uses your procedural macro,
+//! run `cargo expand` from that crate. To show the expanded code for one of
+//! your own test cases, run `cargo expand --test the_test_case` where the last
+//! argument is the name of the test file without the `.rs` extension.
+//!
+//! This write-up by Brandon W Maister discusses debugging in more detail:
+//! [Debugging Rust's new Custom Derive system][debugging].
+//!
+//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
+//!
+//! ## Optional features
+//!
+//! Syn puts a lot of functionality behind optional features in order to
+//! optimize compile time for the most common use cases. The following features
+//! are available.
+//!
+//! - **`derive`** *(enabled by default)* — Data structures for representing the
+//!   possible input to a custom derive, including structs and enums and types.
+//! - **`full`** — Data structures for representing the syntax tree of all valid
+//!   Rust source code, including items and expressions.
+//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
+//!   a syntax tree node of a chosen type.
+//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
+//!   node as tokens of Rust source code.
+//! - **`visit`** — Trait for traversing a syntax tree.
+//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
+//!   tree.
+//! - **`fold`** — Trait for transforming an owned syntax tree.
+//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
+//!   types.
+//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
+//!   types.
+//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
+//!   dynamic library libproc_macro from rustc toolchain.
 
-#[cfg(feature = "proc-macro")]
+// Syn types in rustdoc of other crates get linked to here.
+#![doc(html_root_url = "https://docs.rs/syn/0.14.9")]
+#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
+// Ignored clippy lints.
+#![cfg_attr(
+    feature = "cargo-clippy",
+    allow(
+        const_static_lifetime,
+        doc_markdown,
+        large_enum_variant,
+        match_bool,
+        redundant_closure,
+        needless_pass_by_value,
+        redundant_field_names,
+        trivially_copy_pass_by_ref
+    )
+)]
+// Ignored clippy_pedantic lints.
+#![cfg_attr(
+    feature = "cargo-clippy",
+    allow(
+        cast_possible_truncation,
+        cast_possible_wrap,
+        if_not_else,
+        indexing_slicing,
+        items_after_statements,
+        shadow_unrelated,
+        similar_names,
+        single_match_else,
+        stutter,
+        unseparated_literal_suffix,
+        use_self,
+        used_underscore_binding
+    )
+)]
+
+#[cfg(all(
+    not(all(target_arch = "wasm32", target_os = "unknown")),
+    feature = "proc-macro"
+))]
 extern crate proc_macro;
+extern crate proc_macro2;
+extern crate unicode_xid;
+
+#[cfg(feature = "printing")]
+extern crate quote;
+
+#[cfg(feature = "parsing")]
+#[macro_use]
+#[doc(hidden)]
+pub mod parsers;
+
+#[macro_use]
+mod macros;
+
+#[macro_use]
+pub mod token;
+
+pub use proc_macro2::Ident;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod attr;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue, NestedMeta};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod data;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use data::{
+    Field, Fields, FieldsNamed, FieldsUnnamed, Variant, VisCrate, VisPublic, VisRestricted,
+    Visibility,
+};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod expr;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use expr::{
+    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")]
+pub use expr::{
+    Arm, Block, FieldPat, FieldValue, GenericMethodArgument, Label, Local, MethodTurbofish, Pat,
+    PatBox, PatIdent, PatLit, PatMacro, PatPath, PatRange, PatRef, PatSlice, PatStruct, PatTuple,
+    PatTupleStruct, PatVerbatim, PatWild, RangeLimits, Stmt,
+};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod generics;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use generics::{
+    BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeDef, PredicateEq,
+    PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
+    WhereClause, WherePredicate,
+};
+#[cfg(all(
+    any(feature = "full", feature = "derive"),
+    feature = "printing"
+))]
+pub use generics::{ImplGenerics, Turbofish, TypeGenerics};
+
+#[cfg(feature = "full")]
+mod item;
+#[cfg(feature = "full")]
+pub use item::{
+    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, ItemType, ItemUnion,
+    ItemUse, ItemVerbatim, MethodSig, TraitItem, TraitItemConst, TraitItemExistential,
+    TraitItemMacro, TraitItemMethod, TraitItemType, TraitItemVerbatim, UseGlob, UseGroup, UseName,
+    UsePath, UseRename, UseTree,
+};
+
+#[cfg(feature = "full")]
+mod file;
+#[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"))]
+mod lit;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use lit::{
+    FloatSuffix, IntSuffix, Lit, LitBool, LitByte, LitByteStr, LitChar, LitFloat, LitInt, LitStr,
+    LitVerbatim, StrStyle,
+};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod mac;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use mac::{Macro, MacroDelimiter};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod derive;
+#[cfg(feature = "derive")]
+pub use derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod op;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use op::{BinOp, UnOp};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod ty;
+#[cfg(any(feature = "full", feature = "derive"))]
+pub use ty::{
+    Abi, BareFnArg, BareFnArgName, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
+    TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
+    TypeSlice, TypeTraitObject, TypeTuple, TypeVerbatim,
+};
+
+#[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,
+    PathArguments, PathSegment, QSelf,
+};
+
+#[cfg(feature = "parsing")]
+pub mod buffer;
+pub mod punctuated;
+#[cfg(feature = "parsing")]
+pub mod synom;
+#[cfg(any(feature = "full", feature = "derive"))]
+mod tt;
+
+// Not public API except the `parse_quote!` macro.
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+pub mod parse_quote;
+
+#[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.
+    ///
+    /// Each method of the [`Visit`] trait is a hook that can be overridden to
+    /// customize the behavior when visiting the corresponding type of node. By
+    /// default, every method recursively visits the substructure of the input
+    /// by invoking the right visitor method of each of its fields.
+    ///
+    /// [`Visit`]: trait.Visit.html
+    ///
+    /// ```rust
+    /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
+    /// #
+    /// pub trait Visit<'ast> {
+    ///     /* ... */
+    ///
+    ///     fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
+    ///         for attr in &node.attrs {
+    ///             self.visit_attribute(attr);
+    ///         }
+    ///         self.visit_expr(&*node.left);
+    ///         self.visit_bin_op(&node.op);
+    ///         self.visit_expr(&*node.right);
+    ///     }
+    ///
+    ///     /* ... */
+    ///     # fn visit_attribute(&mut self, node: &'ast Attribute);
+    ///     # fn visit_expr(&mut self, node: &'ast Expr);
+    ///     # fn visit_bin_op(&mut self, node: &'ast BinOp);
+    /// }
+    /// ```
+    ///
+    /// *This module is available if Syn is built with the `"visit"` feature.*
+    #[cfg(feature = "visit")]
+    pub mod visit;
+
+    /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
+    /// place.
+    ///
+    /// Each method of the [`VisitMut`] trait is a hook that can be overridden
+    /// to customize the behavior when mutating the corresponding type of node.
+    /// By default, every method recursively visits the substructure of the
+    /// input by invoking the right visitor method of each of its fields.
+    ///
+    /// [`VisitMut`]: trait.VisitMut.html
+    ///
+    /// ```rust
+    /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
+    /// #
+    /// pub trait VisitMut {
+    ///     /* ... */
+    ///
+    ///     fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
+    ///         for attr in &mut node.attrs {
+    ///             self.visit_attribute_mut(attr);
+    ///         }
+    ///         self.visit_expr_mut(&mut *node.left);
+    ///         self.visit_bin_op_mut(&mut node.op);
+    ///         self.visit_expr_mut(&mut *node.right);
+    ///     }
+    ///
+    ///     /* ... */
+    ///     # fn visit_attribute_mut(&mut self, node: &mut Attribute);
+    ///     # fn visit_expr_mut(&mut self, node: &mut Expr);
+    ///     # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
+    /// }
+    /// ```
+    ///
+    /// *This module is available if Syn is built with the `"visit-mut"`
+    /// feature.*
+    #[cfg(feature = "visit-mut")]
+    pub mod visit_mut;
+
+    /// Syntax tree traversal to transform the nodes of an owned syntax tree.
+    ///
+    /// Each method of the [`Fold`] trait is a hook that can be overridden to
+    /// customize the behavior when transforming the corresponding type of node.
+    /// By default, every method recursively visits the substructure of the
+    /// input by invoking the right visitor method of each of its fields.
+    ///
+    /// [`Fold`]: trait.Fold.html
+    ///
+    /// ```rust
+    /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
+    /// #
+    /// pub trait Fold {
+    ///     /* ... */
+    ///
+    ///     fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
+    ///         ExprBinary {
+    ///             attrs: node.attrs
+    ///                        .into_iter()
+    ///                        .map(|attr| self.fold_attribute(attr))
+    ///                        .collect(),
+    ///             left: Box::new(self.fold_expr(*node.left)),
+    ///             op: self.fold_bin_op(node.op),
+    ///             right: Box::new(self.fold_expr(*node.right)),
+    ///         }
+    ///     }
+    ///
+    ///     /* ... */
+    ///     # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
+    ///     # fn fold_expr(&mut self, node: Expr) -> Expr;
+    ///     # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
+    /// }
+    /// ```
+    ///
+    /// *This module is available if Syn is built with the `"fold"` feature.*
+    #[cfg(feature = "fold")]
+    pub mod fold;
+
+    #[cfg(any(feature = "full", feature = "derive"))]
+    #[path = "../gen_helper.rs"]
+    mod helper;
+}
+pub use gen::*;
 
 pub mod next;
+
+////////////////////////////////////////////////////////////////////////////////
+
+#[cfg(feature = "parsing")]
+use synom::{Parser, Synom};
+
+#[cfg(feature = "parsing")]
+mod error;
+#[cfg(feature = "parsing")]
+use error::ParseError;
+
+// Not public API.
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+pub use error::parse_error;
+
+/// Parse tokens of source code into the chosen syntax tree node.
+///
+/// This is preferred over parsing a string because tokens are able to preserve
+/// information about where in the user's code they were originally written (the
+/// "span" of the token), possibly allowing the compiler to produce better error
+/// messages.
+///
+/// This function parses a `proc_macro::TokenStream` which is the type used for
+/// interop with the compiler in a procedural macro. To parse a
+/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
+///
+/// [`syn::parse2`]: fn.parse2.html
+///
+/// *This function is available if Syn is built with both the `"parsing"` and
+/// `"proc-macro"` features.*
+///
+/// # Examples
+///
+/// ```rust
+/// extern crate proc_macro;
+/// use proc_macro::TokenStream;
+///
+/// extern crate syn;
+///
+/// #[macro_use]
+/// extern crate quote;
+///
+/// use syn::DeriveInput;
+///
+/// # const IGNORE_TOKENS: &str = stringify! {
+/// #[proc_macro_derive(MyMacro)]
+/// # };
+/// pub fn my_macro(input: TokenStream) -> TokenStream {
+///     // Parse the tokens into a syntax tree
+///     let ast: DeriveInput = syn::parse(input).unwrap();
+///
+///     // Build the output, possibly using quasi-quotation
+///     let expanded = quote! {
+///         /* ... */
+///     };
+///
+///     // Convert into a token stream and return it
+///     expanded.into()
+/// }
+/// #
+/// # fn main() {}
+/// ```
+#[cfg(all(
+    not(all(target_arch = "wasm32", target_os = "unknown")),
+    feature = "parsing",
+    feature = "proc-macro"
+))]
+pub fn parse<T>(tokens: proc_macro::TokenStream) -> Result<T, ParseError>
+where
+    T: Synom,
+{
+    parse2(tokens.into())
+}
+
+/// Parse a proc-macro2 token stream into the chosen syntax tree node.
+///
+/// This function parses a `proc_macro2::TokenStream` which is commonly useful
+/// when the input comes from a node of the Syn syntax tree, for example the tts
+/// of a [`Macro`] node. When in a procedural macro parsing the
+/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
+/// instead.
+///
+/// [`Macro`]: struct.Macro.html
+/// [`syn::parse`]: fn.parse.html
+///
+/// *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,
+    })
+}
+
+/// Parse a string of Rust code into the chosen syntax tree node.
+///
+/// *This function is available if Syn is built with the `"parsing"` feature.*
+///
+/// # Hygiene
+///
+/// Every span in the resulting syntax tree will be set to resolve at the macro
+/// call site.
+///
+/// # Examples
+///
+/// ```rust
+/// extern crate syn;
+/// #
+/// #
+/// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
+///
+/// use syn::Expr;
+///
+/// fn run() -> Result<()> {
+///     let code = "assert_eq!(u8::max_value(), 255)";
+///     let expr = syn::parse_str::<Expr>(code)?;
+///     println!("{:#?}", expr);
+///     Ok(())
+/// }
+/// #
+/// # 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")),
+    }
+}
+
+// FIXME the name parse_file makes it sound like you might pass in a path to a
+// file, rather than the content.
+/// Parse the content of a file of Rust code.
+///
+/// This is different from `syn::parse_str::<File>(content)` in two ways:
+///
+/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
+/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
+///
+/// If present, either of these would be an error using `from_str`.
+///
+/// *This function is available if Syn is built with the `"parsing"` and `"full"` features.*
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// extern crate syn;
+/// #
+/// #
+/// # type Result<T> = std::result::Result<T, Box<std::error::Error>>;
+///
+/// use std::fs::File;
+/// use std::io::Read;
+///
+/// fn run() -> Result<()> {
+///     let mut file = File::open("path/to/code.rs")?;
+///     let mut content = String::new();
+///     file.read_to_string(&mut content)?;
+///
+///     let ast = syn::parse_file(&content)?;
+///     if let Some(shebang) = ast.shebang {
+///         println!("{}", shebang);
+///     }
+///     println!("{} items", ast.items.len());
+///
+///     Ok(())
+/// }
+/// #
+/// # fn main() { run().unwrap() }
+/// ```
+#[cfg(all(feature = "parsing", feature = "full"))]
+pub fn parse_file(mut content: &str) -> Result<File, ParseError> {
+    // Strip the BOM if it is present
+    const BOM: &'static str = "\u{feff}";
+    if content.starts_with(BOM) {
+        content = &content[BOM.len()..];
+    }
+
+    let mut shebang = None;
+    if content.starts_with("#!") && !content.starts_with("#![") {
+        if let Some(idx) = content.find('\n') {
+            shebang = Some(content[..idx].to_string());
+            content = &content[idx..];
+        } else {
+            shebang = Some(content.to_string());
+            content = "";
+        }
+    }
+
+    let mut file: File = parse_str(content)?;
+    file.shebang = shebang;
+    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),
+        }
+    }
+}
diff --git a/src/lifetime.rs b/src/lifetime.rs
new file mode 100644
index 0000000..5ca876f
--- /dev/null
+++ b/src/lifetime.rs
@@ -0,0 +1,150 @@
+// 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 std::cmp::Ordering;
+use std::fmt::{self, Display};
+use std::hash::{Hash, Hasher};
+
+use proc_macro2::{Ident, Span};
+use unicode_xid::UnicodeXID;
+
+use token::Apostrophe;
+
+/// A Rust lifetime: `'a`.
+///
+/// Lifetime names must conform to the following rules:
+///
+/// - Must start with an apostrophe.
+/// - Must not consist of just an apostrophe: `'`.
+/// - Character after the apostrophe must be `_` or a Unicode code point with
+///   the XID_Start property.
+/// - All following characters must be Unicode code points with the XID_Continue
+///   property.
+///
+/// *This type is available if Syn is built with the `"derive"` or `"full"`
+/// feature.*
+#[cfg_attr(feature = "extra-traits", derive(Debug))]
+#[derive(Clone)]
+pub struct Lifetime {
+    pub apostrophe: Apostrophe,
+    pub ident: Ident,
+}
+
+impl Lifetime {
+    pub fn new(s: &str, span: Span) -> Self {
+        if !s.starts_with('\'') {
+            panic!(
+                "lifetime name must start with apostrophe as in \"'a\", got {:?}",
+                s
+            );
+        }
+
+        if s == "'" {
+            panic!("lifetime name must not be empty");
+        }
+
+        fn xid_ok(s: &str) -> bool {
+            let mut chars = s.chars();
+            let first = chars.next().unwrap();
+            if !(UnicodeXID::is_xid_start(first) || first == '_') {
+                return false;
+            }
+            for ch in chars {
+                if !UnicodeXID::is_xid_continue(ch) {
+                    return false;
+                }
+            }
+            true
+        }
+
+        if !xid_ok(&s[1..]) {
+            panic!("{:?} is not a valid lifetime name", s);
+        }
+
+        Lifetime {
+            apostrophe: Apostrophe::default(),
+            ident: Ident::new(&s[1..], span),
+        }
+    }
+}
+
+impl Display for Lifetime {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        "'".fmt(formatter)?;
+        self.ident.fmt(formatter)
+    }
+}
+
+impl PartialEq for Lifetime {
+    fn eq(&self, other: &Lifetime) -> bool {
+        self.ident.eq(&other.ident)
+    }
+}
+
+impl Eq for Lifetime {}
+
+impl PartialOrd for Lifetime {
+    fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Lifetime {
+    fn cmp(&self, other: &Lifetime) -> Ordering {
+        self.ident.cmp(&other.ident)
+    }
+}
+
+impl Hash for Lifetime {
+    fn hash<H: Hasher>(&self, h: &mut H) {
+        self.ident.hash(h)
+    }
+}
+
+#[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(),
+            };
+
+            let ret = Lifetime {
+                ident: ident,
+                apostrophe: apostrophe,
+            };
+            Ok((ret, rest))
+        }
+
+        fn description() -> Option<&'static str> {
+            Some("lifetime")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::ToTokens;
+
+    impl ToTokens for Lifetime {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.apostrophe.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+        }
+    }
+}
diff --git a/src/lit.rs b/src/lit.rs
new file mode 100644
index 0000000..47555d4
--- /dev/null
+++ b/src/lit.rs
@@ -0,0 +1,1026 @@
+// 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 proc_macro2::{Literal, Span};
+use std::str;
+
+#[cfg(feature = "printing")]
+use proc_macro2::Ident;
+
+#[cfg(feature = "parsing")]
+use proc_macro2::TokenStream;
+#[cfg(feature = "parsing")]
+use {ParseError, Synom};
+
+use proc_macro2::TokenTree;
+
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+
+ast_enum_of_structs! {
+    /// A Rust literal such as a string or integer or boolean.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum Lit {
+        /// A UTF-8 string literal: `"foo"`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Str(LitStr #manual_extra_traits {
+            token: Literal,
+        }),
+
+        /// A byte string literal: `b"foo"`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub ByteStr(LitByteStr #manual_extra_traits {
+            token: Literal,
+        }),
+
+        /// A byte literal: `b'f'`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Byte(LitByte #manual_extra_traits {
+            token: Literal,
+        }),
+
+        /// A character literal: `'a'`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Char(LitChar #manual_extra_traits {
+            token: Literal,
+        }),
+
+        /// An integer literal: `1` or `1u16`.
+        ///
+        /// Holds up to 64 bits of data. Use `LitVerbatim` for any larger
+        /// integer literal.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Int(LitInt #manual_extra_traits {
+            token: Literal,
+        }),
+
+        /// A floating point literal: `1f64` or `1.0e10f64`.
+        ///
+        /// Must be finite. May not be infinte or NaN.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Float(LitFloat #manual_extra_traits {
+            token: Literal,
+        }),
+
+        /// A boolean literal: `true` or `false`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Bool(LitBool #manual_extra_traits {
+            pub value: bool,
+            pub span: Span,
+        }),
+
+        /// A raw token literal not interpreted by Syn, possibly because it
+        /// represents an integer larger than 64 bits.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Verbatim(LitVerbatim #manual_extra_traits {
+            pub token: Literal,
+        }),
+    }
+}
+
+impl LitStr {
+    pub fn new(value: &str, span: Span) -> Self {
+        let mut lit = Literal::string(value);
+        lit.set_span(span);
+        LitStr { token: lit }
+    }
+
+    pub fn value(&self) -> String {
+        value::parse_lit_str(&self.token.to_string())
+    }
+
+    /// 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`.
+    #[cfg(feature = "parsing")]
+    pub fn parse<T: Synom>(&self) -> Result<T, ParseError> {
+        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> {
+            let stream = ::parse_str(&s.value())?;
+            Ok(respan_token_stream(stream, s.span()))
+        }
+
+        // Token stream with every span replaced by the given one.
+        fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
+            stream
+                .into_iter()
+                .map(|token| respan_token_tree(token, span))
+                .collect()
+        }
+
+        // Token tree with every span replaced by the given one.
+        fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
+            match token {
+                TokenTree::Group(ref mut g) => {
+                    let stream = respan_token_stream(g.stream().clone(), span);
+                    *g = Group::new(g.delimiter(), stream);
+                    g.set_span(span);
+                }
+                ref mut other => other.set_span(span),
+            }
+            token
+        }
+
+        spanned_tokens(self).and_then(::parse2)
+    }
+
+    pub fn span(&self) -> Span {
+        self.token.span()
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.token.set_span(span)
+    }
+}
+
+impl LitByteStr {
+    pub fn new(value: &[u8], span: Span) -> Self {
+        let mut token = Literal::byte_string(value);
+        token.set_span(span);
+        LitByteStr { token: token }
+    }
+
+    pub fn value(&self) -> Vec<u8> {
+        value::parse_lit_byte_str(&self.token.to_string())
+    }
+
+    pub fn span(&self) -> Span {
+        self.token.span()
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.token.set_span(span)
+    }
+}
+
+impl LitByte {
+    pub fn new(value: u8, span: Span) -> Self {
+        let mut token = Literal::u8_suffixed(value);
+        token.set_span(span);
+        LitByte { token: token }
+    }
+
+    pub fn value(&self) -> u8 {
+        value::parse_lit_byte(&self.token.to_string())
+    }
+
+    pub fn span(&self) -> Span {
+        self.token.span()
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.token.set_span(span)
+    }
+}
+
+impl LitChar {
+    pub fn new(value: char, span: Span) -> Self {
+        let mut token = Literal::character(value);
+        token.set_span(span);
+        LitChar { token: token }
+    }
+
+    pub fn value(&self) -> char {
+        value::parse_lit_char(&self.token.to_string())
+    }
+
+    pub fn span(&self) -> Span {
+        self.token.span()
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.token.set_span(span)
+    }
+}
+
+impl LitInt {
+    pub fn new(value: u64, suffix: IntSuffix, span: Span) -> Self {
+        let mut token = match suffix {
+            IntSuffix::Isize => Literal::isize_suffixed(value as isize),
+            IntSuffix::I8 => Literal::i8_suffixed(value as i8),
+            IntSuffix::I16 => Literal::i16_suffixed(value as i16),
+            IntSuffix::I32 => Literal::i32_suffixed(value as i32),
+            IntSuffix::I64 => Literal::i64_suffixed(value as i64),
+            IntSuffix::I128 => value::to_literal(&format!("{}i128", value)),
+            IntSuffix::Usize => Literal::usize_suffixed(value as usize),
+            IntSuffix::U8 => Literal::u8_suffixed(value as u8),
+            IntSuffix::U16 => Literal::u16_suffixed(value as u16),
+            IntSuffix::U32 => Literal::u32_suffixed(value as u32),
+            IntSuffix::U64 => Literal::u64_suffixed(value),
+            IntSuffix::U128 => value::to_literal(&format!("{}u128", value)),
+            IntSuffix::None => Literal::u64_unsuffixed(value),
+        };
+        token.set_span(span);
+        LitInt { token: token }
+    }
+
+    pub fn value(&self) -> u64 {
+        value::parse_lit_int(&self.token.to_string()).unwrap()
+    }
+
+    pub fn suffix(&self) -> IntSuffix {
+        let value = self.token.to_string();
+        for (s, suffix) in vec![
+            ("i8", IntSuffix::I8),
+            ("i16", IntSuffix::I16),
+            ("i32", IntSuffix::I32),
+            ("i64", IntSuffix::I64),
+            ("i128", IntSuffix::I128),
+            ("isize", IntSuffix::Isize),
+            ("u8", IntSuffix::U8),
+            ("u16", IntSuffix::U16),
+            ("u32", IntSuffix::U32),
+            ("u64", IntSuffix::U64),
+            ("u128", IntSuffix::U128),
+            ("usize", IntSuffix::Usize),
+        ] {
+            if value.ends_with(s) {
+                return suffix;
+            }
+        }
+        IntSuffix::None
+    }
+
+    pub fn span(&self) -> Span {
+        self.token.span()
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.token.set_span(span)
+    }
+}
+
+impl LitFloat {
+    pub fn new(value: f64, suffix: FloatSuffix, span: Span) -> Self {
+        let mut token = match suffix {
+            FloatSuffix::F32 => Literal::f32_suffixed(value as f32),
+            FloatSuffix::F64 => Literal::f64_suffixed(value),
+            FloatSuffix::None => Literal::f64_unsuffixed(value),
+        };
+        token.set_span(span);
+        LitFloat { token: token }
+    }
+
+    pub fn value(&self) -> f64 {
+        value::parse_lit_float(&self.token.to_string())
+    }
+
+    pub fn suffix(&self) -> FloatSuffix {
+        let value = self.token.to_string();
+        for (s, suffix) in vec![("f32", FloatSuffix::F32), ("f64", FloatSuffix::F64)] {
+            if value.ends_with(s) {
+                return suffix;
+            }
+        }
+        FloatSuffix::None
+    }
+
+    pub fn span(&self) -> Span {
+        self.token.span()
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.token.set_span(span)
+    }
+}
+
+macro_rules! lit_extra_traits {
+    ($ty:ident, $field:ident) => {
+        #[cfg(feature = "extra-traits")]
+        impl Eq for $ty {}
+
+        #[cfg(feature = "extra-traits")]
+        impl PartialEq for $ty {
+            fn eq(&self, other: &Self) -> bool {
+                self.$field.to_string() == other.$field.to_string()
+            }
+        }
+
+        #[cfg(feature = "extra-traits")]
+        impl Hash for $ty {
+            fn hash<H>(&self, state: &mut H)
+            where
+                H: Hasher,
+            {
+                self.$field.to_string().hash(state);
+            }
+        }
+    };
+}
+
+impl LitVerbatim {
+    pub fn span(&self) -> Span {
+        self.token.span()
+    }
+
+    pub fn set_span(&mut self, span: Span) {
+        self.token.set_span(span)
+    }
+}
+
+lit_extra_traits!(LitStr, token);
+lit_extra_traits!(LitByteStr, token);
+lit_extra_traits!(LitByte, token);
+lit_extra_traits!(LitChar, token);
+lit_extra_traits!(LitInt, token);
+lit_extra_traits!(LitFloat, token);
+lit_extra_traits!(LitBool, value);
+lit_extra_traits!(LitVerbatim, token);
+
+ast_enum! {
+    /// The style of a string literal, either plain quoted or a raw string like
+    /// `r##"data"##`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum StrStyle #no_visit {
+        /// An ordinary string like `"data"`.
+        Cooked,
+        /// A raw string like `r##"data"##`.
+        ///
+        /// The unsigned integer is the number of `#` symbols used.
+        Raw(usize),
+    }
+}
+
+ast_enum! {
+    /// The suffix on an integer literal if any, like the `u8` in `127u8`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum IntSuffix #no_visit {
+        I8,
+        I16,
+        I32,
+        I64,
+        I128,
+        Isize,
+        U8,
+        U16,
+        U32,
+        U64,
+        U128,
+        Usize,
+        None,
+    }
+}
+
+ast_enum! {
+    /// The suffix on a floating point literal if any, like the `f32` in
+    /// `1.0f32`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum FloatSuffix #no_visit {
+        F32,
+        F64,
+        None,
+    }
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+    use buffer::Cursor;
+    use parse_error;
+    use synom::PResult;
+    use synom::Synom;
+
+    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))
+                    }
+                }
+                _ => 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")
+        }
+    }
+
+    impl_synom!(LitStr "string literal" switch!(
+        syn!(Lit),
+        Lit::Str(lit) => value!(lit)
+        |
+        _ => reject!()
+    ));
+
+    impl_synom!(LitByteStr "byte string literal" switch!(
+        syn!(Lit),
+        Lit::ByteStr(lit) => value!(lit)
+        |
+        _ => reject!()
+    ));
+
+    impl_synom!(LitByte "byte literal" switch!(
+        syn!(Lit),
+        Lit::Byte(lit) => value!(lit)
+        |
+        _ => reject!()
+    ));
+
+    impl_synom!(LitChar "character literal" switch!(
+        syn!(Lit),
+        Lit::Char(lit) => value!(lit)
+        |
+        _ => reject!()
+    ));
+
+    impl_synom!(LitInt "integer literal" switch!(
+        syn!(Lit),
+        Lit::Int(lit) => value!(lit)
+        |
+        _ => reject!()
+    ));
+
+    impl_synom!(LitFloat "floating point literal" switch!(
+        syn!(Lit),
+        Lit::Float(lit) => value!(lit)
+        |
+        _ => reject!()
+    ));
+
+    impl_synom!(LitBool "boolean literal" switch!(
+        syn!(Lit),
+        Lit::Bool(lit) => value!(lit)
+        |
+        _ => reject!()
+    ));
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::{ToTokens, TokenStreamExt};
+
+    impl ToTokens for LitStr {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for LitByteStr {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for LitByte {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for LitChar {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for LitInt {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for LitFloat {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for LitBool {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            let s = if self.value { "true" } else { "false" };
+            tokens.append(Ident::new(s, self.span));
+        }
+    }
+
+    impl ToTokens for LitVerbatim {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.token.to_tokens(tokens);
+        }
+    }
+}
+
+mod value {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use std::char;
+    use std::ops::{Index, RangeFrom};
+
+    impl Lit {
+        /// Interpret a Syn literal from a proc-macro2 literal.
+        ///
+        /// Not all proc-macro2 literals are valid Syn literals. In particular,
+        /// doc comments are considered by proc-macro2 to be literals but in Syn
+        /// they are [`Attribute`].
+        ///
+        /// [`Attribute`]: struct.Attribute.html
+        ///
+        /// # Panics
+        ///
+        /// Panics if the input is a doc comment literal.
+        pub fn new(token: Literal) -> Self {
+            let value = token.to_string();
+
+            match value::byte(&value, 0) {
+                b'"' | b'r' => return Lit::Str(LitStr { token: token }),
+                b'b' => match value::byte(&value, 1) {
+                    b'"' | b'r' => return Lit::ByteStr(LitByteStr { token: token }),
+                    b'\'' => return Lit::Byte(LitByte { token: token }),
+                    _ => {}
+                },
+                b'\'' => return Lit::Char(LitChar { token: token }),
+                b'0'...b'9' => if number_is_int(&value) {
+                    return Lit::Int(LitInt { token: token });
+                } else if number_is_float(&value) {
+                    return Lit::Float(LitFloat { token: token });
+                } else {
+                    // number overflow
+                    return Lit::Verbatim(LitVerbatim { token: token });
+                },
+                _ => if value == "true" || value == "false" {
+                    return Lit::Bool(LitBool {
+                        value: value == "true",
+                        span: token.span(),
+                    });
+                },
+            }
+
+            panic!("Unrecognized literal: {}", value);
+        }
+    }
+
+    fn number_is_int(value: &str) -> bool {
+        if number_is_float(value) {
+            false
+        } else {
+            value::parse_lit_int(value).is_some()
+        }
+    }
+
+    fn number_is_float(value: &str) -> bool {
+        if value.contains('.') {
+            true
+        } else if value.starts_with("0x") || value.ends_with("size") {
+            false
+        } else {
+            value.contains('e') || value.contains('E')
+        }
+    }
+
+    /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
+    /// past the end of the input buffer.
+    pub fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
+        let s = s.as_ref();
+        if idx < s.len() {
+            s[idx]
+        } else {
+            0
+        }
+    }
+
+    fn next_chr(s: &str) -> char {
+        s.chars().next().unwrap_or('\0')
+    }
+
+    pub fn parse_lit_str(s: &str) -> String {
+        match byte(s, 0) {
+            b'"' => parse_lit_str_cooked(s),
+            b'r' => parse_lit_str_raw(s),
+            _ => unreachable!(),
+        }
+    }
+
+    // Clippy false positive
+    // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
+    #[cfg_attr(feature = "cargo-clippy", allow(needless_continue))]
+    fn parse_lit_str_cooked(mut s: &str) -> String {
+        assert_eq!(byte(s, 0), b'"');
+        s = &s[1..];
+
+        let mut out = String::new();
+        'outer: loop {
+            let ch = match byte(s, 0) {
+                b'"' => break,
+                b'\\' => {
+                    let b = byte(s, 1);
+                    s = &s[2..];
+                    match b {
+                        b'x' => {
+                            let (byte, rest) = backslash_x(s);
+                            s = rest;
+                            assert!(byte <= 0x80, "Invalid \\x byte in string literal");
+                            char::from_u32(u32::from(byte)).unwrap()
+                        }
+                        b'u' => {
+                            let (chr, rest) = backslash_u(s);
+                            s = rest;
+                            chr
+                        }
+                        b'n' => '\n',
+                        b'r' => '\r',
+                        b't' => '\t',
+                        b'\\' => '\\',
+                        b'0' => '\0',
+                        b'\'' => '\'',
+                        b'"' => '"',
+                        b'\r' | b'\n' => loop {
+                            let ch = next_chr(s);
+                            if ch.is_whitespace() {
+                                s = &s[ch.len_utf8()..];
+                            } else {
+                                continue 'outer;
+                            }
+                        },
+                        b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
+                    }
+                }
+                b'\r' => {
+                    assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
+                    s = &s[2..];
+                    '\n'
+                }
+                _ => {
+                    let ch = next_chr(s);
+                    s = &s[ch.len_utf8()..];
+                    ch
+                }
+            };
+            out.push(ch);
+        }
+
+        assert_eq!(s, "\"");
+        out
+    }
+
+    fn parse_lit_str_raw(mut s: &str) -> String {
+        assert_eq!(byte(s, 0), b'r');
+        s = &s[1..];
+
+        let mut pounds = 0;
+        while byte(s, pounds) == b'#' {
+            pounds += 1;
+        }
+        assert_eq!(byte(s, pounds), b'"');
+        assert_eq!(byte(s, s.len() - pounds - 1), b'"');
+        for end in s[s.len() - pounds..].bytes() {
+            assert_eq!(end, b'#');
+        }
+
+        s[pounds + 1..s.len() - pounds - 1].to_owned()
+    }
+
+    pub fn parse_lit_byte_str(s: &str) -> Vec<u8> {
+        assert_eq!(byte(s, 0), b'b');
+        match byte(s, 1) {
+            b'"' => parse_lit_byte_str_cooked(s),
+            b'r' => parse_lit_byte_str_raw(s),
+            _ => unreachable!(),
+        }
+    }
+
+    // Clippy false positive
+    // https://github.com/rust-lang-nursery/rust-clippy/issues/2329
+    #[cfg_attr(feature = "cargo-clippy", allow(needless_continue))]
+    fn parse_lit_byte_str_cooked(mut s: &str) -> Vec<u8> {
+        assert_eq!(byte(s, 0), b'b');
+        assert_eq!(byte(s, 1), b'"');
+        s = &s[2..];
+
+        // We're going to want to have slices which don't respect codepoint boundaries.
+        let mut s = s.as_bytes();
+
+        let mut out = Vec::new();
+        'outer: loop {
+            let byte = match byte(s, 0) {
+                b'"' => break,
+                b'\\' => {
+                    let b = byte(s, 1);
+                    s = &s[2..];
+                    match b {
+                        b'x' => {
+                            let (b, rest) = backslash_x(s);
+                            s = rest;
+                            b
+                        }
+                        b'n' => b'\n',
+                        b'r' => b'\r',
+                        b't' => b'\t',
+                        b'\\' => b'\\',
+                        b'0' => b'\0',
+                        b'\'' => b'\'',
+                        b'"' => b'"',
+                        b'\r' | b'\n' => loop {
+                            let byte = byte(s, 0);
+                            let ch = char::from_u32(u32::from(byte)).unwrap();
+                            if ch.is_whitespace() {
+                                s = &s[1..];
+                            } else {
+                                continue 'outer;
+                            }
+                        },
+                        b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
+                    }
+                }
+                b'\r' => {
+                    assert_eq!(byte(s, 1), b'\n', "Bare CR not allowed in string");
+                    s = &s[2..];
+                    b'\n'
+                }
+                b => {
+                    s = &s[1..];
+                    b
+                }
+            };
+            out.push(byte);
+        }
+
+        assert_eq!(s, b"\"");
+        out
+    }
+
+    fn parse_lit_byte_str_raw(s: &str) -> Vec<u8> {
+        assert_eq!(byte(s, 0), b'b');
+        parse_lit_str_raw(&s[1..]).into_bytes()
+    }
+
+    pub fn parse_lit_byte(s: &str) -> u8 {
+        assert_eq!(byte(s, 0), b'b');
+        assert_eq!(byte(s, 1), b'\'');
+
+        // We're going to want to have slices which don't respect codepoint boundaries.
+        let mut s = s[2..].as_bytes();
+
+        let b = match byte(s, 0) {
+            b'\\' => {
+                let b = byte(s, 1);
+                s = &s[2..];
+                match b {
+                    b'x' => {
+                        let (b, rest) = backslash_x(s);
+                        s = rest;
+                        b
+                    }
+                    b'n' => b'\n',
+                    b'r' => b'\r',
+                    b't' => b'\t',
+                    b'\\' => b'\\',
+                    b'0' => b'\0',
+                    b'\'' => b'\'',
+                    b'"' => b'"',
+                    b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
+                }
+            }
+            b => {
+                s = &s[1..];
+                b
+            }
+        };
+
+        assert_eq!(byte(s, 0), b'\'');
+        b
+    }
+
+    pub fn parse_lit_char(mut s: &str) -> char {
+        assert_eq!(byte(s, 0), b'\'');
+        s = &s[1..];
+
+        let ch = match byte(s, 0) {
+            b'\\' => {
+                let b = byte(s, 1);
+                s = &s[2..];
+                match b {
+                    b'x' => {
+                        let (byte, rest) = backslash_x(s);
+                        s = rest;
+                        assert!(byte <= 0x80, "Invalid \\x byte in string literal");
+                        char::from_u32(u32::from(byte)).unwrap()
+                    }
+                    b'u' => {
+                        let (chr, rest) = backslash_u(s);
+                        s = rest;
+                        chr
+                    }
+                    b'n' => '\n',
+                    b'r' => '\r',
+                    b't' => '\t',
+                    b'\\' => '\\',
+                    b'0' => '\0',
+                    b'\'' => '\'',
+                    b'"' => '"',
+                    b => panic!("unexpected byte {:?} after \\ character in byte literal", b),
+                }
+            }
+            _ => {
+                let ch = next_chr(s);
+                s = &s[ch.len_utf8()..];
+                ch
+            }
+        };
+        assert_eq!(s, "\'", "Expected end of char literal");
+        ch
+    }
+
+    fn backslash_x<S>(s: &S) -> (u8, &S)
+    where
+        S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
+    {
+        let mut ch = 0;
+        let b0 = byte(s, 0);
+        let b1 = byte(s, 1);
+        ch += 0x10 * match b0 {
+            b'0'...b'9' => b0 - b'0',
+            b'a'...b'f' => 10 + (b0 - b'a'),
+            b'A'...b'F' => 10 + (b0 - b'A'),
+            _ => panic!("unexpected non-hex character after \\x"),
+        };
+        ch += match b1 {
+            b'0'...b'9' => b1 - b'0',
+            b'a'...b'f' => 10 + (b1 - b'a'),
+            b'A'...b'F' => 10 + (b1 - b'A'),
+            _ => panic!("unexpected non-hex character after \\x"),
+        };
+        (ch, &s[2..])
+    }
+
+    fn backslash_u(mut s: &str) -> (char, &str) {
+        if byte(s, 0) != b'{' {
+            panic!("expected {{ after \\u");
+        }
+        s = &s[1..];
+
+        let mut ch = 0;
+        for _ in 0..6 {
+            let b = byte(s, 0);
+            match b {
+                b'0'...b'9' => {
+                    ch *= 0x10;
+                    ch += u32::from(b - b'0');
+                    s = &s[1..];
+                }
+                b'a'...b'f' => {
+                    ch *= 0x10;
+                    ch += u32::from(10 + b - b'a');
+                    s = &s[1..];
+                }
+                b'A'...b'F' => {
+                    ch *= 0x10;
+                    ch += u32::from(10 + b - b'A');
+                    s = &s[1..];
+                }
+                b'}' => break,
+                _ => panic!("unexpected non-hex character after \\u"),
+            }
+        }
+        assert!(byte(s, 0) == b'}');
+        s = &s[1..];
+
+        if let Some(ch) = char::from_u32(ch) {
+            (ch, s)
+        } else {
+            panic!("character code {:x} is not a valid unicode character", ch);
+        }
+    }
+
+    pub fn parse_lit_int(mut s: &str) -> Option<u64> {
+        let base = match (byte(s, 0), byte(s, 1)) {
+            (b'0', b'x') => {
+                s = &s[2..];
+                16
+            }
+            (b'0', b'o') => {
+                s = &s[2..];
+                8
+            }
+            (b'0', b'b') => {
+                s = &s[2..];
+                2
+            }
+            (b'0'...b'9', _) => 10,
+            _ => unreachable!(),
+        };
+
+        let mut value = 0u64;
+        loop {
+            let b = byte(s, 0);
+            let digit = match b {
+                b'0'...b'9' => u64::from(b - b'0'),
+                b'a'...b'f' if base > 10 => 10 + u64::from(b - b'a'),
+                b'A'...b'F' if base > 10 => 10 + u64::from(b - b'A'),
+                b'_' => {
+                    s = &s[1..];
+                    continue;
+                }
+                // NOTE: Looking at a floating point literal, we don't want to
+                // consider these integers.
+                b'.' if base == 10 => return None,
+                b'e' | b'E' if base == 10 => return None,
+                _ => break,
+            };
+
+            if digit >= base {
+                panic!("Unexpected digit {:x} out of base range", digit);
+            }
+
+            value = match value.checked_mul(base) {
+                Some(value) => value,
+                None => return None,
+            };
+            value = match value.checked_add(digit) {
+                Some(value) => value,
+                None => return None,
+            };
+            s = &s[1..];
+        }
+
+        Some(value)
+    }
+
+    pub fn parse_lit_float(input: &str) -> f64 {
+        // Rust's floating point literals are very similar to the ones parsed by
+        // the standard library, except that rust's literals can contain
+        // ignorable underscores. Let's remove those underscores.
+        let mut bytes = input.to_owned().into_bytes();
+        let mut write = 0;
+        for read in 0..bytes.len() {
+            if bytes[read] == b'_' {
+                continue; // Don't increase write
+            }
+            if write != read {
+                let x = bytes[read];
+                bytes[write] = x;
+            }
+            write += 1;
+        }
+        bytes.truncate(write);
+        let input = String::from_utf8(bytes).unwrap();
+        let end = input.find('f').unwrap_or_else(|| input.len());
+        input[..end].parse().unwrap()
+    }
+
+    pub fn to_literal(s: &str) -> Literal {
+        let stream = s.parse::<TokenStream>().unwrap();
+        match stream.into_iter().next().unwrap() {
+            TokenTree::Literal(l) => l,
+            _ => unreachable!(),
+        }
+    }
+}
diff --git a/src/mac.rs b/src/mac.rs
new file mode 100644
index 0000000..a9219fe
--- /dev/null
+++ b/src/mac.rs
@@ -0,0 +1,117 @@
+// 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 super::*;
+use proc_macro2::TokenStream;
+use token::{Brace, Bracket, Paren};
+
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+#[cfg(feature = "extra-traits")]
+use tt::TokenStreamHelper;
+
+ast_struct! {
+    /// A macro invocation: `println!("{}", mac)`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Macro #manual_extra_traits {
+        pub path: Path,
+        pub bang_token: Token![!],
+        pub delimiter: MacroDelimiter,
+        pub tts: TokenStream,
+    }
+}
+
+ast_enum! {
+    /// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum MacroDelimiter {
+        Paren(Paren),
+        Brace(Brace),
+        Bracket(Bracket),
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for Macro {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for Macro {
+    fn eq(&self, other: &Self) -> bool {
+        self.path == other.path
+            && self.bang_token == other.bang_token
+            && self.delimiter == other.delimiter
+            && TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for Macro {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        self.path.hash(state);
+        self.bang_token.hash(state);
+        self.delimiter.hash(state);
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+#[cfg(feature = "parsing")]
+pub mod parsing {
+    use super::*;
+
+    use synom::Synom;
+
+    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,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("macro invocation")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::ToTokens;
+
+    impl ToTokens for Macro {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.path.to_tokens(tokens);
+            self.bang_token.to_tokens(tokens);
+            match self.delimiter {
+                MacroDelimiter::Paren(ref paren) => {
+                    paren.surround(tokens, |tokens| self.tts.to_tokens(tokens));
+                }
+                MacroDelimiter::Brace(ref brace) => {
+                    brace.surround(tokens, |tokens| self.tts.to_tokens(tokens));
+                }
+                MacroDelimiter::Bracket(ref bracket) => {
+                    bracket.surround(tokens, |tokens| self.tts.to_tokens(tokens));
+                }
+            }
+        }
+    }
+}
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 0000000..f4e7d0a
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,196 @@
+// 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(any(feature = "full", feature = "derive"))]
+macro_rules! ast_struct {
+    (
+        $(#[$attr:meta])*
+        pub struct $name:ident #full $($rest:tt)*
+    ) => {
+        #[cfg(feature = "full")]
+        $(#[$attr])*
+        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
+        #[cfg_attr(feature = "clone-impls", derive(Clone))]
+        pub struct $name $($rest)*
+
+        #[cfg(not(feature = "full"))]
+        $(#[$attr])*
+        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
+        #[cfg_attr(feature = "clone-impls", derive(Clone))]
+        pub struct $name {
+            _noconstruct: (),
+        }
+    };
+
+    (
+        $(#[$attr:meta])*
+        pub struct $name:ident #manual_extra_traits $($rest:tt)*
+    ) => {
+        $(#[$attr])*
+        #[cfg_attr(feature = "extra-traits", derive(Debug))]
+        #[cfg_attr(feature = "clone-impls", derive(Clone))]
+        pub struct $name $($rest)*
+    };
+
+    (
+        $(#[$attr:meta])*
+        pub struct $name:ident $($rest:tt)*
+    ) => {
+        $(#[$attr])*
+        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
+        #[cfg_attr(feature = "clone-impls", derive(Clone))]
+        pub struct $name $($rest)*
+    };
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! ast_enum {
+    (
+        $(#[$enum_attr:meta])*
+        pub enum $name:ident $(# $tags:ident)* { $($variants:tt)* }
+    ) => (
+        $(#[$enum_attr])*
+        #[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
+        #[cfg_attr(feature = "clone-impls", derive(Clone))]
+        pub enum $name {
+            $($variants)*
+        }
+    )
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! ast_enum_of_structs {
+    (
+        $(#[$enum_attr:meta])*
+        pub enum $name:ident {
+            $(
+                $(#[$variant_attr:meta])*
+                pub $variant:ident $( ($member:ident $($rest:tt)*) )*,
+            )*
+        }
+
+        $($remaining:tt)*
+    ) => (
+        ast_enum! {
+            $(#[$enum_attr])*
+            pub enum $name {
+                $(
+                    $(#[$variant_attr])*
+                    $variant $( ($member) )*,
+                )*
+            }
+        }
+
+        $(
+            maybe_ast_struct! {
+                $(#[$variant_attr])*
+                $(
+                    pub struct $member $($rest)*
+                )*
+            }
+
+            $(
+                impl From<$member> for $name {
+                    fn from(e: $member) -> $name {
+                        $name::$variant(e)
+                    }
+                }
+            )*
+        )*
+
+        #[cfg(feature = "printing")]
+        generate_to_tokens! {
+            $($remaining)*
+            ()
+            tokens
+            $name { $($variant $( [$($rest)*] )*,)* }
+        }
+    )
+}
+
+#[cfg(all(
+    feature = "printing",
+    any(feature = "full", feature = "derive")
+))]
+macro_rules! generate_to_tokens {
+    (do_not_generate_to_tokens $($foo:tt)*) => ();
+
+    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident, $($next:tt)*}) => {
+        generate_to_tokens!(
+            ($($arms)* $name::$variant => {})
+            $tokens $name { $($next)* }
+        );
+    };
+
+    (($($arms:tt)*) $tokens:ident $name:ident { $variant:ident [$($rest:tt)*], $($next:tt)*}) => {
+        generate_to_tokens!(
+            ($($arms)* $name::$variant(ref _e) => to_tokens_call!(_e, $tokens, $($rest)*),)
+            $tokens $name { $($next)* }
+        );
+    };
+
+    (($($arms:tt)*) $tokens:ident $name:ident {}) => {
+        impl ::quote::ToTokens for $name {
+            fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
+                match *self {
+                    $($arms)*
+                }
+            }
+        }
+    };
+}
+
+#[cfg(all(feature = "printing", feature = "full"))]
+macro_rules! to_tokens_call {
+    ($e:ident, $tokens:ident, $($rest:tt)*) => {
+        $e.to_tokens($tokens)
+    };
+}
+
+#[cfg(all(
+    feature = "printing",
+    feature = "derive",
+    not(feature = "full")
+))]
+macro_rules! to_tokens_call {
+    // If the variant is marked as #full, don't auto-generate to-tokens for it.
+    ($e:ident, $tokens:ident, #full $($rest:tt)*) => {
+        unreachable!()
+    };
+    ($e:ident, $tokens:ident, $($rest:tt)*) => {
+        $e.to_tokens($tokens)
+    };
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! maybe_ast_struct {
+    (
+        $(#[$attr:meta])*
+        $(
+            pub struct $name:ident
+        )*
+    ) => ();
+
+    ($($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/next/error.rs b/src/next/error.rs
index 92ac21c..05473f3 100644
--- a/src/next/error.rs
+++ b/src/next/error.rs
@@ -6,7 +6,7 @@
     Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
 };
 
-use syn::buffer::Cursor;
+use buffer::Cursor;
 
 /// The result of a Syn parser.
 pub type Result<T> = std::result::Result<T, Error>;
diff --git a/src/next/group.rs b/src/next/group.rs
index dca4d1c..40317bf 100644
--- a/src/next/group.rs
+++ b/src/next/group.rs
@@ -29,11 +29,22 @@
 /// Parse a set of curly braces and expose their content to subsequent parsers.
 ///
 /// ```rust
-/// # extern crate syn_error_experiment;
+/// # extern crate syn;
 /// #
-/// use syn_error_experiment::{braced, token, Ident, Token};
-/// use syn_error_experiment::parse::{Parse, ParseStream, Result};
-/// # use syn_error_experiment::Field;
+/// use syn::{braced, Token};
+/// use syn::next::{token, Ident};
+/// use syn::next::parse::{Parse, ParseStream, Result};
+/// #
+/// # mod example {
+/// #     use super::{syn, braced, token, Ident, Parse, ParseStream, Result};
+/// #
+/// #     macro_rules! Token {
+/// #         (struct) => {
+/// #             syn::next::token::Struct
+/// #         };
+/// #     }
+/// #
+/// #     type Field = Ident;
 ///
 /// // Parse a simplified struct syntax like:
 /// //
@@ -59,6 +70,9 @@
 ///         })
 ///     }
 /// }
+/// # }
+/// #
+/// # fn main() {}
 /// ```
 #[macro_export]
 macro_rules! braced {
diff --git a/src/next/lookahead.rs b/src/next/lookahead.rs
index db0fa63..256ac05 100644
--- a/src/next/lookahead.rs
+++ b/src/next/lookahead.rs
@@ -1,7 +1,7 @@
 use std::cell::RefCell;
 
+use buffer::Cursor;
 use proc_macro2::Span;
-use syn::buffer::Cursor;
 
 use super::error;
 use super::parse::Error;
diff --git a/src/next/mod.rs b/src/next/mod.rs
index aff318d..c9d4088 100644
--- a/src/next/mod.rs
+++ b/src/next/mod.rs
@@ -19,10 +19,10 @@
 
 use std::str::FromStr;
 
+use buffer::TokenBuffer;
 #[cfg(feature = "proc-macro")]
 use proc_macro;
 use proc_macro2::{self, Span};
-use syn::buffer::TokenBuffer;
 
 use self::parse::{Parse, ParseBuffer, Result};
 
@@ -52,11 +52,11 @@
 ///
 /// ```rust
 /// # extern crate proc_macro;
-/// # extern crate syn_error_experiment;
+/// # extern crate syn;
 /// #
 /// use proc_macro::TokenStream;
-/// use syn_error_experiment::parse_macro_input;
-/// use syn_error_experiment::parse::{Parse, ParseStream, Result};
+/// use syn::parse_macro_input;
+/// use syn::next::parse::{Parse, ParseStream, Result};
 ///
 /// struct MyMacroInput {
 ///     /* ... */
diff --git a/src/next/parse.rs b/src/next/parse.rs
index 5aa5505..447b8e1 100644
--- a/src/next/parse.rs
+++ b/src/next/parse.rs
@@ -6,8 +6,8 @@
 use std::mem;
 use std::ops::Deref;
 
+use buffer::Cursor;
 use proc_macro2::{Ident, Span};
-use syn::buffer::Cursor;
 
 use super::error;
 
diff --git a/src/next/token.rs b/src/next/token.rs
index d26f504..5b80a14 100644
--- a/src/next/token.rs
+++ b/src/next/token.rs
@@ -26,18 +26,6 @@
     pub trait Sealed {}
 }
 
-/// A type-macro that expands to the name of the Rust type representation of a
-/// given token.
-#[macro_export]
-#[cfg_attr(rustfmt, rustfmt_skip)]
-macro_rules! Token {
-    (struct) => { $crate::next::token::Struct };
-    (enum)   => { $crate::next::token::Enum };
-    (:)      => { $crate::next::token::Colon };
-    (,)      => { $crate::next::token::Comma };
-    (..)     => { $crate::next::token::Dot2 };
-}
-
 macro_rules! impl_token {
     ($token:tt $name:ident #[$doc:meta]) => {
         impl Token for $name {
diff --git a/src/op.rs b/src/op.rs
new file mode 100644
index 0000000..a5188d0
--- /dev/null
+++ b/src/op.rs
@@ -0,0 +1,224 @@
+// 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.
+
+ast_enum! {
+    /// A binary operator: `+`, `+=`, `&`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    #[cfg_attr(feature = "clone-impls", derive(Copy))]
+    pub enum BinOp {
+        /// The `+` operator (addition)
+        Add(Token![+]),
+        /// The `-` operator (subtraction)
+        Sub(Token![-]),
+        /// The `*` operator (multiplication)
+        Mul(Token![*]),
+        /// The `/` operator (division)
+        Div(Token![/]),
+        /// The `%` operator (modulus)
+        Rem(Token![%]),
+        /// The `&&` operator (logical and)
+        And(Token![&&]),
+        /// The `||` operator (logical or)
+        Or(Token![||]),
+        /// The `^` operator (bitwise xor)
+        BitXor(Token![^]),
+        /// The `&` operator (bitwise and)
+        BitAnd(Token![&]),
+        /// The `|` operator (bitwise or)
+        BitOr(Token![|]),
+        /// The `<<` operator (shift left)
+        Shl(Token![<<]),
+        /// The `>>` operator (shift right)
+        Shr(Token![>>]),
+        /// The `==` operator (equality)
+        Eq(Token![==]),
+        /// The `<` operator (less than)
+        Lt(Token![<]),
+        /// The `<=` operator (less than or equal to)
+        Le(Token![<=]),
+        /// The `!=` operator (not equal to)
+        Ne(Token![!=]),
+        /// The `>=` operator (greater than or equal to)
+        Ge(Token![>=]),
+        /// The `>` operator (greater than)
+        Gt(Token![>]),
+        /// The `+=` operator
+        AddEq(Token![+=]),
+        /// The `-=` operator
+        SubEq(Token![-=]),
+        /// The `*=` operator
+        MulEq(Token![*=]),
+        /// The `/=` operator
+        DivEq(Token![/=]),
+        /// The `%=` operator
+        RemEq(Token![%=]),
+        /// The `^=` operator
+        BitXorEq(Token![^=]),
+        /// The `&=` operator
+        BitAndEq(Token![&=]),
+        /// The `|=` operator
+        BitOrEq(Token![|=]),
+        /// The `<<=` operator
+        ShlEq(Token![<<=]),
+        /// The `>>=` operator
+        ShrEq(Token![>>=]),
+    }
+}
+
+ast_enum! {
+    /// A unary operator: `*`, `!`, `-`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    #[cfg_attr(feature = "clone-impls", derive(Copy))]
+    pub enum UnOp {
+        /// The `*` operator for dereferencing
+        Deref(Token![*]),
+        /// The `!` operator for logical inversion
+        Not(Token![!]),
+        /// The `-` operator for negation
+        Neg(Token![-]),
+    }
+}
+
+#[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 }
+        ));
+
+        #[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 }
+        ));
+    }
+
+    impl Synom for UnOp {
+        named!(parse -> Self, alt!(
+            punct!(*) => { UnOp::Deref }
+            |
+            punct!(!) => { UnOp::Not }
+            |
+            punct!(-) => { UnOp::Neg }
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("unary operator: `*`, `!`, or `-`")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::ToTokens;
+
+    impl ToTokens for BinOp {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                BinOp::Add(ref t) => t.to_tokens(tokens),
+                BinOp::Sub(ref t) => t.to_tokens(tokens),
+                BinOp::Mul(ref t) => t.to_tokens(tokens),
+                BinOp::Div(ref t) => t.to_tokens(tokens),
+                BinOp::Rem(ref t) => t.to_tokens(tokens),
+                BinOp::And(ref t) => t.to_tokens(tokens),
+                BinOp::Or(ref t) => t.to_tokens(tokens),
+                BinOp::BitXor(ref t) => t.to_tokens(tokens),
+                BinOp::BitAnd(ref t) => t.to_tokens(tokens),
+                BinOp::BitOr(ref t) => t.to_tokens(tokens),
+                BinOp::Shl(ref t) => t.to_tokens(tokens),
+                BinOp::Shr(ref t) => t.to_tokens(tokens),
+                BinOp::Eq(ref t) => t.to_tokens(tokens),
+                BinOp::Lt(ref t) => t.to_tokens(tokens),
+                BinOp::Le(ref t) => t.to_tokens(tokens),
+                BinOp::Ne(ref t) => t.to_tokens(tokens),
+                BinOp::Ge(ref t) => t.to_tokens(tokens),
+                BinOp::Gt(ref t) => t.to_tokens(tokens),
+                BinOp::AddEq(ref t) => t.to_tokens(tokens),
+                BinOp::SubEq(ref t) => t.to_tokens(tokens),
+                BinOp::MulEq(ref t) => t.to_tokens(tokens),
+                BinOp::DivEq(ref t) => t.to_tokens(tokens),
+                BinOp::RemEq(ref t) => t.to_tokens(tokens),
+                BinOp::BitXorEq(ref t) => t.to_tokens(tokens),
+                BinOp::BitAndEq(ref t) => t.to_tokens(tokens),
+                BinOp::BitOrEq(ref t) => t.to_tokens(tokens),
+                BinOp::ShlEq(ref t) => t.to_tokens(tokens),
+                BinOp::ShrEq(ref t) => t.to_tokens(tokens),
+            }
+        }
+    }
+
+    impl ToTokens for UnOp {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                UnOp::Deref(ref t) => t.to_tokens(tokens),
+                UnOp::Not(ref t) => t.to_tokens(tokens),
+                UnOp::Neg(ref t) => t.to_tokens(tokens),
+            }
+        }
+    }
+}
diff --git a/src/parse_quote.rs b/src/parse_quote.rs
new file mode 100644
index 0000000..ec8ef5a
--- /dev/null
+++ b/src/parse_quote.rs
@@ -0,0 +1,163 @@
+/// 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
+///
+/// The return type can be any syntax tree node that implements the [`Synom`]
+/// trait.
+///
+/// [`Synom`]: synom/trait.Synom.html
+///
+/// ```
+/// #[macro_use]
+/// extern crate syn;
+///
+/// #[macro_use]
+/// extern crate quote;
+///
+/// use syn::Stmt;
+///
+/// fn main() {
+///     let name = quote!(v);
+///     let ty = quote!(u8);
+///
+///     let stmt: Stmt = parse_quote! {
+///         let #name: #ty = Default::default();
+///     };
+///
+///     println!("{:#?}", stmt);
+/// }
+/// ```
+///
+/// *This macro is available if Syn is built with the `"parsing"` feature,
+/// although interpolation of syntax tree nodes into the quoted tokens is only
+/// supported if Syn is built with the `"printing"` feature as well.*
+///
+/// # Example
+///
+/// The following helper function adds a bound `T: HeapSize` to every type
+/// parameter `T` in the input generics.
+///
+/// ```
+/// # #[macro_use]
+/// # extern crate syn;
+/// #
+/// # #[macro_use]
+/// # extern crate quote;
+/// #
+/// # 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 {
+///         if let GenericParam::Type(ref mut type_param) = *param {
+///             type_param.bounds.push(parse_quote!(HeapSize));
+///         }
+///     }
+///     generics
+/// }
+/// #
+/// # fn main() {}
+/// ```
+///
+/// # Special cases
+///
+/// This macro can parse the following additional types as a special case even
+/// though they do not implement the `Synom` trait.
+///
+/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
+///   or inner like `#![...]`
+/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation
+///   `P` with optional trailing punctuation
+///
+/// [`Attribute`]: struct.Attribute.html
+/// [`Punctuated<T, P>`]: punctuated/struct.Punctuated.html
+///
+/// # Panics
+///
+/// Panics if the tokens fail to parse as the expected syntax tree type. The
+/// caller is responsible for ensuring that the input tokens are syntactically
+/// valid.
+#[macro_export]
+macro_rules! parse_quote {
+    ($($tt:tt)*) => {
+        $crate::parse_quote::parse($crate::parse_quote::From::from(quote!($($tt)*)))
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Can parse any type that implements Synom.
+
+use buffer::Cursor;
+use proc_macro2::TokenStream;
+use synom::{PResult, Parser, Synom};
+
+// Not public API.
+#[doc(hidden)]
+pub use std::convert::From;
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {
+    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),
+        },
+    }
+}
+
+// Not public API.
+#[doc(hidden)]
+pub trait ParseQuote: Sized {
+    fn parse(input: Cursor) -> PResult<Self>;
+    fn description() -> Option<&'static str>;
+}
+
+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()
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 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")
+    }
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+impl ParseQuote for Attribute {
+    named!(parse -> Self, alt!(
+        call!(Attribute::parse_outer)
+        |
+        call!(Attribute::parse_inner)
+    ));
+
+    fn description() -> Option<&'static str> {
+        Some("attribute")
+    }
+}
diff --git a/src/parsers.rs b/src/parsers.rs
new file mode 100644
index 0000000..400c0ca
--- /dev/null
+++ b/src/parsers.rs
@@ -0,0 +1,1428 @@
+// 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
new file mode 100644
index 0000000..a848944
--- /dev/null
+++ b/src/path.rs
@@ -0,0 +1,577 @@
+// 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 super::*;
+use punctuated::Punctuated;
+
+ast_struct! {
+    /// A path at which a named item is exported: `std::collections::HashMap`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Path {
+        pub leading_colon: Option<Token![::]>,
+        pub segments: Punctuated<PathSegment, Token![::]>,
+    }
+}
+
+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>,
+{
+    fn from(segment: T) -> Self {
+        let mut path = Path {
+            leading_colon: None,
+            segments: Punctuated::new(),
+        };
+        path.segments.push_value(segment.into());
+        path
+    }
+}
+
+ast_struct! {
+    /// A segment of a path together with any path arguments on that segment.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct PathSegment {
+        pub ident: Ident,
+        pub arguments: PathArguments,
+    }
+}
+
+impl<T> From<T> for PathSegment
+where
+    T: Into<Ident>,
+{
+    fn from(ident: T) -> Self {
+        PathSegment {
+            ident: ident.into(),
+            arguments: PathArguments::None,
+        }
+    }
+}
+
+ast_enum! {
+    /// Angle bracketed or parenthesized arguments of a path segment.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// ## Angle bracketed
+    ///
+    /// The `<'a, T>` in `std::slice::iter<'a, T>`.
+    ///
+    /// ## Parenthesized
+    ///
+    /// The `(A, B) -> C` in `Fn(A, B) -> C`.
+    pub enum PathArguments {
+        None,
+        /// The `<'a, T>` in `std::slice::iter<'a, T>`.
+        AngleBracketed(AngleBracketedGenericArguments),
+        /// The `(A, B) -> C` in `Fn(A, B) -> C`.
+        Parenthesized(ParenthesizedGenericArguments),
+    }
+}
+
+impl Default for PathArguments {
+    fn default() -> Self {
+        PathArguments::None
+    }
+}
+
+impl PathArguments {
+    pub fn is_empty(&self) -> bool {
+        match *self {
+            PathArguments::None => true,
+            PathArguments::AngleBracketed(ref bracketed) => bracketed.args.is_empty(),
+            PathArguments::Parenthesized(_) => false,
+        }
+    }
+}
+
+ast_enum! {
+    /// An individual generic argument, like `'a`, `T`, or `Item = T`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum GenericArgument {
+        /// A lifetime argument.
+        Lifetime(Lifetime),
+        /// A type argument.
+        Type(Type),
+        /// A binding (equality constraint) on an associated type: the `Item =
+        /// u8` in `Iterator<Item = u8>`.
+        Binding(Binding),
+        /// A const expression. Must be inside of a block.
+        ///
+        /// NOTE: Identity expressions are represented as Type arguments, as
+        /// they are indistinguishable syntactically.
+        Const(Expr),
+    }
+}
+
+ast_struct! {
+    /// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K,
+    /// V>`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct AngleBracketedGenericArguments {
+        pub colon2_token: Option<Token![::]>,
+        pub lt_token: Token![<],
+        pub args: Punctuated<GenericArgument, Token![,]>,
+        pub gt_token: Token![>],
+    }
+}
+
+ast_struct! {
+    /// A binding (equality constraint) on an associated type: `Item = u8`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Binding {
+        pub ident: Ident,
+        pub eq_token: Token![=],
+        pub ty: Type,
+    }
+}
+
+ast_struct! {
+    /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) ->
+    /// C`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct ParenthesizedGenericArguments {
+        pub paren_token: token::Paren,
+        /// `(A, B)`
+        pub inputs: Punctuated<Type, Token![,]>,
+        /// `C`
+        pub output: ReturnType,
+    }
+}
+
+ast_struct! {
+    /// The explicit Self type in a qualified path: the `T` in `<T as
+    /// Display>::fmt`.
+    ///
+    /// The actual path, including the trait and the associated item, is stored
+    /// separately. The `position` field represents the index of the associated
+    /// item qualified with this Self type.
+    ///
+    /// ```text
+    /// <Vec<T> as a::b::Trait>::AssociatedItem
+    ///  ^~~~~~    ~~~~~~~~~~~~~~^
+    ///  ty        position = 3
+    ///
+    /// <Vec<T>>::AssociatedItem
+    ///  ^~~~~~   ^
+    ///  ty       position = 0
+    /// ```
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct QSelf {
+        pub lt_token: Token![<],
+        pub ty: Box<Type>,
+        pub position: usize,
+        pub as_token: Option<Token![as]>,
+        pub gt_token: Token![>],
+    }
+}
+
+#[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)) }
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("generic argument")
+        }
+    }
+
+    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,
+            })
+        ));
+
+        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,
+            })
+        ));
+
+        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 {
+                    ident: ident,
+                    arguments: PathArguments::AngleBracketed(arguments),
+                })
+            )
+            |
+            mod_style_path_segment
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("path segment")
+        }
+    }
+
+    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,
+            })
+        ));
+
+        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,
+            })
+        ));
+    }
+
+    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)
+    ));
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::ToTokens;
+
+    impl ToTokens for Path {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.leading_colon.to_tokens(tokens);
+            self.segments.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for PathSegment {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+            self.arguments.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for PathArguments {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                PathArguments::None => {}
+                PathArguments::AngleBracketed(ref arguments) => {
+                    arguments.to_tokens(tokens);
+                }
+                PathArguments::Parenthesized(ref arguments) => {
+                    arguments.to_tokens(tokens);
+                }
+            }
+        }
+    }
+
+    impl ToTokens for GenericArgument {
+        #[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                GenericArgument::Lifetime(ref lt) => lt.to_tokens(tokens),
+                GenericArgument::Type(ref ty) => ty.to_tokens(tokens),
+                GenericArgument::Binding(ref tb) => tb.to_tokens(tokens),
+                GenericArgument::Const(ref e) => match *e {
+                    Expr::Lit(_) => e.to_tokens(tokens),
+
+                    // NOTE: We should probably support parsing blocks with only
+                    // expressions in them without the full feature for const
+                    // generics.
+                    #[cfg(feature = "full")]
+                    Expr::Block(_) => e.to_tokens(tokens),
+
+                    // ERROR CORRECTION: Add braces to make sure that the
+                    // generated code is valid.
+                    _ => token::Brace::default().surround(tokens, |tokens| {
+                        e.to_tokens(tokens);
+                    }),
+                },
+            }
+        }
+    }
+
+    impl ToTokens for AngleBracketedGenericArguments {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.colon2_token.to_tokens(tokens);
+            self.lt_token.to_tokens(tokens);
+
+            // Print lifetimes before types and consts, all before bindings,
+            // regardless of their order in self.args.
+            //
+            // TODO: ordering rules for const arguments vs type arguments have
+            // not been settled yet. https://github.com/rust-lang/rust/issues/44580
+            let mut trailing_or_empty = true;
+            for param in self.args.pairs() {
+                if let GenericArgument::Lifetime(_) = **param.value() {
+                    param.to_tokens(tokens);
+                    trailing_or_empty = param.punct().is_some();
+                }
+            }
+            for param in self.args.pairs() {
+                match **param.value() {
+                    GenericArgument::Type(_) | GenericArgument::Const(_) => {
+                        if !trailing_or_empty {
+                            <Token![,]>::default().to_tokens(tokens);
+                        }
+                        param.to_tokens(tokens);
+                        trailing_or_empty = param.punct().is_some();
+                    }
+                    GenericArgument::Lifetime(_) | GenericArgument::Binding(_) => {}
+                }
+            }
+            for param in self.args.pairs() {
+                if let GenericArgument::Binding(_) = **param.value() {
+                    if !trailing_or_empty {
+                        <Token![,]>::default().to_tokens(tokens);
+                        trailing_or_empty = true;
+                    }
+                    param.to_tokens(tokens);
+                }
+            }
+
+            self.gt_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for Binding {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.ident.to_tokens(tokens);
+            self.eq_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ParenthesizedGenericArguments {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.paren_token.surround(tokens, |tokens| {
+                self.inputs.to_tokens(tokens);
+            });
+            self.output.to_tokens(tokens);
+        }
+    }
+
+    impl<'a> ToTokens for PathTokens<'a> {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            let qself = match *self.0 {
+                Some(ref qself) => qself,
+                None => return self.1.to_tokens(tokens),
+            };
+            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
+            } else {
+                qself.position
+            };
+            let mut segments = self.1.segments.pairs();
+            if pos > 0 {
+                TokensOrDefault(&qself.as_token).to_tokens(tokens);
+                self.1.leading_colon.to_tokens(tokens);
+                for (i, segment) in segments.by_ref().take(pos).enumerate() {
+                    if i + 1 == pos {
+                        segment.value().to_tokens(tokens);
+                        qself.gt_token.to_tokens(tokens);
+                        segment.punct().to_tokens(tokens);
+                    } else {
+                        segment.to_tokens(tokens);
+                    }
+                }
+            } else {
+                qself.gt_token.to_tokens(tokens);
+                self.1.leading_colon.to_tokens(tokens);
+            }
+            for segment in segments {
+                segment.to_tokens(tokens);
+            }
+        }
+    }
+}
diff --git a/src/punctuated.rs b/src/punctuated.rs
new file mode 100644
index 0000000..b4a0b3f
--- /dev/null
+++ b/src/punctuated.rs
@@ -0,0 +1,807 @@
+// 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.
+
+//! A punctuated sequence of syntax tree nodes separated by punctuation.
+//!
+//! Lots of things in Rust are punctuated sequences.
+//!
+//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
+//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
+//! - The bounds on a generic parameter are `Punctuated<TypeParamBound, Token![+]>`.
+//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
+//!
+//! This module provides a common representation for these punctuated sequences
+//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
+//! syntax tree node + punctuation, where every node in the sequence is followed
+//! by punctuation except for possibly the final one.
+//!
+//! [`Punctuated<T, P>`]: struct.Punctuated.html
+//!
+//! ```text
+//! a_function_call(arg1, arg2, arg3);
+//!                 ^^^^^ ~~~~~ ^^^^
+//! ```
+
+#[cfg(feature = "extra-traits")]
+use std::fmt::{self, Debug};
+#[cfg(any(feature = "full", feature = "derive"))]
+use std::iter;
+use std::iter::FromIterator;
+use std::ops::{Index, IndexMut};
+use std::option;
+use std::slice;
+use std::vec;
+
+#[cfg(feature = "parsing")]
+use buffer::Cursor;
+#[cfg(feature = "parsing")]
+use parse_error;
+#[cfg(feature = "parsing")]
+use synom::{PResult, Synom};
+
+/// A punctuated sequence of syntax tree nodes of type `T` separated by
+/// punctuation of type `P`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
+#[cfg_attr(feature = "clone-impls", derive(Clone))]
+pub struct Punctuated<T, P> {
+    inner: Vec<(T, P)>,
+    last: Option<Box<T>>,
+}
+
+impl<T, P> Punctuated<T, P> {
+    /// Creates an empty punctuated sequence.
+    pub fn new() -> Punctuated<T, P> {
+        Punctuated {
+            inner: Vec::new(),
+            last: None,
+        }
+    }
+
+    /// Determines whether this punctuated sequence is empty, meaning it
+    /// contains no syntax tree nodes or punctuation.
+    pub fn is_empty(&self) -> bool {
+        self.inner.len() == 0 && self.last.is_none()
+    }
+
+    /// Returns the number of syntax tree nodes in this punctuated sequence.
+    ///
+    /// This is the number of nodes of type `T`, not counting the punctuation of
+    /// type `P`.
+    pub fn len(&self) -> usize {
+        self.inner.len() + if self.last.is_some() { 1 } else { 0 }
+    }
+
+    /// Borrows the first punctuated pair in this sequence.
+    pub fn first(&self) -> Option<Pair<&T, &P>> {
+        self.pairs().next()
+    }
+
+    /// Borrows the last punctuated pair in this sequence.
+    pub fn last(&self) -> Option<Pair<&T, &P>> {
+        if self.last.is_some() {
+            self.last.as_ref().map(|t| Pair::End(t.as_ref()))
+        } else {
+            self.inner
+                .last()
+                .map(|&(ref t, ref d)| Pair::Punctuated(t, d))
+        }
+    }
+
+    /// Mutably borrows the last punctuated pair in this sequence.
+    pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
+        if self.last.is_some() {
+            self.last.as_mut().map(|t| Pair::End(t.as_mut()))
+        } else {
+            self.inner
+                .last_mut()
+                .map(|&mut (ref mut t, ref mut d)| Pair::Punctuated(t, d))
+        }
+    }
+
+    /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
+    pub fn iter(&self) -> Iter<T> {
+        Iter {
+            inner: Box::new(PrivateIter {
+                inner: self.inner.iter(),
+                last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
+            }),
+        }
+    }
+
+    /// Returns an iterator over mutably borrowed syntax tree nodes of type
+    /// `&mut T`.
+    pub fn iter_mut(&mut self) -> IterMut<T> {
+        IterMut {
+            inner: Box::new(PrivateIterMut {
+                inner: self.inner.iter_mut(),
+                last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
+            }),
+        }
+    }
+
+    /// Returns an iterator over the contents of this sequence as borrowed
+    /// punctuated pairs.
+    pub fn pairs(&self) -> Pairs<T, P> {
+        Pairs {
+            inner: self.inner.iter(),
+            last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
+        }
+    }
+
+    /// Returns an iterator over the contents of this sequence as mutably
+    /// borrowed punctuated pairs.
+    pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
+        PairsMut {
+            inner: self.inner.iter_mut(),
+            last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
+        }
+    }
+
+    /// Returns an iterator over the contents of this sequence as owned
+    /// punctuated pairs.
+    pub fn into_pairs(self) -> IntoPairs<T, P> {
+        IntoPairs {
+            inner: self.inner.into_iter(),
+            last: self.last.map(|t| *t).into_iter(),
+        }
+    }
+
+    /// Appends a syntax tree node onto the end of this punctuated sequence. The
+    /// sequence must previously have a trailing punctuation.
+    ///
+    /// Use [`push`] instead if the punctuated sequence may or may not already
+    /// have trailing punctuation.
+    ///
+    /// [`push`]: #method.push
+    ///
+    /// # Panics
+    ///
+    /// Panics if the sequence does not already have a trailing punctuation when
+    /// this method is called.
+    pub fn push_value(&mut self, value: T) {
+        assert!(self.empty_or_trailing());
+        self.last = Some(Box::new(value));
+    }
+
+    /// Appends a trailing punctuation onto the end of this punctuated sequence.
+    /// The sequence must be non-empty and must not already have trailing
+    /// punctuation.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the sequence is empty or already has a trailing punctuation.
+    pub fn push_punct(&mut self, punctuation: P) {
+        assert!(self.last.is_some());
+        let last = self.last.take().unwrap();
+        self.inner.push((*last, punctuation));
+    }
+
+    /// Removes the last punctuated pair from this sequence, or `None` if the
+    /// sequence is empty.
+    pub fn pop(&mut self) -> Option<Pair<T, P>> {
+        if self.last.is_some() {
+            self.last.take().map(|t| Pair::End(*t))
+        } else {
+            self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d))
+        }
+    }
+
+    /// Determines whether this punctuated sequence ends with a trailing
+    /// punctuation.
+    pub fn trailing_punct(&self) -> bool {
+        self.last.is_none() && !self.is_empty()
+    }
+
+    /// Returns true if either this `Punctuated` is empty, or it has a trailing
+    /// punctuation.
+    ///
+    /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
+    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) {
+        if !self.empty_or_trailing() {
+            self.push_punct(Default::default());
+        }
+        self.push_value(value);
+    }
+
+    /// Inserts an element at position `index`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `index` is greater than the number of elements previously in
+    /// this punctuated sequence.
+    pub fn insert(&mut self, index: usize, value: T) {
+        assert!(index <= self.len());
+
+        if index == self.len() {
+            self.push(value);
+        } else {
+            self.inner.insert(index, (value, Default::default()));
+        }
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut list = f.debug_list();
+        for &(ref t, ref p) in &self.inner {
+            list.entry(t);
+            list.entry(p);
+        }
+        if let Some(ref last) = self.last {
+            list.entry(last);
+        }
+        list.finish()
+    }
+}
+
+impl<T, P> FromIterator<T> for Punctuated<T, P>
+where
+    P: Default,
+{
+    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
+        let mut ret = Punctuated::new();
+        ret.extend(i);
+        ret
+    }
+}
+
+impl<T, P> Extend<T> for Punctuated<T, P>
+where
+    P: Default,
+{
+    fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
+        for value in i {
+            self.push(value);
+        }
+    }
+}
+
+impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
+    fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
+        let mut ret = Punctuated::new();
+        ret.extend(i);
+        ret
+    }
+}
+
+impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
+    fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
+        assert!(self.empty_or_trailing());
+        let mut nomore = false;
+        for pair in i {
+            if nomore {
+                panic!("Punctuated extended with items after a Pair::End");
+            }
+            match pair {
+                Pair::Punctuated(a, b) => self.inner.push((a, b)),
+                Pair::End(a) => {
+                    self.last = Some(Box::new(a));
+                    nomore = true;
+                }
+            }
+        }
+    }
+}
+
+impl<T, P> IntoIterator for Punctuated<T, P> {
+    type Item = T;
+    type IntoIter = IntoIter<T, P>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        IntoIter {
+            inner: self.inner.into_iter(),
+            last: self.last.map(|t| *t).into_iter(),
+        }
+    }
+}
+
+impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
+    type Item = &'a T;
+    type IntoIter = Iter<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        Punctuated::iter(self)
+    }
+}
+
+impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
+    type Item = &'a mut T;
+    type IntoIter = IterMut<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        Punctuated::iter_mut(self)
+    }
+}
+
+impl<T, P> Default for Punctuated<T, P> {
+    fn default() -> Self {
+        Punctuated::new()
+    }
+}
+
+/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+pub struct Pairs<'a, T: 'a, P: 'a> {
+    inner: slice::Iter<'a, (T, P)>,
+    last: option::IntoIter<&'a T>,
+}
+
+impl<'a, T, P> Iterator for Pairs<'a, T, P> {
+    type Item = Pair<&'a T, &'a P>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner
+            .next()
+            .map(|&(ref t, ref p)| Pair::Punctuated(t, p))
+            .or_else(|| self.last.next().map(Pair::End))
+    }
+}
+
+impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
+    fn len(&self) -> usize {
+        self.inner.len() + self.last.len()
+    }
+}
+
+/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+pub struct PairsMut<'a, T: 'a, P: 'a> {
+    inner: slice::IterMut<'a, (T, P)>,
+    last: option::IntoIter<&'a mut T>,
+}
+
+impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
+    type Item = Pair<&'a mut T, &'a mut P>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner
+            .next()
+            .map(|&mut (ref mut t, ref mut p)| Pair::Punctuated(t, p))
+            .or_else(|| self.last.next().map(Pair::End))
+    }
+}
+
+impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
+    fn len(&self) -> usize {
+        self.inner.len() + self.last.len()
+    }
+}
+
+/// An iterator over owned pairs of type `Pair<T, P>`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+pub struct IntoPairs<T, P> {
+    inner: vec::IntoIter<(T, P)>,
+    last: option::IntoIter<T>,
+}
+
+impl<T, P> Iterator for IntoPairs<T, P> {
+    type Item = Pair<T, P>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner
+            .next()
+            .map(|(t, p)| Pair::Punctuated(t, p))
+            .or_else(|| self.last.next().map(Pair::End))
+    }
+}
+
+impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
+    fn len(&self) -> usize {
+        self.inner.len() + self.last.len()
+    }
+}
+
+/// An iterator over owned values of type `T`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+pub struct IntoIter<T, P> {
+    inner: vec::IntoIter<(T, P)>,
+    last: option::IntoIter<T>,
+}
+
+impl<T, P> Iterator for IntoIter<T, P> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner
+            .next()
+            .map(|pair| pair.0)
+            .or_else(|| self.last.next())
+    }
+}
+
+impl<T, P> ExactSizeIterator for IntoIter<T, P> {
+    fn len(&self) -> usize {
+        self.inner.len() + self.last.len()
+    }
+}
+
+/// An iterator over borrowed values of type `&T`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+pub struct Iter<'a, T: 'a> {
+    inner: Box<ExactSizeIterator<Item = &'a T> + 'a>,
+}
+
+struct PrivateIter<'a, T: 'a, P: 'a> {
+    inner: slice::Iter<'a, (T, P)>,
+    last: option::IntoIter<&'a T>,
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+impl<'a, T> Iter<'a, T> {
+    // Not public API.
+    #[doc(hidden)]
+    pub fn private_empty() -> Self {
+        Iter {
+            inner: Box::new(iter::empty()),
+        }
+    }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner.next()
+    }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
+}
+
+impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner
+            .next()
+            .map(|pair| &pair.0)
+            .or_else(|| self.last.next())
+    }
+}
+
+impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
+    fn len(&self) -> usize {
+        self.inner.len() + self.last.len()
+    }
+}
+
+/// An iterator over mutably borrowed values of type `&mut T`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+pub struct IterMut<'a, T: 'a> {
+    inner: Box<ExactSizeIterator<Item = &'a mut T> + 'a>,
+}
+
+struct PrivateIterMut<'a, T: 'a, P: 'a> {
+    inner: slice::IterMut<'a, (T, P)>,
+    last: option::IntoIter<&'a mut T>,
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+impl<'a, T> IterMut<'a, T> {
+    // Not public API.
+    #[doc(hidden)]
+    pub fn private_empty() -> Self {
+        IterMut {
+            inner: Box::new(iter::empty()),
+        }
+    }
+}
+
+impl<'a, T> Iterator for IterMut<'a, T> {
+    type Item = &'a mut T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner.next()
+    }
+}
+
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
+    fn len(&self) -> usize {
+        self.inner.len()
+    }
+}
+
+impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
+    type Item = &'a mut T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner
+            .next()
+            .map(|pair| &mut pair.0)
+            .or_else(|| self.last.next())
+    }
+}
+
+impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
+    fn len(&self) -> usize {
+        self.inner.len() + self.last.len()
+    }
+}
+
+/// A single syntax tree node of type `T` followed by its trailing punctuation
+/// of type `P` if any.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: index.html
+pub enum Pair<T, P> {
+    Punctuated(T, P),
+    End(T),
+}
+
+impl<T, P> Pair<T, P> {
+    /// Extracts the syntax tree node from this punctuated pair, discarding the
+    /// following punctuation.
+    pub fn into_value(self) -> T {
+        match self {
+            Pair::Punctuated(t, _) | Pair::End(t) => t,
+        }
+    }
+
+    /// Borrows the syntax tree node from this punctuated pair.
+    pub fn value(&self) -> &T {
+        match *self {
+            Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
+        }
+    }
+
+    /// Mutably borrows the syntax tree node from this punctuated pair.
+    pub fn value_mut(&mut self) -> &mut T {
+        match *self {
+            Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
+        }
+    }
+
+    /// Borrows the punctuation from this punctuated pair, unless this pair is
+    /// the final one and there is no trailing punctuation.
+    pub fn punct(&self) -> Option<&P> {
+        match *self {
+            Pair::Punctuated(_, ref d) => Some(d),
+            Pair::End(_) => None,
+        }
+    }
+
+    /// Creates a punctuated pair out of a syntax tree node and an optional
+    /// following punctuation.
+    pub fn new(t: T, d: Option<P>) -> Self {
+        match d {
+            Some(d) => Pair::Punctuated(t, d),
+            None => Pair::End(t),
+        }
+    }
+
+    /// Produces this punctuated pair as a tuple of syntax tree node and
+    /// optional following punctuation.
+    pub fn into_tuple(self) -> (T, Option<P>) {
+        match self {
+            Pair::Punctuated(t, d) => (t, Some(d)),
+            Pair::End(t) => (t, None),
+        }
+    }
+}
+
+impl<T, P> Index<usize> for Punctuated<T, P> {
+    type Output = T;
+
+    fn index(&self, index: usize) -> &Self::Output {
+        if index == self.len() - 1 {
+            match self.last {
+                Some(ref t) => t,
+                None => &self.inner[index].0,
+            }
+        } else {
+            &self.inner[index].0
+        }
+    }
+}
+
+impl<T, P> IndexMut<usize> for Punctuated<T, P> {
+    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+        if index == self.len() - 1 {
+            match self.last {
+                Some(ref mut t) => t,
+                None => &mut self.inner[index].0,
+            }
+        } else {
+            &mut self.inner[index].0
+        }
+    }
+}
+
+#[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::*;
+    use proc_macro2::TokenStream;
+    use quote::{ToTokens, TokenStreamExt};
+
+    impl<T, P> ToTokens for Punctuated<T, P>
+    where
+        T: ToTokens,
+        P: ToTokens,
+    {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            tokens.append_all(self.pairs())
+        }
+    }
+
+    impl<T, P> ToTokens for Pair<T, P>
+    where
+        T: ToTokens,
+        P: ToTokens,
+    {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                Pair::Punctuated(ref a, ref b) => {
+                    a.to_tokens(tokens);
+                    b.to_tokens(tokens);
+                }
+                Pair::End(ref a) => a.to_tokens(tokens),
+            }
+        }
+    }
+}
diff --git a/src/spanned.rs b/src/spanned.rs
new file mode 100644
index 0000000..6e2215d
--- /dev/null
+++ b/src/spanned.rs
@@ -0,0 +1,149 @@
+// 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.
+
+//! A trait that can provide the `Span` of the complete contents of a syntax
+//! tree node.
+//!
+//! *This module is available if Syn is built with both the `"parsing"` and
+//! `"printing"` features.*
+//!
+//! # Example
+//!
+//! Suppose in a procedural macro we have a [`Type`] that we want to assert
+//! implements the [`Sync`] trait. Maybe this is the type of one of the fields
+//! of a struct for which we are deriving a trait implementation, and we need to
+//! be able to pass a reference to one of those fields across threads.
+//!
+//! [`Type`]: ../enum.Type.html
+//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+//!
+//! If the field type does *not* implement `Sync` as required, we want the
+//! compiler to report an error pointing out exactly which type it was.
+//!
+//! The following macro code takes a variable `ty` of type `Type` and produces a
+//! 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;
+//! use proc_macro::TokenStream;
+//! use proc_macro2::Span;
+//!
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[proc_macro_derive(MyMacro)]
+//! # };
+//! pub fn my_macro(input: TokenStream) -> TokenStream {
+//!     # let ty = get_a_type();
+//!     /* ... */
+//!
+//!     let assert_sync = quote_spanned! {ty.span()=>
+//!         struct _AssertSync where #ty: Sync;
+//!     };
+//!
+//!     /* ... */
+//!     # input
+//! }
+//! #
+//! # fn get_a_type() -> Type {
+//! #     unimplemented!()
+//! # }
+//! #
+//! # fn main() {}
+//! ```
+//!
+//! By inserting this `assert_sync` fragment into the output code generated by
+//! our macro, the user's code will fail to compile if `ty` does not implement
+//! `Sync`. The errors they would see look like the following.
+//!
+//! ```text
+//! error[E0277]: the trait bound `*const i32: std::marker::Sync` is not satisfied
+//!   --> src/main.rs:10:21
+//!    |
+//! 10 |     bad_field: *const i32,
+//!    |                ^^^^^^^^^^ `*const i32` cannot be shared between threads safely
+//! ```
+//!
+//! In this technique, using the `Type`'s span for the error message makes the
+//! error appear in the correct place underlining the right type.
+
+use proc_macro2::{Span, TokenStream};
+use quote::ToTokens;
+
+/// A trait that can provide the `Span` of the complete contents of a syntax
+/// tree node.
+///
+/// This trait is automatically implemented for all types that implement
+/// [`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
+///
+/// See the [module documentation] for an example.
+///
+/// [module documentation]: index.html
+///
+/// *This trait is available if Syn is built with both the `"parsing"` and
+/// `"printing"` features.*
+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
+    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,
+{
+    #[cfg(procmacro2_semver_exempt)]
+    fn span(&self) -> Span {
+        let mut tokens = TokenStream::new();
+        self.to_tokens(&mut tokens);
+        let mut iter = tokens.into_iter();
+        let mut span = match iter.next() {
+            Some(tt) => tt.span(),
+            None => {
+                return Span::call_site();
+            }
+        };
+        for tt in iter {
+            if let Some(joined) = span.join(tt.span()) {
+                span = joined;
+            }
+        }
+        span
+    }
+
+    #[cfg(not(procmacro2_semver_exempt))]
+    fn span(&self) -> Span {
+        let mut tokens = TokenStream::new();
+        self.to_tokens(&mut tokens);
+        let mut iter = tokens.into_iter();
+
+        // We can't join spans without procmacro2_semver_exempt so just grab the
+        // first one.
+        match iter.next() {
+            Some(tt) => tt.span(),
+            None => Span::call_site(),
+        }
+    }
+}
diff --git a/src/synom.rs b/src/synom.rs
new file mode 100644
index 0000000..f3454eb
--- /dev/null
+++ b/src/synom.rs
@@ -0,0 +1,419 @@
+// 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
new file mode 100644
index 0000000..4ec3743
--- /dev/null
+++ b/src/token.rs
@@ -0,0 +1,955 @@
+// 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.
+
+//! Tokens representing Rust punctuation, keywords, and delimiters.
+//!
+//! The type names in this module can be difficult to keep straight, so we
+//! prefer to use the [`Token!`] macro instead. This is a type-macro that
+//! expands to the token type of the given token.
+//!
+//! [`Token!`]: ../macro.Token.html
+//!
+//! # Example
+//!
+//! The [`ItemStatic`] syntax tree node is defined like this.
+//!
+//! [`ItemStatic`]: ../struct.ItemStatic.html
+//!
+//! ```
+//! # #[macro_use]
+//! # extern crate syn;
+//! #
+//! # use syn::{Attribute, Visibility, Ident, Type, Expr};
+//! #
+//! pub struct ItemStatic {
+//!     pub attrs: Vec<Attribute>,
+//!     pub vis: Visibility,
+//!     pub static_token: Token![static],
+//!     pub mutability: Option<Token![mut]>,
+//!     pub ident: Ident,
+//!     pub colon_token: Token![:],
+//!     pub ty: Box<Type>,
+//!     pub eq_token: Token![=],
+//!     pub expr: Box<Expr>,
+//!     pub semi_token: Token![;],
+//! }
+//! #
+//! # fn main() {}
+//! ```
+//!
+//! # Parsing
+//!
+//! These tokens can be parsed using the [`Synom`] trait and the parser
+//! combinator macros [`punct!`], [`keyword!`], [`parens!`], [`braces!`], and
+//! [`brackets!`].
+//!
+//! [`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
+//!
+//! ```
+//! #[macro_use]
+//! extern crate syn;
+//!
+//! use syn::synom::Synom;
+//! use syn::{Attribute, Visibility, Ident, Type, Expr};
+//! #
+//! # struct ItemStatic;
+//! # use syn::ItemStatic as SynItemStatic;
+//!
+//! // 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,
+//!         })
+//!     ));
+//! }
+//! #
+//! # fn main() {}
+//! ```
+
+use proc_macro2::{Ident, Span};
+
+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/$len })*
+        $(token_delimiter! { #[$delimiter_doc] $delimiter pub struct $delimiter_name })*
+        $(token_keyword! { #[$keyword_doc] $keyword pub struct $keyword_name })*
+    )
+}
+
+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 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 ::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])
+            }
+        }
+    };
+}
+
+macro_rules! token_punct_parser {
+    ($s:tt pub struct $name:ident/$len:tt) => {
+        #[cfg(feature = "printing")]
+        impl ::quote::ToTokens for $name {
+            fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
+                printing::punct($s, &self.spans, tokens);
+            }
+        }
+
+        #[cfg(feature = "parsing")]
+        impl ::Synom for $name {
+            fn parse(tokens: $crate::buffer::Cursor) -> $crate::synom::PResult<$name> {
+                parsing::punct($s, tokens, $name::<[Span; $len]>)
+            }
+
+            fn description() -> Option<&'static str> {
+                Some(concat!("`", $s, "`"))
+            }
+        }
+    };
+}
+
+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: 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::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.span, tokens);
+            }
+        }
+
+        #[cfg(feature = "parsing")]
+        impl ::Synom for $name {
+            fn parse(tokens: $crate::buffer::Cursor) -> $crate::synom::PResult<$name> {
+                parsing::keyword($s, tokens, $name)
+            }
+
+            fn description() -> Option<&'static str> {
+                Some(concat!("`", $s, "`"))
+            }
+        }
+
+        impl From<Span> for $name {
+            fn from(span: Span) -> Self {
+                $name(span)
+            }
+        }
+    };
+}
+
+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: 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::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,
+            {
+            }
+        }
+
+        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.span, tokens, f);
+            }
+
+            #[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 From<Span> for $name {
+            fn from(span: Span) -> Self {
+                $name(span)
+            }
+        }
+    };
+}
+
+token_punct_def! {
+    /// `_`
+    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.spans[0]));
+    }
+}
+
+#[cfg(feature = "parsing")]
+impl ::Synom for Underscore {
+    fn parse(input: ::buffer::Cursor) -> ::synom::PResult<Underscore> {
+        match input.ident() {
+            Some((ident, rest)) => {
+                if ident == "_" {
+                    Ok((Underscore([ident.span()]), rest))
+                } else {
+                    ::parse_error()
+                }
+            }
+            None => parsing::punct("_", input, Underscore::<[Span; 1]>),
+        }
+    }
+
+    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.spans)
+    }
+}
+
+#[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.spans[0]);
+        tokens.append(token);
+    }
+}
+
+#[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(),
+        }
+    }
+
+    fn description() -> Option<&'static str> {
+        Some("`'`")
+    }
+}
+
+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      /// `-=`
+    }
+    delimiter: {
+        "{"           pub struct Brace        /// `{...}`
+        "["           pub struct Bracket      /// `[...]`
+        "("           pub struct Paren        /// `(...)`
+        " "           pub struct Group        /// None-delimited group
+    }
+    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`
+        "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`
+    }
+}
+
+/// A type-macro that expands to the name of the Rust type representation of a
+/// given token.
+///
+/// See the [token module] documentation for details and examples.
+///
+/// [token module]: token/index.html
+// Unfortunate duplication due to a rustdoc bug.
+// https://github.com/rust-lang/rust/issues/45939
+#[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 };
+    (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 };
+}
+
+/// 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, 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, 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, existential) => { call!($i, <$crate::token::Existential 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) };
+}
+
+macro_rules! ident_from_token {
+    ($token:ident) => {
+        impl From<Token![$token]> for Ident {
+            fn from(token: Token![$token]) -> Ident {
+                Ident::new(stringify!($token), token.span)
+            }
+        }
+    };
+}
+
+ident_from_token!(self);
+ident_from_token!(Self);
+ident_from_token!(super);
+ident_from_token!(crate);
+ident_from_token!(extern);
+
+// Not public API.
+#[doc(hidden)]
+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<Self> for [Span; 1] {
+    fn into_spans(self) -> Self {
+        self
+    }
+}
+
+impl IntoSpans<Self> for [Span; 2] {
+    fn into_spans(self) -> Self {
+        self
+    }
+}
+
+impl IntoSpans<Self> for [Span; 3] {
+    fn into_spans(self) -> Self {
+        self
+    }
+}
+
+#[cfg(feature = "parsing")]
+mod parsing {
+    use proc_macro2::{Delimiter, Spacing, Span};
+
+    use buffer::Cursor;
+    use parse_error;
+    use synom::PResult;
+
+    pub trait FromSpans: Sized {
+        fn from_spans(spans: &[Span]) -> Self;
+    }
+
+    impl FromSpans for [Span; 1] {
+        fn from_spans(spans: &[Span]) -> Self {
+            [spans[0]]
+        }
+    }
+
+    impl FromSpans for [Span; 2] {
+        fn from_spans(spans: &[Span]) -> Self {
+            [spans[0], spans[1]]
+        }
+    }
+
+    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(),
+                            }
+                        }
+                        *slot = op.span();
+                        tokens = rest;
+                    } else {
+                        return parse_error();
+                    }
+                }
+                _ => 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()
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
+    use quote::TokenStreamExt;
+
+    pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
+        assert_eq!(s.len(), spans.len());
+
+        let mut chars = s.chars();
+        let mut spans = spans.iter();
+        let ch = chars.next_back().unwrap();
+        let span = spans.next_back().unwrap();
+        for (ch, span) in chars.zip(spans) {
+            let mut op = Punct::new(ch, Spacing::Joint);
+            op.set_span(*span);
+            tokens.append(op);
+        }
+
+        let mut op = Punct::new(ch, Spacing::Alone);
+        op.set_span(*span);
+        tokens.append(op);
+    }
+
+    pub fn keyword(s: &str, span: &Span, tokens: &mut TokenStream) {
+        tokens.append(Ident::new(s, *span));
+    }
+
+    pub fn delim<F>(s: &str, span: &Span, tokens: &mut TokenStream, f: F)
+    where
+        F: FnOnce(&mut TokenStream),
+    {
+        let delim = match s {
+            "(" => Delimiter::Parenthesis,
+            "[" => Delimiter::Bracket,
+            "{" => Delimiter::Brace,
+            " " => Delimiter::None,
+            _ => panic!("unknown delimiter: {}", s),
+        };
+        let mut inner = TokenStream::new();
+        f(&mut inner);
+        let mut g = Group::new(delim, inner);
+        g.set_span(*span);
+        tokens.append(g);
+    }
+}
diff --git a/src/tt.rs b/src/tt.rs
new file mode 100644
index 0000000..bde82dc
--- /dev/null
+++ b/src/tt.rs
@@ -0,0 +1,170 @@
+// 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 = "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;
+
+        match (self.0, other.0) {
+            (&TokenTree::Group(ref g1), &TokenTree::Group(ref g2)) => {
+                match (g1.delimiter(), g2.delimiter()) {
+                    (Delimiter::Parenthesis, Delimiter::Parenthesis)
+                    | (Delimiter::Brace, Delimiter::Brace)
+                    | (Delimiter::Bracket, Delimiter::Bracket)
+                    | (Delimiter::None, Delimiter::None) => {}
+                    _ => return false,
+                }
+
+                let s1 = g1.stream().clone().into_iter();
+                let mut s2 = g2.stream().clone().into_iter();
+
+                for item1 in s1 {
+                    let item2 = match s2.next() {
+                        Some(item) => item,
+                        None => return false,
+                    };
+                    if TokenTreeHelper(&item1) != TokenTreeHelper(&item2) {
+                        return false;
+                    }
+                }
+                s2.next().is_none()
+            }
+            (&TokenTree::Punct(ref o1), &TokenTree::Punct(ref o2)) => {
+                o1.as_char() == o2.as_char() && match (o1.spacing(), o2.spacing()) {
+                    (Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
+                    _ => false,
+                }
+            }
+            (&TokenTree::Literal(ref l1), &TokenTree::Literal(ref l2)) => {
+                l1.to_string() == l2.to_string()
+            }
+            (&TokenTree::Ident(ref s1), &TokenTree::Ident(ref s2)) => s1 == s2,
+            _ => false,
+        }
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl<'a> Hash for TokenTreeHelper<'a> {
+    fn hash<H: Hasher>(&self, h: &mut H) {
+        use proc_macro2::Spacing;
+
+        match *self.0 {
+            TokenTree::Group(ref g) => {
+                0u8.hash(h);
+                match g.delimiter() {
+                    Delimiter::Parenthesis => 0u8.hash(h),
+                    Delimiter::Brace => 1u8.hash(h),
+                    Delimiter::Bracket => 2u8.hash(h),
+                    Delimiter::None => 3u8.hash(h),
+                }
+
+                for item in g.stream().clone() {
+                    TokenTreeHelper(&item).hash(h);
+                }
+                0xffu8.hash(h); // terminator w/ a variant we don't normally hash
+            }
+            TokenTree::Punct(ref op) => {
+                1u8.hash(h);
+                op.as_char().hash(h);
+                match op.spacing() {
+                    Spacing::Alone => 0u8.hash(h),
+                    Spacing::Joint => 1u8.hash(h),
+                }
+            }
+            TokenTree::Literal(ref lit) => (2u8, lit.to_string()).hash(h),
+            TokenTree::Ident(ref word) => (3u8, word).hash(h),
+        }
+    }
+}
+
+#[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<_>>();
+        let right = other.0.clone().into_iter().collect::<Vec<_>>();
+        if left.len() != right.len() {
+            return false;
+        }
+        for (a, b) in left.into_iter().zip(right) {
+            if TokenTreeHelper(&a) != TokenTreeHelper(&b) {
+                return false;
+            }
+        }
+        true
+    }
+}
+
+#[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<_>>();
+        tts.len().hash(state);
+        for tt in tts {
+            TokenTreeHelper(&tt).hash(state);
+        }
+    }
+}
diff --git a/src/ty.rs b/src/ty.rs
new file mode 100644
index 0000000..81e4df5
--- /dev/null
+++ b/src/ty.rs
@@ -0,0 +1,818 @@
+// 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 super::*;
+use proc_macro2::TokenStream;
+use punctuated::Punctuated;
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+#[cfg(feature = "extra-traits")]
+use tt::TokenStreamHelper;
+
+ast_enum_of_structs! {
+    /// The possible types that a Rust value could have.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    ///
+    /// # Syntax tree enum
+    ///
+    /// This type is a [syntax tree enum].
+    ///
+    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
+    pub enum Type {
+        /// A dynamically sized slice type: `[T]`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Slice(TypeSlice {
+            pub bracket_token: token::Bracket,
+            pub elem: Box<Type>,
+        }),
+
+        /// A fixed size array type: `[T; n]`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Array(TypeArray {
+            pub bracket_token: token::Bracket,
+            pub elem: Box<Type>,
+            pub semi_token: Token![;],
+            pub len: Expr,
+        }),
+
+        /// A raw pointer type: `*const T` or `*mut T`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Ptr(TypePtr {
+            pub star_token: Token![*],
+            pub const_token: Option<Token![const]>,
+            pub mutability: Option<Token![mut]>,
+            pub elem: Box<Type>,
+        }),
+
+        /// A reference type: `&'a T` or `&'a mut T`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Reference(TypeReference {
+            pub and_token: Token![&],
+            pub lifetime: Option<Lifetime>,
+            pub mutability: Option<Token![mut]>,
+            pub elem: Box<Type>,
+        }),
+
+        /// A bare function type: `fn(usize) -> bool`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub BareFn(TypeBareFn {
+            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![...]>,
+            pub output: ReturnType,
+        }),
+
+        /// The never type: `!`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Never(TypeNever {
+            pub bang_token: Token![!],
+        }),
+
+        /// A tuple type: `(A, B, C, String)`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Tuple(TypeTuple {
+            pub paren_token: token::Paren,
+            pub elems: Punctuated<Type, Token![,]>,
+        }),
+
+        /// A path like `std::slice::Iter`, optionally qualified with a
+        /// self-type as in `<Vec<T> as SomeTrait>::Associated`.
+        ///
+        /// Type arguments are stored in the Path itself.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Path(TypePath {
+            pub qself: Option<QSelf>,
+            pub path: Path,
+        }),
+
+        /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a
+        /// trait or a lifetime.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub TraitObject(TypeTraitObject {
+            pub dyn_token: Option<Token![dyn]>,
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+        }),
+
+        /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
+        /// a lifetime.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub ImplTrait(TypeImplTrait {
+            pub impl_token: Token![impl],
+            pub bounds: Punctuated<TypeParamBound, Token![+]>,
+        }),
+
+        /// A parenthesized type equivalent to the inner type.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Paren(TypeParen {
+            pub paren_token: token::Paren,
+            pub elem: Box<Type>,
+        }),
+
+        /// A type contained within invisible delimiters.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Group(TypeGroup {
+            pub group_token: token::Group,
+            pub elem: Box<Type>,
+        }),
+
+        /// Indication that a type should be inferred by the compiler: `_`.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Infer(TypeInfer {
+            pub underscore_token: Token![_],
+        }),
+
+        /// A macro in the type position.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Macro(TypeMacro {
+            pub mac: Macro,
+        }),
+
+        /// Tokens in type position not interpreted by Syn.
+        ///
+        /// *This type is available if Syn is built with the `"derive"` or
+        /// `"full"` feature.*
+        pub Verbatim(TypeVerbatim #manual_extra_traits {
+            pub tts: TokenStream,
+        }),
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Eq for TypeVerbatim {}
+
+#[cfg(feature = "extra-traits")]
+impl PartialEq for TypeVerbatim {
+    fn eq(&self, other: &Self) -> bool {
+        TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
+    }
+}
+
+#[cfg(feature = "extra-traits")]
+impl Hash for TypeVerbatim {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        TokenStreamHelper(&self.tts).hash(state);
+    }
+}
+
+ast_struct! {
+    /// The binary interface of a function: `extern "C"`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct Abi {
+        pub extern_token: Token![extern],
+        pub name: Option<LitStr>,
+    }
+}
+
+ast_struct! {
+    /// An argument in a function type: the `usize` in `fn(usize) -> bool`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub struct BareFnArg {
+        pub name: Option<(BareFnArgName, Token![:])>,
+        pub ty: Type,
+    }
+}
+
+ast_enum! {
+    /// Name of an argument in a function type: the `n` in `fn(n: usize)`.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum BareFnArgName {
+        /// Argument given a name.
+        Named(Ident),
+        /// Argument not given a name, matched with `_`.
+        Wild(Token![_]),
+    }
+}
+
+ast_enum! {
+    /// Return type of a function signature.
+    ///
+    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// feature.*
+    pub enum ReturnType {
+        /// Return type is not specified.
+        ///
+        /// Functions default to `()` and closures default to type inference.
+        Default,
+        /// A particular type is returned.
+        Type(Token![->], Box<Type>),
+    }
+}
+
+#[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));
+
+        fn description() -> Option<&'static str> {
+            Some("type")
+        }
+    }
+
+    impl Type {
+        /// In some positions, types may not contain the `+` character, to
+        /// disambiguate them. For example in the expression `1 as T`, T may not
+        /// 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")
+        }
+    }
+
+    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 {
+                    elem: Box::new(elem),
+                    len: len,
+                    bracket_token: brackets,
+                    semi_token: semi,
+                }
+            }
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("array type")
+        }
+    }
+
+    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),
+            })
+        ));
+
+        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,
+                mutability: mutability,
+                elem: Box::new(target),
+                and_token: amp,
+            })
+        ));
+
+        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,
+            })
+        ));
+
+        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,
+            })
+        ));
+
+        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 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 }
+        ));
+    }
+
+    impl Synom for ReturnType {
+        named!(parse -> Self, call!(Self::parse, true));
+
+        fn description() -> Option<&'static str> {
+            Some("return type")
+        }
+    }
+
+    impl Synom for TypeTraitObject {
+        named!(parse -> Self, call!(Self::parse, true));
+
+        fn description() -> Option<&'static str> {
+            Some("trait object type")
+        }
+    }
+
+    fn at_least_one_type(bounds: &Punctuated<TypeParamBound, Token![+]>) -> bool {
+        for bound in bounds {
+            if let TypeParamBound::Trait(_) = *bound {
+                return true;
+            }
+        }
+        false
+    }
+
+    impl TypeTraitObject {
+        named!(pub without_plus -> Self, call!(Self::parse, 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| {
+                    let mut bounds = Punctuated::new();
+                    bounds.push_value(x);
+                    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),
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("type surrounded by invisible delimiters")
+        }
+    }
+
+    impl Synom for TypeParen {
+        named!(parse -> Self, call!(Self::parse, false));
+
+        fn description() -> Option<&'static str> {
+            Some("parenthesized type")
+        }
+    }
+
+    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),
+            })
+        ));
+    }
+
+    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 Synom for Abi {
+        named!(parse -> Self, do_parse!(
+            extern_: keyword!(extern) >>
+            name: option!(syn!(LitStr)) >>
+            (Abi {
+                extern_token: extern_,
+                name: name,
+            })
+        ));
+
+        fn description() -> Option<&'static str> {
+            Some("`extern` ABI qualifier")
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+    use super::*;
+    use proc_macro2::TokenStream;
+    use quote::ToTokens;
+
+    impl ToTokens for TypeSlice {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.bracket_token.surround(tokens, |tokens| {
+                self.elem.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for TypeArray {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.bracket_token.surround(tokens, |tokens| {
+                self.elem.to_tokens(tokens);
+                self.semi_token.to_tokens(tokens);
+                self.len.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for TypePtr {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.star_token.to_tokens(tokens);
+            match self.mutability {
+                Some(ref tok) => tok.to_tokens(tokens),
+                None => {
+                    TokensOrDefault(&self.const_token).to_tokens(tokens);
+                }
+            }
+            self.elem.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeReference {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.and_token.to_tokens(tokens);
+            self.lifetime.to_tokens(tokens);
+            self.mutability.to_tokens(tokens);
+            self.elem.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeBareFn {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.lifetimes.to_tokens(tokens);
+            self.unsafety.to_tokens(tokens);
+            self.abi.to_tokens(tokens);
+            self.fn_token.to_tokens(tokens);
+            self.paren_token.surround(tokens, |tokens| {
+                self.inputs.to_tokens(tokens);
+                if let Some(ref variadic) = self.variadic {
+                    if !self.inputs.empty_or_trailing() {
+                        let span = variadic.spans[0];
+                        Token![,](span).to_tokens(tokens);
+                    }
+                    variadic.to_tokens(tokens);
+                }
+            });
+            self.output.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeNever {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.bang_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeTuple {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.paren_token.surround(tokens, |tokens| {
+                self.elems.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for TypePath {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            PathTokens(&self.qself, &self.path).to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeTraitObject {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.dyn_token.to_tokens(tokens);
+            self.bounds.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeImplTrait {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.impl_token.to_tokens(tokens);
+            self.bounds.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeGroup {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.group_token.surround(tokens, |tokens| {
+                self.elem.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for TypeParen {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.paren_token.surround(tokens, |tokens| {
+                self.elem.to_tokens(tokens);
+            });
+        }
+    }
+
+    impl ToTokens for TypeInfer {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.underscore_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeMacro {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.mac.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for TypeVerbatim {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.tts.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ReturnType {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                ReturnType::Default => {}
+                ReturnType::Type(ref arrow, ref ty) => {
+                    arrow.to_tokens(tokens);
+                    ty.to_tokens(tokens);
+                }
+            }
+        }
+    }
+
+    impl ToTokens for BareFnArg {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            if let Some((ref name, ref colon)) = self.name {
+                name.to_tokens(tokens);
+                colon.to_tokens(tokens);
+            }
+            self.ty.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for BareFnArgName {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            match *self {
+                BareFnArgName::Named(ref t) => t.to_tokens(tokens),
+                BareFnArgName::Wild(ref t) => t.to_tokens(tokens),
+            }
+        }
+    }
+
+    impl ToTokens for Abi {
+        fn to_tokens(&self, tokens: &mut TokenStream) {
+            self.extern_token.to_tokens(tokens);
+            self.name.to_tokens(tokens);
+        }
+    }
+}
diff --git a/src/verbatim.rs b/src/verbatim.rs
new file mode 100644
index 0000000..35145d5
--- /dev/null
+++ b/src/verbatim.rs
@@ -0,0 +1,22 @@
+use std::ops::Range;
+
+use buffer::Cursor;
+use proc_macro2::TokenStream;
+use synom::PResult;
+
+#[allow(dead_code)]
+pub fn grab_cursor(cursor: Cursor) -> PResult<Cursor> {
+    Ok((cursor, cursor))
+}
+
+#[allow(dead_code)]
+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/clone.sh b/tests/clone.sh
new file mode 100755
index 0000000..48d9739
--- /dev/null
+++ b/tests/clone.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+REMOTE=rust
+REPO=https://github.com/rust-lang/rust
+REV=63d66494aff57411bfec1dd2a3a5f1af900feab6
+
+set -euo pipefail
+cd "$(dirname "${BASH_SOURCE[0]}")"
+mkdir -p rust
+cd rust
+
+git init
+
+if git remote | grep --fixed-strings --line-regexp --quiet "$REMOTE"; then
+    git remote set-url "$REMOTE" "$REPO"
+else
+    git remote add "$REMOTE" "$REPO"
+fi
+
+if ! git cat-file -t "$REV" >/dev/null 2>&1; then
+    git fetch "$REMOTE" master
+fi
+
+git checkout "$REV"
diff --git a/tests/common/eq.rs b/tests/common/eq.rs
new file mode 100644
index 0000000..b229890
--- /dev/null
+++ b/tests/common/eq.rs
@@ -0,0 +1,456 @@
+extern crate rustc_data_structures;
+extern crate rustc_target;
+extern crate syntax;
+extern crate syntax_pos;
+
+use std::mem;
+
+use self::rustc_data_structures::sync::Lrc;
+use self::rustc_data_structures::thin_vec::ThinVec;
+use self::rustc_target::abi::FloatTy;
+use self::rustc_target::spec::abi::Abi;
+use self::syntax::ast::{
+    AngleBracketedArgs, AnonConst, Arg, Arm, AsmDialect, AttrId, AttrStyle, Attribute, BareFnTy,
+    BinOpKind, BindingMode, Block, BlockCheckMode, CaptureBy, Constness, Crate, CrateSugar,
+    Defaultness, EnumDef, Expr, ExprKind, Field, FieldPat, FnDecl, FnHeader, ForeignItem,
+    ForeignItemKind, ForeignMod, FunctionRetTy, GenericArg, GenericArgs, GenericBound,
+    GenericParam, GenericParamKind, Generics, GlobalAsm, Ident, ImplItem, ImplItemKind,
+    ImplPolarity, InlineAsm, InlineAsmOutput, IntTy, IsAsync, IsAuto, Item, ItemKind, Label,
+    Lifetime, LitIntType, LitKind, Local, MacDelimiter, MacStmtStyle, Mac_, MacroDef, MethodSig,
+    Mod, Movability, MutTy, Mutability, NodeId, ParenthesisedArgs, Pat, PatKind, Path, PathSegment,
+    PolyTraitRef, QSelf, RangeEnd, RangeLimits, RangeSyntax, Stmt, StmtKind, StrStyle, StructField,
+    TraitBoundModifier, TraitItem, TraitItemKind, TraitObjectSyntax, TraitRef, Ty, TyKind,
+    TypeBinding, UintTy, UnOp, UnsafeSource, Unsafety, UseTree, UseTreeKind, VariantData, Variant_,
+    VisibilityKind, WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate,
+    WhereRegionPredicate,
+};
+use self::syntax::parse::lexer::comments;
+use self::syntax::parse::token::{DelimToken, Lit, Token};
+use self::syntax::ptr::P;
+use self::syntax::source_map::Spanned;
+use self::syntax::symbol::Symbol;
+use self::syntax::tokenstream::{Delimited, ThinTokenStream, TokenStream, TokenTree};
+use self::syntax_pos::{Span, SyntaxContext, DUMMY_SP};
+
+pub trait SpanlessEq {
+    fn eq(&self, other: &Self) -> bool;
+}
+
+impl<T: SpanlessEq> SpanlessEq for P<T> {
+    fn eq(&self, other: &Self) -> bool {
+        SpanlessEq::eq(&**self, &**other)
+    }
+}
+
+impl<T: SpanlessEq> SpanlessEq for Lrc<T> {
+    fn eq(&self, other: &Self) -> bool {
+        SpanlessEq::eq(&**self, &**other)
+    }
+}
+
+impl<T: SpanlessEq> SpanlessEq for Option<T> {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            (None, None) => true,
+            (Some(this), Some(other)) => SpanlessEq::eq(this, other),
+            _ => false,
+        }
+    }
+}
+
+impl<T: SpanlessEq> SpanlessEq for Vec<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.len() == other.len() && self.iter().zip(other).all(|(a, b)| SpanlessEq::eq(a, b))
+    }
+}
+
+impl<T: SpanlessEq> SpanlessEq for ThinVec<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.len() == other.len() && self
+            .iter()
+            .zip(other.iter())
+            .all(|(a, b)| SpanlessEq::eq(a, b))
+    }
+}
+
+impl<T: SpanlessEq> SpanlessEq for Spanned<T> {
+    fn eq(&self, other: &Self) -> bool {
+        SpanlessEq::eq(&self.node, &other.node)
+    }
+}
+
+impl<A: SpanlessEq, B: SpanlessEq> SpanlessEq for (A, B) {
+    fn eq(&self, other: &Self) -> bool {
+        SpanlessEq::eq(&self.0, &other.0) && SpanlessEq::eq(&self.1, &other.1)
+    }
+}
+
+impl<A: SpanlessEq, B: SpanlessEq, C: SpanlessEq> SpanlessEq for (A, B, C) {
+    fn eq(&self, other: &Self) -> bool {
+        SpanlessEq::eq(&self.0, &other.0)
+            && SpanlessEq::eq(&self.1, &other.1)
+            && SpanlessEq::eq(&self.2, &other.2)
+    }
+}
+
+macro_rules! spanless_eq_true {
+    ($name:ident) => {
+        impl SpanlessEq for $name {
+            fn eq(&self, _other: &Self) -> bool {
+                true
+            }
+        }
+    };
+}
+
+spanless_eq_true!(Span);
+spanless_eq_true!(AttrId);
+spanless_eq_true!(NodeId);
+spanless_eq_true!(SyntaxContext);
+
+macro_rules! spanless_eq_partial_eq {
+    ($name:ident) => {
+        impl SpanlessEq for $name {
+            fn eq(&self, other: &Self) -> bool {
+                PartialEq::eq(self, other)
+            }
+        }
+    };
+}
+
+spanless_eq_partial_eq!(bool);
+spanless_eq_partial_eq!(u8);
+spanless_eq_partial_eq!(u16);
+spanless_eq_partial_eq!(u128);
+spanless_eq_partial_eq!(usize);
+spanless_eq_partial_eq!(char);
+spanless_eq_partial_eq!(Symbol);
+spanless_eq_partial_eq!(Abi);
+spanless_eq_partial_eq!(DelimToken);
+
+macro_rules! spanless_eq_struct {
+    {
+        $name:ident;
+        $([$field:ident $other:ident])*
+        $(![$ignore:ident])*
+    } => {
+        impl SpanlessEq for $name {
+            fn eq(&self, other: &Self) -> bool {
+                let $name { $($field,)* $($ignore: _,)* } = self;
+                let $name { $($field: $other,)* $($ignore: _,)* } = other;
+                $(SpanlessEq::eq($field, $other))&&*
+            }
+        }
+    };
+
+    {
+        $name:ident;
+        $([$field:ident $other:ident])*
+        $next:ident
+        $($rest:ident)*
+        $(!$ignore:ident)*
+    } => {
+        spanless_eq_struct! {
+            $name;
+            $([$field $other])*
+            [$next other]
+            $($rest)*
+            $(!$ignore)*
+        }
+    };
+
+    {
+        $name:ident;
+        $([$field:ident $other:ident])*
+        $(![$ignore:ident])*
+        !$next:ident
+        $(!$rest:ident)*
+    } => {
+        spanless_eq_struct! {
+            $name;
+            $([$field $other])*
+            $(![$ignore])*
+            ![$next]
+            $(!$rest)*
+        }
+    };
+}
+
+macro_rules! spanless_eq_enum {
+    {
+        $name:ident;
+        $([$variant:ident $([$field:tt $this:ident $other:ident])*])*
+    } => {
+        impl SpanlessEq for $name {
+            fn eq(&self, other: &Self) -> bool {
+                match self {
+                    $(
+                        $name::$variant { .. } => {}
+                    )*
+                }
+                match (self, other) {
+                    $(
+                        (
+                            $name::$variant { $($field: $this),* },
+                            $name::$variant { $($field: $other),* },
+                        ) => {
+                            true $(&& SpanlessEq::eq($this, $other))*
+                        }
+                    )*
+                    _ => false,
+                }
+            }
+        }
+    };
+
+    {
+        $name:ident;
+        $([$variant:ident $($fields:tt)*])*
+        $next:ident [$($named:tt)*] ( $i:tt $($field:tt)* )
+        $($rest:tt)*
+    } => {
+        spanless_eq_enum! {
+            $name;
+            $([$variant $($fields)*])*
+            $next [$($named)* [$i this other]] ( $($field)* )
+            $($rest)*
+        }
+    };
+
+    {
+        $name:ident;
+        $([$variant:ident $($fields:tt)*])*
+        $next:ident [$($named:tt)*] ()
+        $($rest:tt)*
+    } => {
+        spanless_eq_enum! {
+            $name;
+            $([$variant $($fields)*])*
+            [$next $($named)*]
+            $($rest)*
+        }
+    };
+
+    {
+        $name:ident;
+        $([$variant:ident $($fields:tt)*])*
+        $next:ident ( $($field:tt)* )
+        $($rest:tt)*
+    } => {
+        spanless_eq_enum! {
+            $name;
+            $([$variant $($fields)*])*
+            $next [] ( $($field)* )
+            $($rest)*
+        }
+    };
+
+    {
+        $name:ident;
+        $([$variant:ident $($fields:tt)*])*
+        $next:ident
+        $($rest:tt)*
+    } => {
+        spanless_eq_enum! {
+            $name;
+            $([$variant $($fields)*])*
+            [$next]
+            $($rest)*
+        }
+    };
+}
+
+spanless_eq_struct!(AngleBracketedArgs; span args bindings);
+spanless_eq_struct!(AnonConst; id value);
+spanless_eq_struct!(Arg; ty pat id);
+spanless_eq_struct!(Arm; attrs pats guard body);
+spanless_eq_struct!(Attribute; id style path tokens span !is_sugared_doc);
+spanless_eq_struct!(BareFnTy; unsafety abi generic_params decl);
+spanless_eq_struct!(Block; stmts id rules span recovered);
+spanless_eq_struct!(Crate; module attrs span);
+spanless_eq_struct!(Delimited; delim tts);
+spanless_eq_struct!(EnumDef; variants);
+spanless_eq_struct!(Expr; id node span attrs);
+spanless_eq_struct!(Field; ident expr span is_shorthand attrs);
+spanless_eq_struct!(FieldPat; ident pat is_shorthand attrs);
+spanless_eq_struct!(FnDecl; inputs output variadic);
+spanless_eq_struct!(FnHeader; unsafety asyncness constness abi);
+spanless_eq_struct!(ForeignItem; ident attrs node id span vis);
+spanless_eq_struct!(ForeignMod; abi items);
+spanless_eq_struct!(GenericParam; id ident attrs bounds kind);
+spanless_eq_struct!(Generics; params where_clause span);
+spanless_eq_struct!(GlobalAsm; asm ctxt);
+spanless_eq_struct!(ImplItem; id ident vis defaultness attrs generics node span !tokens);
+spanless_eq_struct!(InlineAsm; asm asm_str_style outputs inputs clobbers volatile alignstack dialect ctxt);
+spanless_eq_struct!(InlineAsmOutput; constraint expr is_rw is_indirect);
+spanless_eq_struct!(Item; ident attrs id node vis span !tokens);
+spanless_eq_struct!(Label; ident);
+spanless_eq_struct!(Lifetime; id ident);
+spanless_eq_struct!(Local; pat ty init id span attrs);
+spanless_eq_struct!(Mac_; path delim tts);
+spanless_eq_struct!(MacroDef; tokens legacy);
+spanless_eq_struct!(MethodSig; header decl);
+spanless_eq_struct!(Mod; inner items);
+spanless_eq_struct!(MutTy; ty mutbl);
+spanless_eq_struct!(ParenthesisedArgs; span inputs output);
+spanless_eq_struct!(Pat; id node span);
+spanless_eq_struct!(Path; span segments);
+spanless_eq_struct!(PathSegment; ident args);
+spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span);
+spanless_eq_struct!(QSelf; ty path_span position);
+spanless_eq_struct!(Stmt; id node span);
+spanless_eq_struct!(StructField; span ident vis id ty attrs);
+spanless_eq_struct!(TraitItem; id ident attrs generics node span !tokens);
+spanless_eq_struct!(TraitRef; path ref_id);
+spanless_eq_struct!(Ty; id node span);
+spanless_eq_struct!(TypeBinding; id ident ty span);
+spanless_eq_struct!(UseTree; prefix kind span);
+spanless_eq_struct!(Variant_; ident attrs data disr_expr);
+spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
+spanless_eq_struct!(WhereClause; id predicates span);
+spanless_eq_struct!(WhereEqPredicate; id span lhs_ty rhs_ty);
+spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds);
+spanless_eq_enum!(AsmDialect; Att Intel);
+spanless_eq_enum!(AttrStyle; Outer Inner);
+spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt);
+spanless_eq_enum!(BindingMode; ByRef(0) ByValue(0));
+spanless_eq_enum!(BlockCheckMode; Default Unsafe(0));
+spanless_eq_enum!(CaptureBy; Value Ref);
+spanless_eq_enum!(Constness; Const NotConst);
+spanless_eq_enum!(CrateSugar; PubCrate JustCrate);
+spanless_eq_enum!(Defaultness; Default Final);
+spanless_eq_enum!(FloatTy; F32 F64);
+spanless_eq_enum!(ForeignItemKind; Fn(0 1) Static(0 1) Ty Macro(0));
+spanless_eq_enum!(FunctionRetTy; Default(0) Ty(0));
+spanless_eq_enum!(GenericArg; Lifetime(0) Type(0));
+spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0));
+spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0));
+spanless_eq_enum!(GenericParamKind; Lifetime Type(default));
+spanless_eq_enum!(ImplItemKind; Const(0 1) Method(0 1) Type(0) Existential(0) Macro(0));
+spanless_eq_enum!(ImplPolarity; Positive Negative);
+spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128);
+spanless_eq_enum!(IsAsync; Async(closure_id return_impl_trait_id) NotAsync);
+spanless_eq_enum!(IsAuto; Yes No);
+spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
+spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
+spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
+spanless_eq_enum!(Movability; Static Movable);
+spanless_eq_enum!(Mutability; Mutable Immutable);
+spanless_eq_enum!(RangeEnd; Included(0) Excluded);
+spanless_eq_enum!(RangeLimits; HalfOpen Closed);
+spanless_eq_enum!(StmtKind; Local(0) Item(0) Expr(0) Semi(0) Mac(0));
+spanless_eq_enum!(StrStyle; Cooked Raw(0));
+spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1));
+spanless_eq_enum!(TraitBoundModifier; None Maybe);
+spanless_eq_enum!(TraitItemKind; Const(0 1) Method(0 1) Type(0 1) Macro(0));
+spanless_eq_enum!(TraitObjectSyntax; Dyn None);
+spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
+spanless_eq_enum!(UnOp; Deref Not Neg);
+spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
+spanless_eq_enum!(Unsafety; Unsafe Normal);
+spanless_eq_enum!(UseTreeKind; Simple(0 1 2) Nested(0) Glob);
+spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
+spanless_eq_enum!(VisibilityKind; Public Crate(0) Restricted(path id) Inherited);
+spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
+spanless_eq_enum!(ExprKind; Box(0) ObsoleteInPlace(0 1) Array(0) Call(0 1)
+    MethodCall(0 1) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1)
+    If(0 1 2) IfLet(0 1 2 3) While(0 1 2) WhileLet(0 1 2 3) ForLoop(0 1 2 3)
+    Loop(0 1) Match(0 1) Closure(0 1 2 3 4 5) Block(0 1) Async(0 1 2) TryBlock(0)
+    Assign(0 1) AssignOp(0 1 2) Field(0 1) Index(0 1) Range(0 1 2) Path(0 1)
+    AddrOf(0 1) Break(0 1) Continue(0) Ret(0) InlineAsm(0) Mac(0) Struct(0 1 2)
+    Repeat(0 1) Paren(0) Try(0) Yield(0));
+spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1)
+    Fn(0 1 2 3) Mod(0) ForeignMod(0) GlobalAsm(0) Ty(0 1) Existential(0 1)
+    Enum(0 1) Struct(0 1) Union(0 1) Trait(0 1 2 3 4) TraitAlias(0 1)
+    Impl(0 1 2 3 4 5 6) Mac(0) MacroDef(0));
+spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0) Byte(0) Char(0) Int(0 1)
+    Float(0 1) FloatUnsuffixed(0) Bool(0));
+spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2) TupleStruct(0 1 2)
+    Path(0 1) Tuple(0 1) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0 1 2)
+    Paren(0) Mac(0));
+spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Rptr(0 1) BareFn(0) Never
+    Tup(0) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer
+    ImplicitSelf Mac(0) Err);
+
+impl SpanlessEq for Ident {
+    fn eq(&self, other: &Self) -> bool {
+        self.as_str() == other.as_str()
+    }
+}
+
+// Give up on comparing literals inside of macros because there are so many
+// equivalent representations of the same literal; they are tested elsewhere
+impl SpanlessEq for Lit {
+    fn eq(&self, other: &Self) -> bool {
+        mem::discriminant(self) == mem::discriminant(other)
+    }
+}
+
+impl SpanlessEq for RangeSyntax {
+    fn eq(&self, _other: &Self) -> bool {
+        match self {
+            RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true,
+        }
+    }
+}
+
+impl SpanlessEq for Token {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            (Token::Literal(this, _), Token::Literal(other, _)) => SpanlessEq::eq(this, other),
+            (Token::DotDotEq, _) | (Token::DotDotDot, _) => match other {
+                Token::DotDotEq | Token::DotDotDot => true,
+                _ => false,
+            },
+            _ => self == other,
+        }
+    }
+}
+
+impl SpanlessEq for TokenStream {
+    fn eq(&self, other: &Self) -> bool {
+        SpanlessEq::eq(&expand_tts(self), &expand_tts(other))
+    }
+}
+
+impl SpanlessEq for ThinTokenStream {
+    fn eq(&self, other: &Self) -> bool {
+        SpanlessEq::eq(
+            &TokenStream::from(self.clone()),
+            &TokenStream::from(other.clone()),
+        )
+    }
+}
+
+fn expand_tts(tts: &TokenStream) -> Vec<TokenTree> {
+    let mut tokens = Vec::new();
+    for tt in tts.clone().into_trees() {
+        let c = match tt {
+            TokenTree::Token(_, Token::DocComment(c)) => c,
+            _ => {
+                tokens.push(tt);
+                continue;
+            }
+        };
+        let contents = comments::strip_doc_comment_decoration(&c.as_str());
+        let style = comments::doc_comment_style(&c.as_str());
+        tokens.push(TokenTree::Token(DUMMY_SP, Token::Pound));
+        if style == AttrStyle::Inner {
+            tokens.push(TokenTree::Token(DUMMY_SP, Token::Not));
+        }
+        let lit = Lit::Str_(Symbol::intern(&contents));
+        let mut tts = vec![
+            TokenTree::Token(DUMMY_SP, Token::Ident(Ident::from_str("doc"), false)),
+            TokenTree::Token(DUMMY_SP, Token::Eq),
+            TokenTree::Token(DUMMY_SP, Token::Literal(lit, None)),
+        ];
+        tokens.push(TokenTree::Delimited(
+            DUMMY_SP,
+            Delimited {
+                delim: DelimToken::Bracket,
+                tts: tts.into_iter().collect::<TokenStream>().into(),
+            },
+        ));
+    }
+    tokens
+}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
new file mode 100644
index 0000000..e09544b
--- /dev/null
+++ b/tests/common/mod.rs
@@ -0,0 +1,91 @@
+// 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.
+
+#![allow(dead_code)]
+
+extern crate syntax;
+extern crate walkdir;
+
+use std;
+use std::env;
+use std::process::Command;
+
+use self::walkdir::DirEntry;
+
+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") {
+        Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"),
+        Err(_) => std::usize::MAX,
+    }
+}
+
+pub fn base_dir_filter(entry: &DirEntry) -> bool {
+    let path = entry.path();
+    if path.is_dir() {
+        return true; // otherwise walkdir does not visit the files
+    }
+    if path.extension().map(|e| e != "rs").unwrap_or(true) {
+        return false;
+    }
+    let path_string = path.to_string_lossy();
+    let path_string = if cfg!(windows) {
+        path_string.replace('\\', "/").into()
+    } else {
+        path_string
+    };
+    // TODO assert that parsing fails on the parse-fail cases
+    if path_string.starts_with("tests/rust/src/test/parse-fail")
+        || path_string.starts_with("tests/rust/src/test/compile-fail")
+        || path_string.starts_with("tests/rust/src/test/rustfix")
+    {
+        return false;
+    }
+
+    if path_string.starts_with("tests/rust/src/test/ui") {
+        let stderr_path = path.with_extension("stderr");
+        if stderr_path.exists() {
+            // Expected to fail in some way
+            return false;
+        }
+    }
+
+    match path_string.as_ref() {
+        // Deprecated placement syntax
+        "tests/rust/src/test/run-pass/new-box-syntax.rs" |
+        "tests/rust/src/test/ui/obsolete-in-place/bad.rs" |
+        // not actually test cases
+        "tests/rust/src/test/run-pass/auxiliary/macro-comma-support.rs" |
+        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" |
+        "tests/rust/src/test/ui/issues/auxiliary/issue-21146-inc.rs" => false,
+        _ => true,
+    }
+}
+
+pub fn clone_rust() {
+    let result = Command::new("tests/clone.sh").status().unwrap();
+    println!("result: {}", result);
+    assert!(result.success());
+}
diff --git a/tests/common/parse.rs b/tests/common/parse.rs
new file mode 100644
index 0000000..0f410e6
--- /dev/null
+++ b/tests/common/parse.rs
@@ -0,0 +1,78 @@
+// 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.
+
+extern crate proc_macro2;
+extern crate syn;
+extern crate syntax;
+extern crate syntax_pos;
+
+use self::syntax::ast;
+use self::syntax::parse::{self, ParseSess};
+use self::syntax::ptr::P;
+use self::syntax::source_map::FilePathMapping;
+use self::syntax_pos::edition::Edition;
+use self::syntax_pos::{hygiene, FileName};
+
+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);
+        let sess = ParseSess::new(FilePathMapping::empty());
+        sess.span_diagnostic.set_continue_after_error(false);
+        let e = parse::new_parser_from_source_str(
+            &sess,
+            FileName::Custom("test_precedence".to_string()),
+            input.to_string(),
+        ).parse_expr();
+        match e {
+            Ok(expr) => Some(expr),
+            Err(mut diagnostic) => {
+                diagnostic.emit();
+                None
+            }
+        }
+    }) {
+        Ok(Some(e)) => Some(e),
+        Ok(None) => None,
+        Err(_) => {
+            errorf!("libsyntax panicked\n");
+            None
+        }
+    }
+}
+
+pub fn syn_expr(input: &str) -> Option<syn::Expr> {
+    match syn::parse_str(input) {
+        Ok(e) => Some(e),
+        Err(msg) => {
+            errorf!("syn failed to parse\n{:?}\n", msg);
+            None
+        }
+    }
+}
+
+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/macros/mod.rs b/tests/macros/mod.rs
new file mode 100644
index 0000000..820941f
--- /dev/null
+++ b/tests/macros/mod.rs
@@ -0,0 +1,31 @@
+// 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.
+
+#[macro_export]
+macro_rules! errorf {
+    ($($tt:tt)*) => {{
+        use ::std::io::Write;
+        let stderr = ::std::io::stderr();
+        write!(stderr.lock(), $($tt)*).unwrap();
+    }};
+}
+
+#[macro_export]
+macro_rules! punctuated {
+    ($($e:expr,)+) => {{
+        let mut seq = ::syn::punctuated::Punctuated::new();
+        $(
+            seq.push($e);
+        )+
+        seq
+    }};
+
+    ($($e:expr),+) => {
+        punctuated!($($e,)+)
+    };
+}
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
new file mode 100644
index 0000000..045e506
--- /dev/null
+++ b/tests/test_derive_input.rs
@@ -0,0 +1,808 @@
+// 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::Delimiter::{Brace, Parenthesis};
+use proc_macro2::*;
+use syn::punctuated::Punctuated;
+use syn::*;
+
+use std::iter::FromIterator;
+
+#[macro_use]
+mod macros;
+
+fn op(c: char) -> TokenTree {
+    Punct::new(c, Spacing::Alone).into()
+}
+
+fn lit<T: Into<Literal>>(t: T) -> TokenTree {
+    t.into().into()
+}
+
+fn ident(sym: &str) -> Ident {
+    Ident::new(sym, Span::call_site())
+}
+
+fn word(sym: &str) -> TokenTree {
+    ident(sym).into()
+}
+
+fn delimited(delim: Delimiter, tokens: Vec<TokenTree>) -> TokenTree {
+    Group::new(delim, tokens.into_iter().collect()).into()
+}
+
+#[test]
+fn test_unit() {
+    let raw = "struct Unit;";
+
+    let expected = DeriveInput {
+        ident: ident("Unit"),
+        vis: Visibility::Inherited,
+        attrs: Vec::new(),
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+            fields: Fields::Unit,
+        }),
+    };
+
+    assert_eq!(expected, syn::parse_str(raw).unwrap());
+}
+
+#[test]
+fn test_struct() {
+    let raw = "
+        #[derive(Debug, Clone)]
+        pub struct Item {
+            pub ident: Ident,
+            pub attrs: Vec<Attribute>
+        }
+    ";
+
+    let expected = DeriveInput {
+        ident: ident("Item"),
+        vis: Visibility::Public(VisPublic {
+            pub_token: Default::default(),
+        }),
+        attrs: vec![Attribute {
+            bracket_token: Default::default(),
+            pound_token: Default::default(),
+            style: AttrStyle::Outer,
+            path: ident("derive").into(),
+            tts: TokenStream::from_iter(vec![delimited(
+                Parenthesis,
+                vec![word("Debug"), op(','), word("Clone")],
+            )]),
+        }],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            semi_token: None,
+            struct_token: Default::default(),
+            fields: Fields::Named(FieldsNamed {
+                brace_token: Default::default(),
+                named: punctuated![
+                    Field {
+                        ident: Some(ident("ident")),
+                        colon_token: Some(Default::default()),
+                        vis: Visibility::Public(VisPublic {
+                            pub_token: Default::default(),
+                        }),
+                        attrs: Vec::new(),
+                        ty: TypePath {
+                            qself: None,
+                            path: ident("Ident").into(),
+                        }.into(),
+                    },
+                    Field {
+                        ident: Some(ident("attrs")),
+                        colon_token: Some(Default::default()),
+                        vis: Visibility::Public(VisPublic {
+                            pub_token: Default::default(),
+                        }),
+                        attrs: Vec::new(),
+                        ty: TypePath {
+                            qself: None,
+                            path: Path {
+                                leading_colon: None,
+                                segments: punctuated![PathSegment {
+                                    ident: ident("Vec"),
+                                    arguments: PathArguments::AngleBracketed(
+                                        AngleBracketedGenericArguments {
+                                            colon2_token: None,
+                                            lt_token: Default::default(),
+                                            args: punctuated![GenericArgument::Type(Type::from(
+                                                TypePath {
+                                                    qself: None,
+                                                    path: ident("Attribute").into(),
+                                                }
+                                            )),],
+                                            gt_token: Default::default(),
+                                        },
+                                    ),
+                                },],
+                            },
+                        }.into(),
+                    },
+                ],
+            }),
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+
+    let expected_meta_item: Meta = MetaList {
+        ident: ident("derive"),
+        paren_token: Default::default(),
+        nested: punctuated![
+            NestedMeta::Meta(Meta::Word(ident("Debug"))),
+            NestedMeta::Meta(Meta::Word(ident("Clone"))),
+        ],
+    }.into();
+
+    assert_eq!(
+        expected_meta_item,
+        actual.attrs[0].interpret_meta().unwrap()
+    );
+}
+
+#[test]
+fn test_union() {
+    let raw = "
+        union MaybeUninit<T> {
+            uninit: (),
+            value: T
+        }
+    ";
+
+    let expected = DeriveInput {
+        ident: ident("MaybeUninit"),
+        vis: Visibility::Inherited,
+        attrs: Vec::new(),
+        generics: Generics {
+            lt_token: Some(Default::default()),
+            params: punctuated![GenericParam::Type(TypeParam {
+                attrs: Vec::new(),
+                ident: ident("T"),
+                bounds: Default::default(),
+                default: None,
+                colon_token: None,
+                eq_token: None,
+            }),],
+            gt_token: Some(Default::default()),
+            where_clause: None,
+        },
+        data: Data::Union(DataUnion {
+            union_token: Default::default(),
+            fields: FieldsNamed {
+                brace_token: Default::default(),
+                named: punctuated![
+                    Field {
+                        ident: Some(ident("uninit")),
+                        colon_token: Some(Default::default()),
+                        vis: Visibility::Inherited,
+                        attrs: Vec::new(),
+                        ty: TypeTuple {
+                            paren_token: Default::default(),
+                            elems: Punctuated::new(),
+                        }.into(),
+                    },
+                    Field {
+                        ident: Some(ident("value")),
+                        colon_token: Some(Default::default()),
+                        vis: Visibility::Inherited,
+                        attrs: Vec::new(),
+                        ty: TypePath {
+                            qself: None,
+                            path: ident("T").into(),
+                        }.into(),
+                    },
+                ],
+            },
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+#[cfg(feature = "full")]
+fn test_enum() {
+    let raw = r#"
+        /// See the std::result module documentation for details.
+        #[must_use]
+        pub enum Result<T, E> {
+            Ok(T),
+            Err(E),
+            Surprise = 0isize,
+
+            // Smuggling data into a proc_macro_derive,
+            // in the style of https://github.com/dtolnay/proc-macro-hack
+            ProcMacroHack = (0, "data").0
+        }
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("Result"),
+        vis: Visibility::Public(VisPublic {
+            pub_token: Default::default(),
+        }),
+        attrs: vec![
+            Attribute {
+                bracket_token: Default::default(),
+                pound_token: Default::default(),
+                style: AttrStyle::Outer,
+                path: ident("doc").into(),
+                tts: TokenStream::from_iter(vec![
+                    op('='),
+                    lit(Literal::string(
+                        " See the std::result module documentation for details.",
+                    )),
+                ]),
+            },
+            Attribute {
+                bracket_token: Default::default(),
+                pound_token: Default::default(),
+                style: AttrStyle::Outer,
+                path: ident("must_use").into(),
+                tts: TokenStream::new(),
+            },
+        ],
+        generics: Generics {
+            lt_token: Some(Default::default()),
+            params: punctuated![
+                GenericParam::Type(TypeParam {
+                    attrs: Vec::new(),
+                    ident: ident("T"),
+                    bounds: Default::default(),
+                    default: None,
+                    colon_token: None,
+                    eq_token: None,
+                }),
+                GenericParam::Type(TypeParam {
+                    attrs: Vec::new(),
+                    ident: ident("E"),
+                    bounds: Default::default(),
+                    colon_token: None,
+                    eq_token: None,
+                    default: None,
+                }),
+            ],
+            gt_token: Some(Default::default()),
+            where_clause: None,
+        },
+        data: Data::Enum(DataEnum {
+            variants: punctuated![
+                Variant {
+                    ident: ident("Ok"),
+                    attrs: Vec::new(),
+                    fields: Fields::Unnamed(FieldsUnnamed {
+                        paren_token: Default::default(),
+                        unnamed: punctuated![Field {
+                            colon_token: None,
+                            ident: None,
+                            vis: Visibility::Inherited,
+                            attrs: Vec::new(),
+                            ty: TypePath {
+                                qself: None,
+                                path: ident("T").into(),
+                            }.into(),
+                        },],
+                    }),
+                    discriminant: None,
+                },
+                Variant {
+                    ident: ident("Err"),
+                    attrs: Vec::new(),
+                    fields: Fields::Unnamed(FieldsUnnamed {
+                        paren_token: Default::default(),
+                        unnamed: punctuated![Field {
+                            ident: None,
+                            colon_token: None,
+                            vis: Visibility::Inherited,
+                            attrs: Vec::new(),
+                            ty: TypePath {
+                                qself: None,
+                                path: ident("E").into(),
+                            }.into(),
+                        },],
+                    }),
+                    discriminant: None,
+                },
+                Variant {
+                    ident: ident("Surprise"),
+                    attrs: Vec::new(),
+                    fields: Fields::Unit,
+                    discriminant: Some((
+                        Default::default(),
+                        Expr::Lit(ExprLit {
+                            attrs: Vec::new(),
+                            lit: Lit::Int(LitInt::new(0, IntSuffix::Isize, Span::call_site())),
+                        }),
+                    )),
+                },
+                Variant {
+                    ident: ident("ProcMacroHack"),
+                    attrs: Vec::new(),
+                    fields: Fields::Unit,
+                    discriminant: Some((
+                        Default::default(),
+                        Expr::Field(ExprField {
+                            attrs: Vec::new(),
+                            base: Box::new(Expr::Tuple(ExprTuple {
+                                attrs: Vec::new(),
+                                paren_token: Default::default(),
+                                elems: punctuated![
+                                    Expr::Lit(ExprLit {
+                                        attrs: Vec::new(),
+                                        lit: Lit::Int(LitInt::new(
+                                            0,
+                                            IntSuffix::None,
+                                            Span::call_site()
+                                        )),
+                                    }),
+                                    Expr::Lit(ExprLit {
+                                        attrs: Vec::new(),
+                                        lit: Lit::Str(LitStr::new("data", Span::call_site())),
+                                    }),
+                                ],
+                            })),
+                            dot_token: Default::default(),
+                            member: Member::Unnamed(Index {
+                                index: 0,
+                                span: Span::call_site(),
+                            }),
+                        }),
+                    )),
+                },
+            ],
+            brace_token: Default::default(),
+            enum_token: Default::default(),
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+
+    let expected_meta_items = vec![
+        MetaNameValue {
+            ident: ident("doc"),
+            eq_token: Default::default(),
+            lit: Lit::Str(LitStr::new(
+                " See the std::result module documentation for details.",
+                Span::call_site(),
+            )),
+        }.into(),
+        Meta::Word(ident("must_use")),
+    ];
+
+    let actual_meta_items: Vec<_> = actual
+        .attrs
+        .into_iter()
+        .map(|attr| attr.interpret_meta().unwrap())
+        .collect();
+
+    assert_eq!(expected_meta_items, actual_meta_items);
+}
+
+#[test]
+fn test_attr_with_path() {
+    let raw = r#"
+        #[::attr_args::identity
+            fn main() { assert_eq!(foo(), "Hello, world!"); }]
+        struct Dummy;
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("Dummy"),
+        vis: Visibility::Inherited,
+        attrs: vec![Attribute {
+            bracket_token: Default::default(),
+            pound_token: Default::default(),
+            style: AttrStyle::Outer,
+            path: Path {
+                leading_colon: Some(Default::default()),
+                segments: punctuated![
+                    PathSegment::from(ident("attr_args")),
+                    PathSegment::from(ident("identity")),
+                ],
+            },
+            tts: TokenStream::from_iter(vec![
+                word("fn"),
+                word("main"),
+                delimited(Parenthesis, vec![]),
+                delimited(
+                    Brace,
+                    vec![
+                        word("assert_eq"),
+                        op('!'),
+                        delimited(
+                            Parenthesis,
+                            vec![
+                                word("foo"),
+                                delimited(Parenthesis, vec![]),
+                                op(','),
+                                lit(Literal::string("Hello, world!")),
+                            ],
+                        ),
+                        op(';'),
+                    ],
+                ),
+            ]),
+        }],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            fields: Fields::Unit,
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+
+    assert!(actual.attrs[0].interpret_meta().is_none());
+}
+
+#[test]
+fn test_attr_with_non_mod_style_path() {
+    let raw = r#"
+        #[inert <T>]
+        struct S;
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("S"),
+        vis: Visibility::Inherited,
+        attrs: vec![Attribute {
+            bracket_token: Default::default(),
+            pound_token: Default::default(),
+            style: AttrStyle::Outer,
+            path: Path {
+                leading_colon: None,
+                segments: punctuated![PathSegment::from(ident("inert"))],
+            },
+            tts: TokenStream::from_iter(vec![op('<'), word("T"), op('>')]),
+        }],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            fields: Fields::Unit,
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+
+    assert!(actual.attrs[0].interpret_meta().is_none());
+}
+
+#[test]
+fn test_attr_with_mod_style_path_with_self() {
+    let raw = r#"
+        #[foo::self]
+        struct S;
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("S"),
+        vis: Visibility::Inherited,
+        attrs: vec![Attribute {
+            bracket_token: Default::default(),
+            pound_token: Default::default(),
+            style: AttrStyle::Outer,
+            path: Path {
+                leading_colon: None,
+                segments: punctuated![
+                    PathSegment::from(ident("foo")),
+                    PathSegment::from(ident("self")),
+                ],
+            },
+            tts: TokenStream::new(),
+        }],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            fields: Fields::Unit,
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+
+    assert!(actual.attrs[0].interpret_meta().is_none());
+}
+
+#[test]
+fn test_pub_restricted() {
+    // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
+    let raw = r#"
+        pub(in m) struct Z(pub(in m::n) u8);
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("Z"),
+        vis: Visibility::Restricted(VisRestricted {
+            path: Box::new(ident("m").into()),
+            in_token: Some(Default::default()),
+            paren_token: Default::default(),
+            pub_token: Default::default(),
+        }),
+        attrs: vec![],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            fields: Fields::Unnamed(FieldsUnnamed {
+                paren_token: Default::default(),
+                unnamed: punctuated![Field {
+                    ident: None,
+                    vis: Visibility::Restricted(VisRestricted {
+                        path: Box::new(Path {
+                            leading_colon: None,
+                            segments: punctuated![
+                                PathSegment::from(ident("m")),
+                                PathSegment::from(ident("n")),
+                            ],
+                        }),
+                        in_token: Some(Default::default()),
+                        paren_token: Default::default(),
+                        pub_token: Default::default(),
+                    }),
+                    colon_token: None,
+                    attrs: vec![],
+                    ty: TypePath {
+                        qself: None,
+                        path: ident("u8").into(),
+                    }.into(),
+                },],
+            }),
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_vis_crate() {
+    let raw = r#"
+        crate struct S;
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("S"),
+        vis: Visibility::Crate(VisCrate {
+            crate_token: Default::default(),
+        }),
+        attrs: vec![],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+            fields: Fields::Unit,
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_pub_restricted_crate() {
+    let raw = r#"
+        pub(crate) struct S;
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("S"),
+        vis: Visibility::Restricted(VisRestricted {
+            pub_token: Default::default(),
+            paren_token: Default::default(),
+            in_token: None,
+            path: Box::new(ident("crate").into()),
+        }),
+        attrs: vec![],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+            fields: Fields::Unit,
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_pub_restricted_super() {
+    let raw = r#"
+        pub(super) struct S;
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("S"),
+        vis: Visibility::Restricted(VisRestricted {
+            path: Box::new(ident("super").into()),
+            in_token: None,
+            paren_token: Default::default(),
+            pub_token: Default::default(),
+        }),
+        attrs: vec![],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+            fields: Fields::Unit,
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_pub_restricted_in_super() {
+    let raw = r#"
+        pub(in super) struct S;
+    "#;
+
+    let expected = DeriveInput {
+        ident: ident("S"),
+        vis: Visibility::Restricted(VisRestricted {
+            path: Box::new(ident("super").into()),
+            in_token: Some(Default::default()),
+            paren_token: Default::default(),
+            pub_token: Default::default(),
+        }),
+        attrs: vec![],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            semi_token: Some(Default::default()),
+            struct_token: Default::default(),
+            fields: Fields::Unit,
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_fields_on_unit_struct() {
+    let raw = "struct S;";
+    let struct_body = match syn::parse_str::<DeriveInput>(raw).unwrap().data {
+        Data::Struct(body) => body,
+        _ => panic!("expected a struct"),
+    };
+
+    assert_eq!(0, struct_body.fields.iter().count());
+}
+
+#[test]
+fn test_fields_on_named_struct() {
+    let raw = "struct S {
+        foo: i32,
+        pub bar: String,
+    }";
+    let struct_body = match syn::parse_str::<DeriveInput>(raw).unwrap().data {
+        Data::Struct(body) => body,
+        _ => panic!("expected a struct"),
+    };
+
+    let expected = vec![
+        Field {
+            attrs: vec![],
+            vis: Visibility::Inherited,
+            ident: Some(ident("foo")),
+            colon_token: Some(Default::default()),
+            ty: syn::parse_str("i32").unwrap(),
+        },
+        Field {
+            attrs: vec![],
+            vis: Visibility::Public(VisPublic {
+                pub_token: Default::default(),
+            }),
+            ident: Some(ident("bar")),
+            colon_token: Some(Default::default()),
+            ty: syn::parse_str("String").unwrap(),
+        },
+    ];
+    let expected = expected.iter().collect::<Vec<_>>();
+
+    assert_eq!(expected, struct_body.fields.iter().collect::<Vec<_>>());
+}
+
+#[test]
+fn test_fields_on_tuple_struct() {
+    let raw = "struct S(i32, pub String);";
+    let struct_body = match syn::parse_str::<DeriveInput>(raw).unwrap().data {
+        Data::Struct(body) => body,
+        _ => panic!("expected a struct"),
+    };
+
+    let expected = vec![
+        Field {
+            attrs: vec![],
+            vis: Visibility::Inherited,
+            ident: None,
+            colon_token: None,
+            ty: syn::parse_str("i32").unwrap(),
+        },
+        Field {
+            attrs: vec![],
+            vis: Visibility::Public(VisPublic {
+                pub_token: Default::default(),
+            }),
+            ident: None,
+            colon_token: None,
+            ty: syn::parse_str("String").unwrap(),
+        },
+    ];
+    let expected = expected.iter().collect::<Vec<_>>();
+
+    assert_eq!(expected, struct_body.fields.iter().collect::<Vec<_>>());
+}
+
+#[test]
+fn test_ambiguous_crate() {
+    // The field type is `(crate::X)` not `crate (::X)`.
+    let raw = "struct S(crate::X);";
+
+    let expected = DeriveInput {
+        ident: ident("S"),
+        vis: Visibility::Inherited,
+        attrs: vec![],
+        generics: Generics::default(),
+        data: Data::Struct(DataStruct {
+            struct_token: Default::default(),
+            fields: Fields::Unnamed(FieldsUnnamed {
+                paren_token: Default::default(),
+                unnamed: punctuated![Field {
+                    attrs: Vec::new(),
+                    vis: Visibility::Inherited,
+                    ident: None,
+                    colon_token: None,
+                    ty: Type::Path(TypePath {
+                        qself: None,
+                        path: Path {
+                            leading_colon: None,
+                            segments: punctuated![ident("crate").into(), ident("X").into(),],
+                        },
+                    }),
+                }],
+            }),
+            semi_token: Some(Default::default()),
+        }),
+    };
+
+    let actual = syn::parse_str(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
diff --git a/tests/test_generics.rs b/tests/test_generics.rs
new file mode 100644
index 0000000..33e7768
--- /dev/null
+++ b/tests/test_generics.rs
@@ -0,0 +1,175 @@
+// 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")]
+#![recursion_limit = "1024"]
+#![feature(rustc_private)]
+
+extern crate syn;
+use syn::*;
+
+#[macro_use]
+extern crate quote;
+
+extern crate proc_macro2;
+use proc_macro2::{Ident, Span, TokenStream};
+
+#[macro_use]
+mod macros;
+
+mod common;
+
+fn ident(s: &str) -> Ident {
+    Ident::new(s, Span::call_site())
+}
+
+#[test]
+fn test_split_for_impl() {
+    // <'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug
+    let generics = Generics {
+        gt_token: Some(Default::default()),
+        lt_token: Some(Default::default()),
+        params: punctuated![
+            GenericParam::Lifetime(LifetimeDef {
+                attrs: Default::default(),
+                lifetime: Lifetime::new("'a", Span::call_site()),
+                bounds: Default::default(),
+                colon_token: None,
+            }),
+            GenericParam::Lifetime(LifetimeDef {
+                attrs: Default::default(),
+                lifetime: Lifetime::new("'b", Span::call_site()),
+                bounds: punctuated![Lifetime::new("'a", Span::call_site())],
+                colon_token: Some(token::Colon::default()),
+            }),
+            GenericParam::Type(TypeParam {
+                attrs: vec![Attribute {
+                    bracket_token: Default::default(),
+                    pound_token: Default::default(),
+                    style: AttrStyle::Outer,
+                    path: ident("may_dangle").into(),
+                    tts: TokenStream::new(),
+                }],
+                ident: ident("T"),
+                bounds: punctuated![TypeParamBound::Lifetime(Lifetime::new(
+                    "'a",
+                    Span::call_site()
+                )),],
+                default: Some(
+                    TypeTuple {
+                        elems: Default::default(),
+                        paren_token: Default::default(),
+                    }.into(),
+                ),
+                colon_token: Some(Default::default()),
+                eq_token: Default::default(),
+            }),
+        ],
+        where_clause: Some(WhereClause {
+            where_token: Default::default(),
+            predicates: punctuated![WherePredicate::Type(PredicateType {
+                lifetimes: None,
+                colon_token: Default::default(),
+                bounded_ty: TypePath {
+                    qself: None,
+                    path: ident("T").into(),
+                }.into(),
+                bounds: punctuated![TypeParamBound::Trait(TraitBound {
+                    paren_token: None,
+                    modifier: TraitBoundModifier::None,
+                    lifetimes: None,
+                    path: ident("Debug").into(),
+                }),],
+            }),],
+        }),
+    };
+
+    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+    let tokens = quote! {
+        impl #impl_generics MyTrait for Test #ty_generics #where_clause {}
+    };
+    let expected = concat!(
+        "impl < 'a , 'b : 'a , # [ may_dangle ] T : 'a > ",
+        "MyTrait for Test < 'a , 'b , T > ",
+        "where T : Debug { }"
+    );
+    assert_eq!(expected, tokens.to_string());
+
+    let turbofish = ty_generics.as_turbofish();
+    let tokens = quote! {
+        Test #turbofish
+    };
+    let expected = "Test :: < 'a , 'b , T >";
+    assert_eq!(expected, tokens.to_string());
+}
+
+#[test]
+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())
+    );
+
+    let tokens = quote!('_);
+    println!("{:?}", tokens);
+    let expected = TypeParamBound::Lifetime(Lifetime::new("'_", Span::call_site()));
+    assert_eq!(
+        expected,
+        common::parse::syn::<TypeParamBound>(tokens.into())
+    );
+
+    let tokens = quote!(Debug);
+    let expected = TypeParamBound::Trait(TraitBound {
+        paren_token: None,
+        modifier: TraitBoundModifier::None,
+        lifetimes: None,
+        path: ident("Debug").into(),
+    });
+    assert_eq!(
+        expected,
+        common::parse::syn::<TypeParamBound>(tokens.into())
+    );
+
+    let tokens = quote!(?Sized);
+    let expected = TypeParamBound::Trait(TraitBound {
+        paren_token: None,
+        modifier: TraitBoundModifier::Maybe(Default::default()),
+        lifetimes: None,
+        path: ident("Sized").into(),
+    });
+    assert_eq!(
+        expected,
+        common::parse::syn::<TypeParamBound>(tokens.into())
+    );
+}
+
+#[test]
+fn test_fn_precedence_in_where_clause() {
+    // This should parse as two separate bounds, `FnOnce() -> i32` and `Send` - not `FnOnce() -> (i32 + Send)`.
+    let sig = quote! {
+        fn f<G>()
+        where
+            G: FnOnce() -> i32 + Send,
+        {
+        }
+    };
+    let fun = common::parse::syn::<ItemFn>(sig.into());
+    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] {
+        WherePredicate::Type(ref pred) => pred,
+        _ => panic!("wrong predicate kind"),
+    };
+    assert_eq!(predicate.bounds.len(), 2, "{:#?}", predicate.bounds);
+    let first_bound = &predicate.bounds[0];
+    assert_eq!(quote!(#first_bound).to_string(), "FnOnce ( ) -> i32");
+    let second_bound = &predicate.bounds[1];
+    assert_eq!(quote!(#second_bound).to_string(), "Send");
+}
diff --git a/tests/test_grouping.rs b/tests/test_grouping.rs
new file mode 100644
index 0000000..96ab164
--- /dev/null
+++ b/tests/test_grouping.rs
@@ -0,0 +1,123 @@
+// 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"))]
+#![recursion_limit = "1024"]
+#![feature(rustc_private)]
+
+#[macro_use]
+extern crate syn;
+use syn::token::Group;
+use syn::{BinOp, Expr, ExprBinary, ExprGroup, ExprLit, Lit};
+
+extern crate proc_macro2;
+use proc_macro2::*;
+
+#[macro_use]
+mod macros;
+
+mod common;
+
+fn expr<T: Into<Expr>>(t: T) -> Expr {
+    t.into()
+}
+
+fn lit<T: Into<Literal>>(t: T) -> Expr {
+    Expr::Lit(ExprLit {
+        attrs: Vec::new(),
+        lit: Lit::new(t.into()),
+    })
+}
+
+#[test]
+fn test_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)),
+                TokenTree::Literal(Literal::i32_suffixed(3)),
+            ].into_iter()
+            .collect(),
+        )),
+        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(lit(Literal::i32_suffixed(1))),
+            op: BinOp::Add(<Token![+]>::default()),
+            right: Box::new(expr(ExprBinary {
+                attrs: Vec::new(),
+                left: Box::new(expr(ExprGroup {
+                    attrs: Vec::new(),
+                    group_token: Group::default(),
+                    expr: Box::new(expr(ExprBinary {
+                        attrs: Vec::new(),
+                        left: Box::new(lit(Literal::i32_suffixed(2))),
+                        op: BinOp::Add(<Token![+]>::default()),
+                        right: Box::new(lit(Literal::i32_suffixed(3))),
+                    })),
+                })),
+                op: BinOp::Mul(<Token![*]>::default()),
+                right: Box::new(lit(Literal::i32_suffixed(4))),
+            })),
+        })
+    );
+}
+
+#[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
new file mode 100644
index 0000000..73187d3
--- /dev/null
+++ b/tests/test_ident.rs
@@ -0,0 +1,96 @@
+// 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.
+
+extern crate proc_macro2;
+extern crate syn;
+
+use proc_macro2::{Ident, Span, TokenStream};
+use std::str::FromStr;
+use syn::synom::ParseError;
+
+fn parse(s: &str) -> Result<Ident, ParseError> {
+    syn::parse2(TokenStream::from_str(s).unwrap())
+}
+
+fn new(s: &str) -> Ident {
+    Ident::new(s, Span::call_site())
+}
+
+#[test]
+fn ident_parse() {
+    parse("String").unwrap();
+}
+
+#[test]
+fn ident_parse_keyword() {
+    parse("abstract").unwrap_err();
+}
+
+#[test]
+fn ident_parse_empty() {
+    parse("").unwrap_err();
+}
+
+#[test]
+fn ident_parse_lifetime() {
+    parse("'static").unwrap_err();
+}
+
+#[test]
+fn ident_parse_underscore() {
+    parse("_").unwrap_err();
+}
+
+#[test]
+fn ident_parse_number() {
+    parse("255").unwrap_err();
+}
+
+#[test]
+fn ident_parse_invalid() {
+    parse("a#").unwrap_err();
+}
+
+#[test]
+fn ident_new() {
+    new("String");
+}
+
+#[test]
+fn ident_new_keyword() {
+    new("abstract");
+}
+
+#[test]
+#[should_panic(expected = "use Option<Ident>")]
+fn ident_new_empty() {
+    new("");
+}
+
+#[test]
+#[should_panic(expected = "not a valid Ident")]
+fn ident_new_lifetime() {
+    new("'static");
+}
+
+#[test]
+fn ident_new_underscore() {
+    new("_");
+}
+
+#[test]
+#[should_panic(expected = "use Literal instead")]
+fn ident_new_number() {
+    new("255");
+}
+
+#[test]
+#[should_panic(expected = "\"a#\" is not a valid Ident")]
+fn ident_new_invalid() {
+    new("a#");
+}
diff --git a/tests/test_lit.rs b/tests/test_lit.rs
new file mode 100644
index 0000000..b0e4004
--- /dev/null
+++ b/tests/test_lit.rs
@@ -0,0 +1,196 @@
+// 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.
+
+extern crate proc_macro2;
+extern crate quote;
+extern crate syn;
+
+use proc_macro2::{TokenStream, TokenTree};
+use quote::ToTokens;
+use std::str::FromStr;
+use syn::{FloatSuffix, IntSuffix, Lit};
+
+fn lit(s: &str) -> Lit {
+    match TokenStream::from_str(s)
+        .unwrap()
+        .into_iter()
+        .next()
+        .unwrap()
+    {
+        TokenTree::Literal(lit) => Lit::new(lit),
+        _ => panic!(),
+    }
+}
+
+#[test]
+fn strings() {
+    fn test_string(s: &str, value: &str) {
+        match lit(s) {
+            Lit::Str(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_token_stream().to_string();
+                if again != s {
+                    test_string(&again, value);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_string("\"a\"", "a");
+    test_string("\"\\n\"", "\n");
+    test_string("\"\\r\"", "\r");
+    test_string("\"\\t\"", "\t");
+    test_string("\"🐕\"", "🐕"); // NOTE: This is an emoji
+    test_string("\"\\\"\"", "\"");
+    test_string("\"'\"", "'");
+    test_string("\"\"", "");
+    test_string("\"\\u{1F415}\"", "\u{1F415}");
+    test_string(
+        "\"contains\nnewlines\\\nescaped newlines\"",
+        "contains\nnewlinesescaped newlines",
+    );
+    test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere");
+}
+
+#[test]
+fn byte_strings() {
+    fn test_byte_string(s: &str, value: &[u8]) {
+        match lit(s) {
+            Lit::ByteStr(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_token_stream().to_string();
+                if again != s {
+                    test_byte_string(&again, value);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_byte_string("b\"a\"", b"a");
+    test_byte_string("b\"\\n\"", b"\n");
+    test_byte_string("b\"\\r\"", b"\r");
+    test_byte_string("b\"\\t\"", b"\t");
+    test_byte_string("b\"\\\"\"", b"\"");
+    test_byte_string("b\"'\"", b"'");
+    test_byte_string("b\"\"", b"");
+    test_byte_string(
+        "b\"contains\nnewlines\\\nescaped newlines\"",
+        b"contains\nnewlinesescaped newlines",
+    );
+    test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere");
+}
+
+#[test]
+fn bytes() {
+    fn test_byte(s: &str, value: u8) {
+        match lit(s) {
+            Lit::Byte(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_token_stream().to_string();
+                assert_eq!(again, s);
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_byte("b'a'", b'a');
+    test_byte("b'\\n'", b'\n');
+    test_byte("b'\\r'", b'\r');
+    test_byte("b'\\t'", b'\t');
+    test_byte("b'\\''", b'\'');
+    test_byte("b'\"'", b'"');
+}
+
+#[test]
+fn chars() {
+    fn test_char(s: &str, value: char) {
+        match lit(s) {
+            Lit::Char(lit) => {
+                assert_eq!(lit.value(), value);
+                let again = lit.into_token_stream().to_string();
+                if again != s {
+                    test_char(&again, value);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    test_char("'a'", 'a');
+    test_char("'\\n'", '\n');
+    test_char("'\\r'", '\r');
+    test_char("'\\t'", '\t');
+    test_char("'🐕'", '🐕'); // NOTE: This is an emoji
+    test_char("'\\''", '\'');
+    test_char("'\"'", '"');
+    test_char("'\\u{1F415}'", '\u{1F415}');
+}
+
+#[test]
+fn ints() {
+    fn test_int(s: &str, value: u64, suffix: IntSuffix) {
+        match lit(s) {
+            Lit::Int(lit) => {
+                assert_eq!(lit.value(), value);
+                assert_eq!(lit.suffix(), suffix);
+                let again = lit.into_token_stream().to_string();
+                if again != s {
+                    test_int(&again, value, suffix);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    use syn::IntSuffix::*;
+    test_int("5", 5, None);
+    test_int("5u32", 5, U32);
+    test_int("5_0", 50, None);
+    test_int("5_____0_____", 50, None);
+    test_int("0x7f", 127, None);
+    test_int("0x7F", 127, None);
+    test_int("0b1001", 9, None);
+    test_int("0o73", 59, None);
+    test_int("0x7Fu8", 127, U8);
+    test_int("0b1001i8", 9, I8);
+    test_int("0o73u32", 59, U32);
+    test_int("0x__7___f_", 127, None);
+    test_int("0x__7___F_", 127, None);
+    test_int("0b_1_0__01", 9, None);
+    test_int("0o_7__3", 59, None);
+    test_int("0x_7F__u8", 127, U8);
+    test_int("0b__10__0_1i8", 9, I8);
+    test_int("0o__7__________________3u32", 59, U32);
+}
+
+#[test]
+fn floats() {
+    #[cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
+    fn test_float(s: &str, value: f64, suffix: FloatSuffix) {
+        match lit(s) {
+            Lit::Float(lit) => {
+                assert_eq!(lit.value(), value);
+                assert_eq!(lit.suffix(), suffix);
+                let again = lit.into_token_stream().to_string();
+                if again != s {
+                    test_float(&again, value, suffix);
+                }
+            }
+            wrong => panic!("{:?}", wrong),
+        }
+    }
+
+    use syn::FloatSuffix::*;
+    test_float("5.5", 5.5, None);
+    test_float("5.5E12", 5.5e12, None);
+    test_float("5.5e12", 5.5e12, None);
+    test_float("1.0__3e-12", 1.03e-12, None);
+    test_float("1.03e+12", 1.03e12, None);
+}
diff --git a/tests/test_meta_item.rs b/tests/test_meta_item.rs
new file mode 100644
index 0000000..a45e36e
--- /dev/null
+++ b/tests/test_meta_item.rs
@@ -0,0 +1,181 @@
+// 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::{Ident, Literal, Span, TokenStream};
+use syn::buffer::TokenBuffer;
+use syn::*;
+
+#[macro_use]
+mod macros;
+
+fn lit<T: Into<Literal>>(t: T) -> Lit {
+    Lit::new(t.into())
+}
+
+fn ident(s: &str) -> Ident {
+    Ident::new(s, Span::call_site())
+}
+
+#[test]
+fn test_meta_item_word() {
+    run_test("#[foo]", Meta::Word(ident("foo")))
+}
+
+#[test]
+fn test_meta_item_name_value() {
+    run_test(
+        "#[foo = 5]",
+        MetaNameValue {
+            ident: ident("foo").into(),
+            eq_token: Default::default(),
+            lit: lit(Literal::i32_unsuffixed(5)),
+        },
+    )
+}
+
+#[test]
+fn test_meta_item_bool_value() {
+    run_test(
+        "#[foo = true]",
+        MetaNameValue {
+            ident: ident("foo").into(),
+            eq_token: Default::default(),
+            lit: Lit::Bool(LitBool {
+                value: true,
+                span: Span::call_site(),
+            }),
+        },
+    );
+    run_test(
+        "#[foo = false]",
+        MetaNameValue {
+            ident: ident("foo").into(),
+            eq_token: Default::default(),
+            lit: Lit::Bool(LitBool {
+                value: false,
+                span: Span::call_site(),
+            }),
+        },
+    )
+}
+
+#[test]
+fn test_meta_item_list_lit() {
+    run_test(
+        "#[foo(5)]",
+        MetaList {
+            ident: ident("foo").into(),
+            paren_token: Default::default(),
+            nested: punctuated![NestedMeta::Literal(lit(Literal::i32_unsuffixed(5)))],
+        },
+    )
+}
+
+#[test]
+fn test_meta_item_list_word() {
+    run_test(
+        "#[foo(bar)]",
+        MetaList {
+            ident: ident("foo").into(),
+            paren_token: Default::default(),
+            nested: punctuated![NestedMeta::Meta(Meta::Word(ident("bar").into()))],
+        },
+    )
+}
+
+#[test]
+fn test_meta_item_list_name_value() {
+    run_test(
+        "#[foo(bar = 5)]",
+        MetaList {
+            ident: ident("foo").into(),
+            paren_token: Default::default(),
+            nested: punctuated![NestedMeta::Meta(
+                MetaNameValue {
+                    ident: ident("bar").into(),
+                    eq_token: Default::default(),
+                    lit: lit(Literal::i32_unsuffixed(5)),
+                }.into(),
+            ),],
+        },
+    )
+}
+
+#[test]
+fn test_meta_item_list_bool_value() {
+    run_test(
+        "#[foo(bar = true)]",
+        MetaList {
+            ident: ident("foo").into(),
+            paren_token: Default::default(),
+            nested: punctuated![NestedMeta::Meta(
+                MetaNameValue {
+                    ident: ident("bar").into(),
+                    eq_token: Default::default(),
+                    lit: Lit::Bool(LitBool {
+                        value: true,
+                        span: Span::call_site()
+                    }),
+                }.into(),
+            ),],
+        },
+    )
+}
+
+#[test]
+fn test_meta_item_multiple() {
+    run_test(
+        "#[foo(word, name = 5, list(name2 = 6), word2)]",
+        MetaList {
+            ident: ident("foo").into(),
+            paren_token: Default::default(),
+            nested: punctuated![
+                NestedMeta::Meta(Meta::Word(ident("word").into())),
+                NestedMeta::Meta(
+                    MetaNameValue {
+                        ident: ident("name").into(),
+                        eq_token: Default::default(),
+                        lit: lit(Literal::i32_unsuffixed(5)),
+                    }.into(),
+                ),
+                NestedMeta::Meta(
+                    MetaList {
+                        ident: ident("list").into(),
+                        paren_token: Default::default(),
+                        nested: punctuated![NestedMeta::Meta(
+                            MetaNameValue {
+                                ident: ident("name2").into(),
+                                eq_token: Default::default(),
+                                lit: lit(Literal::i32_unsuffixed(6)),
+                            }.into(),
+                        ),],
+                    }.into(),
+                ),
+                NestedMeta::Meta(Meta::Word(ident("word2").into())),
+            ],
+        },
+    )
+}
+
+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),
+    };
+    assert_eq!(expected.into(), attr.interpret_meta().unwrap());
+}
diff --git a/tests/test_precedence.rs b/tests/test_precedence.rs
new file mode 100644
index 0000000..a85bf27
--- /dev/null
+++ b/tests/test_precedence.rs
@@ -0,0 +1,365 @@
+// 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 = "full", feature = "fold"))]
+#![recursion_limit = "1024"]
+#![feature(rustc_private)]
+
+//! The tests in this module do the following:
+//!
+//! 1. Parse a given expression in both `syn` and `libsyntax`.
+//! 2. Fold over the expression adding brackets around each subexpression (with
+//!    some complications - see the `syn_brackets` and `libsyntax_brackets`
+//!    methods).
+//! 3. Serialize the `syn` expression back into a string, and re-parse it with
+//!    `libsyntax`.
+//! 4. Respan all of the expressions, replacing the spans with the default
+//!    spans.
+//! 5. Compare the expressions with one another, if they are not equal fail.
+
+#[macro_use]
+extern crate quote;
+extern crate rayon;
+extern crate regex;
+extern crate rustc_data_structures;
+extern crate syn;
+extern crate syntax;
+extern crate walkdir;
+
+use rayon::iter::{IntoParallelIterator, ParallelIterator};
+use regex::Regex;
+use syntax::ast;
+use syntax::ptr::P;
+use walkdir::{DirEntry, WalkDir};
+
+use std::fs::File;
+use std::io::Read;
+use std::process;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+use common::eq::SpanlessEq;
+use common::parse;
+
+#[macro_use]
+mod macros;
+
+#[allow(dead_code)]
+mod common;
+
+/// Test some pre-set expressions chosen by us.
+#[test]
+fn test_simple_precedence() {
+    const EXPRS: &[&str] = &[
+        "1 + 2 * 3 + 4",
+        "1 + 2 * ( 3 + 4 )",
+        "{ for i in r { } *some_ptr += 1; }",
+        "{ loop { break 5; } }",
+        "{ if true { () }.mthd() }",
+        "{ for i in unsafe { 20 } { } }",
+    ];
+
+    let mut failed = 0;
+
+    for input in EXPRS {
+        let expr = if let Some(expr) = parse::syn_expr(input) {
+            expr
+        } else {
+            failed += 1;
+            continue;
+        };
+
+        let pf = match test_expressions(vec![expr]) {
+            (1, 0) => "passed",
+            (0, 1) => {
+                failed += 1;
+                "failed"
+            }
+            _ => unreachable!(),
+        };
+        errorf!("=== {}: {}\n", input, pf);
+    }
+
+    if failed > 0 {
+        panic!("Failed {} tests", failed);
+    }
+}
+
+/// 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 {
+        panic!("Skipping all precedence tests");
+    }
+
+    let passed = AtomicUsize::new(0);
+    let failed = AtomicUsize::new(0);
+
+    // 2018 edition is hard
+    let edition_regex = Regex::new(r"\b(async|try)[!(]").unwrap();
+
+    WalkDir::new("tests/rust")
+        .sort_by(|a, b| a.file_name().cmp(b.file_name()))
+        .into_iter()
+        .filter_entry(common::base_dir_filter)
+        .collect::<Result<Vec<DirEntry>, walkdir::Error>>()
+        .unwrap()
+        .into_par_iter()
+        .for_each(|entry| {
+            let path = entry.path();
+            if path.is_dir() {
+                return;
+            }
+
+            // Our version of `libsyntax` can't parse this tests
+            if path
+                .to_str()
+                .unwrap()
+                .ends_with("optional_comma_in_match_arm.rs")
+            {
+                return;
+            }
+
+            let mut file = File::open(path).unwrap();
+            let mut content = String::new();
+            file.read_to_string(&mut content).unwrap();
+            let content = edition_regex.replace_all(&content, "_$0");
+
+            let (l_passed, l_failed) = match syn::parse_file(&content) {
+                Ok(file) => {
+                    let exprs = collect_exprs(file);
+                    test_expressions(exprs)
+                }
+                Err(msg) => {
+                    errorf!("syn failed to parse\n{:?}\n", msg);
+                    (0, 1)
+                }
+            };
+
+            errorf!(
+                "=== {}: {} passed | {} failed\n",
+                path.display(),
+                l_passed,
+                l_failed
+            );
+
+            passed.fetch_add(l_passed, Ordering::SeqCst);
+            let prev_failed = failed.fetch_add(l_failed, Ordering::SeqCst);
+
+            if prev_failed + l_failed >= abort_after {
+                process::exit(1);
+            }
+        });
+
+    let passed = passed.load(Ordering::SeqCst);
+    let failed = failed.load(Ordering::SeqCst);
+
+    errorf!("\n===== Precedence Test Results =====\n");
+    errorf!("{} passed | {} failed\n", passed, failed);
+
+    if failed > 0 {
+        panic!("{} failures", failed);
+    }
+}
+
+fn test_expressions(exprs: Vec<syn::Expr>) -> (usize, usize) {
+    let mut passed = 0;
+    let mut failed = 0;
+
+    syntax::with_globals(|| {
+        for expr in exprs {
+            let raw = quote!(#expr).to_string();
+
+            let libsyntax_ast = if let Some(e) = libsyntax_parse_and_rewrite(&raw) {
+                e
+            } else {
+                failed += 1;
+                errorf!("\nFAIL - libsyntax failed to parse raw\n");
+                continue;
+            };
+
+            let syn_expr = syn_brackets(expr);
+            let syn_ast = if let Some(e) = parse::libsyntax_expr(&quote!(#syn_expr).to_string()) {
+                e
+            } else {
+                failed += 1;
+                errorf!("\nFAIL - libsyntax failed to parse bracketed\n");
+                continue;
+            };
+
+            if SpanlessEq::eq(&syn_ast, &libsyntax_ast) {
+                passed += 1;
+            } else {
+                failed += 1;
+                errorf!("\nFAIL\n{:?}\n!=\n{:?}\n", syn_ast, libsyntax_ast);
+            }
+        }
+    });
+
+    (passed, failed)
+}
+
+fn libsyntax_parse_and_rewrite(input: &str) -> Option<P<ast::Expr>> {
+    parse::libsyntax_expr(input).and_then(libsyntax_brackets)
+}
+
+/// Wrap every expression which is not already wrapped in parens with parens, to
+/// reveal the precidence of the parsed expressions, and produce a stringified
+/// form of the resulting expression.
+///
+/// This method operates on libsyntax objects.
+fn libsyntax_brackets(libsyntax_expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
+    use rustc_data_structures::small_vec::OneVector;
+    use rustc_data_structures::thin_vec::ThinVec;
+    use syntax::ast::{Expr, ExprKind, Field, Mac, Pat, Stmt, StmtKind, Ty};
+    use syntax::ext::quote::rt::DUMMY_SP;
+    use syntax::fold::{self, Folder};
+
+    struct BracketsFolder {
+        failed: bool,
+    };
+    impl Folder for BracketsFolder {
+        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
+            e.map(|e| match e.node {
+                ExprKind::If(..) | ExprKind::Block(..) | ExprKind::IfLet(..) => {
+                    fold::noop_fold_expr(e, self)
+                }
+                _ => Expr {
+                    id: ast::DUMMY_NODE_ID,
+                    node: ExprKind::Paren(P(fold::noop_fold_expr(e, self))),
+                    span: DUMMY_SP,
+                    attrs: ThinVec::new(),
+                },
+            })
+        }
+
+        fn fold_field(&mut self, f: Field) -> Field {
+            Field {
+                expr: if f.is_shorthand {
+                    f.expr.map(|e| fold::noop_fold_expr(e, self))
+                } else {
+                    self.fold_expr(f.expr)
+                },
+                ..f
+            }
+        }
+
+        // We don't want to look at expressions that might appear in patterns or
+        // types yet. We'll look into comparing those in the future. For now
+        // focus on expressions appearing in other places.
+        fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
+            pat
+        }
+
+        fn fold_ty(&mut self, ty: P<Ty>) -> P<Ty> {
+            ty
+        }
+
+        fn fold_stmt(&mut self, stmt: Stmt) -> OneVector<Stmt> {
+            let node = match stmt.node {
+                // Don't wrap toplevel expressions in statements.
+                StmtKind::Expr(e) => StmtKind::Expr(e.map(|e| fold::noop_fold_expr(e, self))),
+                StmtKind::Semi(e) => StmtKind::Semi(e.map(|e| fold::noop_fold_expr(e, self))),
+                s => s,
+            };
+
+            OneVector::from_vec(vec![Stmt { node, ..stmt }])
+        }
+
+        fn fold_mac(&mut self, mac: Mac) -> Mac {
+            // By default when folding over macros, libsyntax panics. This is
+            // because it's usually not what you want, you want to run after
+            // macro expansion. We do want to do that (syn doesn't do macro
+            // expansion), so we implement fold_mac to just return the macro
+            // unchanged.
+            mac
+        }
+    }
+
+    let mut folder = BracketsFolder { failed: false };
+    let e = folder.fold_expr(libsyntax_expr);
+    if folder.failed {
+        None
+    } else {
+        Some(e)
+    }
+}
+
+/// Wrap every expression which is not already wrapped in parens with parens, to
+/// reveal the precedence of the parsed expressions, and produce a stringified
+/// form of the resulting expression.
+fn syn_brackets(syn_expr: syn::Expr) -> syn::Expr {
+    use syn::fold::*;
+    use syn::*;
+
+    struct ParenthesizeEveryExpr;
+    impl Fold for ParenthesizeEveryExpr {
+        fn fold_expr(&mut self, expr: Expr) -> Expr {
+            match expr {
+                Expr::Group(_) => unreachable!(),
+                Expr::If(..) | Expr::Unsafe(..) | Expr::Block(..) | Expr::IfLet(..) => {
+                    fold_expr(self, expr)
+                }
+                node => Expr::Paren(ExprParen {
+                    attrs: Vec::new(),
+                    expr: Box::new(fold_expr(self, node)),
+                    paren_token: token::Paren::default(),
+                }),
+            }
+        }
+
+        fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
+            match stmt {
+                // Don't wrap toplevel expressions in statements.
+                Stmt::Expr(e) => Stmt::Expr(fold_expr(self, e)),
+                Stmt::Semi(e, semi) => Stmt::Semi(fold_expr(self, e), semi),
+                s => s,
+            }
+        }
+
+        // We don't want to look at expressions that might appear in patterns or
+        // types yet. We'll look into comparing those in the future. For now
+        // focus on expressions appearing in other places.
+        fn fold_pat(&mut self, pat: Pat) -> Pat {
+            pat
+        }
+
+        fn fold_type(&mut self, ty: Type) -> Type {
+            ty
+        }
+    }
+
+    let mut folder = ParenthesizeEveryExpr;
+    folder.fold_expr(syn_expr)
+}
+
+/// Walk through a crate collecting all expressions we can find in it.
+fn collect_exprs(file: syn::File) -> Vec<syn::Expr> {
+    use syn::fold::*;
+    use syn::punctuated::Punctuated;
+    use syn::*;
+
+    struct CollectExprs(Vec<Expr>);
+    impl Fold for CollectExprs {
+        fn fold_expr(&mut self, expr: Expr) -> Expr {
+            self.0.push(expr);
+
+            Expr::Tuple(ExprTuple {
+                attrs: vec![],
+                elems: Punctuated::new(),
+                paren_token: token::Paren::default(),
+            })
+        }
+    }
+
+    let mut folder = CollectExprs(vec![]);
+    folder.fold_file(file);
+    folder.0
+}
diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs
new file mode 100644
index 0000000..87c1a04
--- /dev/null
+++ b/tests/test_round_trip.rs
@@ -0,0 +1,156 @@
+// 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 = "full")]
+#![recursion_limit = "1024"]
+#![feature(rustc_private)]
+
+#[macro_use]
+extern crate quote;
+extern crate rayon;
+extern crate syn;
+extern crate syntax;
+extern crate syntax_pos;
+extern crate walkdir;
+
+use rayon::iter::{IntoParallelIterator, ParallelIterator};
+use syntax::ast;
+use syntax::parse::{self, PResult, ParseSess};
+use syntax::source_map::FilePathMapping;
+use syntax_pos::FileName;
+use walkdir::{DirEntry, WalkDir};
+
+use std::fs::File;
+use std::io::Read;
+use std::panic;
+use std::process;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::time::Instant;
+
+#[macro_use]
+mod macros;
+
+#[allow(dead_code)]
+mod common;
+
+use common::eq::SpanlessEq;
+
+#[test]
+fn test_round_trip() {
+    common::check_min_stack();
+    common::clone_rust();
+    let abort_after = common::abort_after();
+    if abort_after == 0 {
+        panic!("Skipping all round_trip tests");
+    }
+
+    let failed = AtomicUsize::new(0);
+
+    WalkDir::new("tests/rust")
+        .sort_by(|a, b| a.file_name().cmp(b.file_name()))
+        .into_iter()
+        .filter_entry(common::base_dir_filter)
+        .collect::<Result<Vec<DirEntry>, walkdir::Error>>()
+        .unwrap()
+        .into_par_iter()
+        .for_each(|entry| {
+            let path = entry.path();
+            if path.is_dir() {
+                return;
+            }
+
+            let mut file = File::open(path).unwrap();
+            let mut content = String::new();
+            file.read_to_string(&mut content).unwrap();
+
+            let start = Instant::now();
+            let (krate, elapsed) = match syn::parse_file(&content) {
+                Ok(krate) => (krate, start.elapsed()),
+                Err(msg) => {
+                    errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg);
+                    let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
+                    if prev_failed + 1 >= abort_after {
+                        process::exit(1);
+                    }
+                    return;
+                }
+            };
+            let back = quote!(#krate).to_string();
+
+            let equal = panic::catch_unwind(|| {
+                syntax::with_globals(|| {
+                    let sess = ParseSess::new(FilePathMapping::empty());
+                    let before = match libsyntax_parse(content, &sess) {
+                        Ok(before) => before,
+                        Err(mut diagnostic) => {
+                            diagnostic.cancel();
+                            if diagnostic
+                                .message()
+                                .starts_with("file not found for module")
+                            {
+                                errorf!("=== {}: ignore\n", path.display());
+                            } else {
+                                errorf!(
+                                "=== {}: ignore - libsyntax failed to parse original content: {}\n",
+                                path.display(),
+                                diagnostic.message()
+                            );
+                            }
+                            return true;
+                        }
+                    };
+                    let after = match libsyntax_parse(back, &sess) {
+                        Ok(after) => after,
+                        Err(mut diagnostic) => {
+                            errorf!("=== {}: libsyntax failed to parse", path.display());
+                            diagnostic.emit();
+                            return false;
+                        }
+                    };
+
+                    if SpanlessEq::eq(&before, &after) {
+                        errorf!(
+                            "=== {}: pass in {}ms\n",
+                            path.display(),
+                            elapsed.as_secs() * 1000
+                                + u64::from(elapsed.subsec_nanos()) / 1_000_000
+                        );
+                        true
+                    } else {
+                        errorf!(
+                            "=== {}: FAIL\nbefore: {:#?}\nafter: {:#?}\n",
+                            path.display(),
+                            before,
+                            after,
+                        );
+                        false
+                    }
+                })
+            });
+            match equal {
+                Err(_) => errorf!("=== {}: ignoring libsyntax panic\n", path.display()),
+                Ok(true) => {}
+                Ok(false) => {
+                    let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
+                    if prev_failed + 1 >= abort_after {
+                        process::exit(1);
+                    }
+                }
+            }
+        });
+
+    let failed = failed.load(Ordering::SeqCst);
+    if failed > 0 {
+        panic!("{} failures", failed);
+    }
+}
+
+fn libsyntax_parse(content: String, sess: &ParseSess) -> PResult<ast::Crate> {
+    let name = FileName::Custom("test_round_trip".to_string());
+    parse::parse_crate_from_source_str(name, content, sess)
+}
diff --git a/tests/test_should_parse.rs b/tests/test_should_parse.rs
new file mode 100644
index 0000000..03096e3
--- /dev/null
+++ b/tests/test_should_parse.rs
@@ -0,0 +1,54 @@
+// 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.
+
+extern crate syn;
+
+macro_rules! should_parse {
+    ($name:ident, { $($in:tt)* }) => {
+        #[test]
+        fn $name() {
+            // Make sure we can parse the file!
+            syn::parse_file(stringify!($($in)*)).unwrap();
+        }
+    }
+}
+
+should_parse!(generic_associated_type, {
+    impl Foo {
+        type Item = &'a i32;
+        fn foo<'a>(&'a self) -> Self::Item<'a> {}
+    }
+});
+
+should_parse!(const_generics_use, {
+    type X = Foo<5>;
+    type Y = Foo<"foo">;
+    type Z = Foo<X>;
+    type W = Foo<{ X + 10 }>;
+});
+
+should_parse!(trailing_plus_type, {
+    type A = Box<Foo>;
+    type A = Box<Foo + 'a>;
+    type A = Box<'a + Foo>;
+});
+
+should_parse!(generic_associated_type_where, {
+    trait Foo {
+        type Item;
+        fn foo<T>(&self, t: T) -> Self::Item<T>;
+    }
+});
+
+should_parse!(match_with_block_expr, {
+    fn main() {
+        match false {
+            _ => {}.a(),
+        }
+    }
+});
diff --git a/tests/test_token_trees.rs b/tests/test_token_trees.rs
new file mode 100644
index 0000000..02d8f48
--- /dev/null
+++ b/tests/test_token_trees.rs
@@ -0,0 +1,100 @@
+// 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;
+#[macro_use]
+extern crate quote;
+extern crate syn;
+
+use proc_macro2::Delimiter::*;
+use proc_macro2::*;
+use syn::{AttrStyle, Attribute, Lit};
+
+fn alone(c: char) -> TokenTree {
+    Punct::new(c, Spacing::Alone).into()
+}
+
+fn joint(c: char) -> TokenTree {
+    Punct::new(c, Spacing::Joint).into()
+}
+
+fn delimited(delim: Delimiter, tokens: Vec<TokenTree>) -> TokenTree {
+    Group::new(delim, tokens.into_iter().collect()).into()
+}
+
+fn word(sym: &str) -> TokenTree {
+    Ident::new(sym, Span::call_site()).into()
+}
+
+#[test]
+fn test_struct() {
+    let raw = "
+        #[derive(Debug, Clone)]
+        pub struct Item {
+            pub ident: Ident,
+            pub attrs: Vec<Attribute>,
+        }
+    ";
+
+    let expected = vec![
+        alone('#'),
+        delimited(
+            Bracket,
+            vec![
+                word("derive"),
+                delimited(Parenthesis, vec![word("Debug"), alone(','), word("Clone")]),
+            ],
+        ),
+        word("pub"),
+        word("struct"),
+        word("Item"),
+        delimited(
+            Brace,
+            vec![
+                word("pub"),
+                word("ident"),
+                alone(':'),
+                word("Ident"),
+                alone(','),
+                word("pub"),
+                word("attrs"),
+                alone(':'),
+                word("Vec"),
+                alone('<'),
+                word("Attribute"),
+                joint('>'),
+                alone(','),
+            ],
+        ),
+    ];
+
+    fn wrap(tts: TokenStream) -> Attribute {
+        Attribute {
+            style: AttrStyle::Outer,
+            pound_token: Default::default(),
+            bracket_token: Default::default(),
+            path: Ident::new("test", Span::call_site()).into(),
+            tts,
+        }
+    }
+
+    let result = wrap(raw.parse().unwrap());
+    let expected = wrap(expected.into_iter().collect());
+    if result != expected {
+        panic!("{:#?}\n!=\n{:#?}", result.tts, expected.tts);
+    }
+}
+
+#[test]
+fn test_literal_mangling() {
+    let raw = "0_4";
+    let parsed: Lit = syn::parse_str(raw).unwrap();
+    assert_eq!(raw, quote!(#parsed).to_string());
+}