Merge pull request #629 from bstrie/exprs

Tentative beginning to implementing Parse for Expr types
diff --git a/Cargo.toml b/Cargo.toml
index e1a3e42..6658cc8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "syn"
-version = "0.15.31" # don't forget to update html_root_url and syn.json
+version = "0.15.33" # don't forget to update html_root_url and syn.json
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 license = "MIT/Apache-2.0"
 description = "Parser for Rust source code"
diff --git a/build.rs b/build.rs
index 644bf75..2b2a419 100644
--- a/build.rs
+++ b/build.rs
@@ -15,6 +15,10 @@
         println!("cargo:rustc-cfg=syn_can_use_thread_id");
     }
 
+    if compiler.minor >= 20 {
+        println!("cargo:rustc-cfg=syn_can_use_associated_constants");
+    }
+
     // Macro modularization allows re-exporting the `quote!` macro in 1.30+.
     if compiler.minor >= 30 {
         println!("cargo:rustc-cfg=syn_can_call_macro_by_path");
diff --git a/dev/README.md b/dev/README.md
new file mode 100644
index 0000000..91b9846
--- /dev/null
+++ b/dev/README.md
@@ -0,0 +1,6 @@
+A little project skeleton for troubleshooting Syn's parsers during development,
+especially when adding support for new Rust syntax.
+
+Place a sample of the syntax you are working on into main.rs and then run `cargo
+check` to try parsing it, revealing the resulting syntax tree or else showing
+the position and error message if the input fails to parse.
diff --git a/examples/heapsize/README.md b/examples/heapsize/README.md
index 1e36baf..a1f32d9 100644
--- a/examples/heapsize/README.md
+++ b/examples/heapsize/README.md
@@ -31,12 +31,12 @@
 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> {
+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)
+        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/heapsize_derive/src/lib.rs b/examples/heapsize/heapsize_derive/src/lib.rs
index ad9bb48..9176b29 100644
--- a/examples/heapsize/heapsize_derive/src/lib.rs
+++ b/examples/heapsize/heapsize_derive/src/lib.rs
@@ -22,7 +22,7 @@
 
     let expanded = quote! {
         // The generated impl.
-        impl #impl_generics ::heapsize::HeapSize for #name #ty_generics #where_clause {
+        impl #impl_generics heapsize::HeapSize for #name #ty_generics #where_clause {
             fn heap_size_of_children(&self) -> usize {
                 #sum
             }
@@ -37,7 +37,7 @@
 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));
+            type_param.bounds.push(parse_quote!(heapsize::HeapSize));
         }
     }
     generics
@@ -64,7 +64,7 @@
                     let recurse = fields.named.iter().map(|f| {
                         let name = &f.ident;
                         quote_spanned! {f.span()=>
-                            ::heapsize::HeapSize::heap_size_of_children(&self.#name)
+                            heapsize::HeapSize::heap_size_of_children(&self.#name)
                         }
                     });
                     quote! {
@@ -78,7 +78,7 @@
                     let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| {
                         let index = Index::from(i);
                         quote_spanned! {f.span()=>
-                            ::heapsize::HeapSize::heap_size_of_children(&self.#index)
+                            heapsize::HeapSize::heap_size_of_children(&self.#index)
                         }
                     });
                     quote! {
diff --git a/examples/lazy-static/lazy-static/src/lib.rs b/examples/lazy-static/lazy-static/src/lib.rs
index f90ea8b..5481a30 100644
--- a/examples/lazy-static/lazy-static/src/lib.rs
+++ b/examples/lazy-static/lazy-static/src/lib.rs
@@ -98,7 +98,7 @@
     //     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;
+        struct _AssertSync where #ty: std::marker::Sync;
     };
 
     // Check for Sized. Not vital to check here, but the error message is less
@@ -111,7 +111,7 @@
     //     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;
+        struct _AssertSized where #ty: std::marker::Sized;
     };
 
     let init_ptr = quote_spanned! {init.span()=>
@@ -121,14 +121,14 @@
     let expanded = quote! {
         #visibility struct #name;
 
-        impl ::std::ops::Deref for #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 ONCE: std::sync::Once = std::sync::ONCE_INIT;
                 static mut VALUE: *mut #ty = 0 as *mut #ty;
 
                 unsafe {
diff --git a/src/attr.rs b/src/attr.rs
index d1e7dca..ae90eaa 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -133,8 +133,8 @@
 }
 
 impl Attribute {
-    /// Parses the tokens after the path as a [`Meta`](enum.Meta.html) if
-    /// possible.
+    /// Parses the content of the attribute, consisting of the path and tts, as
+    /// a [`Meta`](enum.Meta.html) if possible.
     ///
     /// Deprecated; use `parse_meta` instead.
     #[doc(hidden)]
@@ -174,8 +174,8 @@
         }
     }
 
-    /// Parses the tokens after the path as a [`Meta`](enum.Meta.html) if
-    /// possible.
+    /// Parses the content of the attribute, consisting of the path and tts, as
+    /// a [`Meta`](enum.Meta.html) if possible.
     #[cfg(feature = "parsing")]
     pub fn parse_meta(&self) -> Result<Meta> {
         if let Some(ref colon) = self.path.leading_colon {
diff --git a/src/error.rs b/src/error.rs
index e07051d..097a6b8 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,5 +1,5 @@
 use std;
-use std::fmt::{self, Display};
+use std::fmt::{self, Debug, Display};
 use std::iter::FromIterator;
 
 use proc_macro2::{
@@ -24,7 +24,6 @@
 /// [module documentation]: index.html
 ///
 /// *This type is available if Syn is built with the `"parsing"` feature.*
-#[derive(Debug)]
 pub struct Error {
     // Span is implemented as an index into a thread-local interner to keep the
     // size small. It is not safe to access from a different thread. We want
@@ -181,6 +180,12 @@
     }
 }
 
+impl Debug for Error {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.debug_tuple("Error").field(&self.message).finish()
+    }
+}
+
 impl Display for Error {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         formatter.write_str(&self.message)
diff --git a/src/expr.rs b/src/expr.rs
index b050e59..8889be8 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -36,9 +36,10 @@
     ///     Expr::If(expr) => {
     ///         /* ... */
     ///     }
+    ///
     ///     /* ... */
     ///     # _ => {}
-    /// }
+    /// # }
     /// # }
     /// ```
     ///
@@ -50,28 +51,15 @@
     /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
     /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
     ///
-    /// The pattern is similar if the input expression is borrowed:
-    ///
-    /// ```edition2018
-    /// # use syn::Expr;
-    /// #
-    /// # fn example(expr: &Expr) {
-    /// match *expr {
-    ///     Expr::MethodCall(ref expr) => {
-    /// #   }
-    /// #   _ => {}
-    /// # }
-    /// # }
-    /// ```
-    ///
     /// This approach avoids repeating the variant names twice on every line.
     ///
     /// ```edition2018
     /// # use syn::{Expr, ExprMethodCall};
     /// #
     /// # fn example(expr: Expr) {
-    /// # match expr {
-    /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
+    /// // Repetitive; recommend not doing this.
+    /// match expr {
+    ///     Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
     /// # }
     /// # _ => {}
     /// # }
@@ -84,10 +72,10 @@
     /// ```edition2018
     /// # use syn::{Expr, ExprField};
     /// #
-    /// # fn example(discriminant: &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 {
+    /// if let Expr::Tuple(base) = *discriminant.base {
     /// # }
     /// # }
     /// ```
diff --git a/src/ext.rs b/src/ext.rs
index ca6d70d..17721d5 100644
--- a/src/ext.rs
+++ b/src/ext.rs
@@ -6,22 +6,38 @@
 
 use parse::{ParseStream, Result};
 
-/// Additional parsing methods for `Ident`.
+#[cfg(syn_can_use_associated_constants)]
+use buffer::Cursor;
+#[cfg(syn_can_use_associated_constants)]
+use parse::Peek;
+#[cfg(syn_can_use_associated_constants)]
+use sealed::lookahead;
+#[cfg(syn_can_use_associated_constants)]
+use token::CustomToken;
+
+/// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro.
 ///
-/// This trait is sealed and cannot be implemented for types outside of Syn.
+/// This trait is sealed and cannot be implemented for types outside of Syn. It
+/// is implemented only for `proc_macro2::Ident`.
 ///
 /// *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
+    /// This is useful when parsing macro input which allows Rust keywords as
     /// identifiers.
     ///
+    /// # Example
+    ///
     /// ```edition2018
     /// use syn::{Error, Ident, Result, Token};
     /// use syn::ext::IdentExt;
     /// use syn::parse::ParseStream;
     ///
+    /// mod kw {
+    ///     syn::custom_keyword!(name);
+    /// }
+    ///
     /// // Parses input that looks like `name = NAME` where `NAME` can be
     /// // any identifier.
     /// //
@@ -30,16 +46,51 @@
     /// //     name = anything
     /// //     name = impl
     /// fn parse_dsl(input: ParseStream) -> Result<Ident> {
-    ///     let name_token: Ident = input.parse()?;
-    ///     if name_token != "name" {
-    ///         return Err(Error::new(name_token.span(), "expected `name`"));
-    ///     }
+    ///     input.parse::<kw::name>()?;
     ///     input.parse::<Token![=]>()?;
     ///     let name = input.call(Ident::parse_any)?;
     ///     Ok(name)
     /// }
     /// ```
     fn parse_any(input: ParseStream) -> Result<Self>;
+
+    /// Peeks any identifier including keywords. Usage:
+    /// `input.peek(Ident::peek_any)`
+    ///
+    /// This is different from `input.peek(Ident)` which only returns true in
+    /// the case of an ident which is not a Rust keyword.
+    #[cfg(syn_can_use_associated_constants)]
+    #[allow(non_upper_case_globals)]
+    const peek_any: private::PeekFn = private::PeekFn;
+
+    /// Strips the raw marker `r#`, if any, from the beginning of an ident.
+    ///
+    ///   - unraw(`x`) = `x`
+    ///   - unraw(`move`) = `move`
+    ///   - unraw(`r#move`) = `move`
+    ///
+    /// # Example
+    ///
+    /// In the case of interop with other languages like Python that have a
+    /// different set of keywords than Rust, we might come across macro input
+    /// that involves raw identifiers to refer to ordinary variables in the
+    /// other language with a name that happens to be a Rust keyword.
+    ///
+    /// The function below appends an identifier from the caller's input onto a
+    /// fixed prefix. Without using `unraw()`, this would tend to produce
+    /// invalid identifiers like `__pyo3_get_r#move`.
+    ///
+    /// ```edition2018
+    /// use proc_macro2::Span;
+    /// use syn::Ident;
+    /// use syn::ext::IdentExt;
+    ///
+    /// fn ident_for_getter(variable: &Ident) -> Ident {
+    ///     let getter = format!("__pyo3_get_{}", variable.unraw());
+    ///     Ident::new(&getter, Span::call_site())
+    /// }
+    /// ```
+    fn unraw(&self) -> Ident;
 }
 
 impl IdentExt for Ident {
@@ -49,12 +100,46 @@
             None => Err(cursor.error("expected ident")),
         })
     }
+
+    fn unraw(&self) -> Ident {
+        let string = self.to_string();
+        if string.starts_with("r#") {
+            Ident::new(&string[2..], self.span())
+        } else {
+            self.clone()
+        }
+    }
 }
 
+#[cfg(syn_can_use_associated_constants)]
+impl Peek for private::PeekFn {
+    type Token = private::IdentAny;
+}
+
+#[cfg(syn_can_use_associated_constants)]
+impl CustomToken for private::IdentAny {
+    fn peek(cursor: Cursor) -> bool {
+        cursor.ident().is_some()
+    }
+
+    fn display() -> &'static str {
+        "identifier"
+    }
+}
+
+#[cfg(syn_can_use_associated_constants)]
+impl lookahead::Sealed for private::PeekFn {}
+
 mod private {
     use proc_macro2::Ident;
 
     pub trait Sealed {}
 
     impl Sealed for Ident {}
+
+    #[cfg(syn_can_use_associated_constants)]
+    #[derive(Copy, Clone)]
+    pub struct PeekFn;
+    #[cfg(syn_can_use_associated_constants)]
+    pub struct IdentAny;
 }
diff --git a/src/item.rs b/src/item.rs
index 9b5b7ea..118ed4e 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -1190,7 +1190,7 @@
             colon_token: input.parse()?,
             ty: match input.parse::<Token![...]>() {
                 Ok(dot3) => {
-                    let mut args = vec![
+                    let args = vec![
                         TokenTree::Punct(Punct::new('.', Spacing::Joint)),
                         TokenTree::Punct(Punct::new('.', Spacing::Joint)),
                         TokenTree::Punct(Punct::new('.', Spacing::Alone)),
diff --git a/src/lib.rs b/src/lib.rs
index ee867be..49d06c2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -222,7 +222,7 @@
 //!   dynamic library libproc_macro from rustc toolchain.
 
 // Syn types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/syn/0.15.31")]
+#![doc(html_root_url = "https://docs.rs/syn/0.15.33")]
 #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
 #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
 // Ignored clippy lints.
@@ -540,6 +540,7 @@
 
 mod custom_keyword;
 mod custom_punctuation;
+mod sealed;
 
 #[cfg(feature = "parsing")]
 mod lookahead;
diff --git a/src/lookahead.rs b/src/lookahead.rs
index 8ee1554..0f5afe1 100644
--- a/src/lookahead.rs
+++ b/src/lookahead.rs
@@ -4,6 +4,7 @@
 
 use buffer::Cursor;
 use error::{self, Error};
+use sealed::lookahead::Sealed;
 use span::IntoSpans;
 use token::Token;
 
@@ -94,7 +95,8 @@
     ///
     /// - `input.peek(Token![struct])`
     /// - `input.peek(Token![==])`
-    /// - `input.peek(Ident)`
+    /// - `input.peek(Ident)`&emsp;*(does not accept keywords)*
+    /// - `input.peek(Ident::peek_any)`
     /// - `input.peek(Lifetime)`
     /// - `input.peek(token::Brace)`
     pub fn peek<T: Peek>(&self, token: T) -> bool {
@@ -141,7 +143,7 @@
 /// This trait is sealed and cannot be implemented for types outside of Syn.
 ///
 /// [`ParseStream::peek`]: struct.ParseBuffer.html#method.peek
-pub trait Peek: private::Sealed {
+pub trait Peek: Sealed {
     // Not public API.
     #[doc(hidden)]
     type Token: Token;
@@ -163,8 +165,4 @@
     cursor.group(delimiter).is_some()
 }
 
-mod private {
-    use super::{Token, TokenMarker};
-    pub trait Sealed: Copy {}
-    impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}
-}
+impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}
diff --git a/src/parse.rs b/src/parse.rs
index 36f1caf..c5786e7 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -305,8 +305,8 @@
 ///     input.step(|cursor| {
 ///         let mut rest = *cursor;
 ///         while let Some((tt, next)) = rest.token_tree() {
-///             match tt {
-///                 TokenTree::Punct(ref punct) if punct.as_char() == '@' => {
+///             match &tt {
+///                 TokenTree::Punct(punct) if punct.as_char() == '@' => {
 ///                     return Ok(((), next));
 ///                 }
 ///                 _ => rest = next,
@@ -469,7 +469,8 @@
     ///
     /// - `input.peek(Token![struct])`
     /// - `input.peek(Token![==])`
-    /// - `input.peek(Ident)`
+    /// - `input.peek(Ident)`&emsp;*(does not accept keywords)*
+    /// - `input.peek(Ident::peek_any)`
     /// - `input.peek(Lifetime)`
     /// - `input.peek(token::Brace)`
     ///
@@ -901,8 +902,8 @@
     ///     input.step(|cursor| {
     ///         let mut rest = *cursor;
     ///         while let Some((tt, next)) = rest.token_tree() {
-    ///             match tt {
-    ///                 TokenTree::Punct(ref punct) if punct.as_char() == '@' => {
+    ///             match &tt {
+    ///                 TokenTree::Punct(punct) if punct.as_char() == '@' => {
     ///                     return Ok(((), next));
     ///                 }
     ///                 _ => rest = next,
diff --git a/src/parse_quote.rs b/src/parse_quote.rs
index 0b9d4d4..08012f5 100644
--- a/src/parse_quote.rs
+++ b/src/parse_quote.rs
@@ -39,7 +39,7 @@
 /// // 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 {
+///         if let GenericParam::Type(type_param) = param {
 ///             type_param.bounds.push(parse_quote!(HeapSize));
 ///         }
 ///     }
diff --git a/src/punctuated.rs b/src/punctuated.rs
index 6b29176..5aa519f 100644
--- a/src/punctuated.rs
+++ b/src/punctuated.rs
@@ -25,6 +25,7 @@
 #[cfg(any(feature = "full", feature = "derive"))]
 use std::iter;
 use std::iter::FromIterator;
+use std::marker::PhantomData;
 use std::ops::{Index, IndexMut};
 use std::option;
 use std::slice;
@@ -413,9 +414,13 @@
     type IntoIter = IntoIter<T, P>;
 
     fn into_iter(self) -> Self::IntoIter {
+        let mut elements = Vec::with_capacity(self.len());
+        elements.extend(self.inner.into_iter().map(|pair| pair.0));
+        elements.extend(self.last.map(|t| *t));
+
         IntoIter {
-            inner: self.inner.into_iter(),
-            last: self.last.map(|t| *t).into_iter(),
+            inner: elements.into_iter(),
+            marker: PhantomData,
         }
     }
 }
@@ -471,6 +476,16 @@
     }
 }
 
+// No Clone bound on T or P.
+impl<'a, T, P> Clone for Pairs<'a, T, P> {
+    fn clone(&self) -> Self {
+        Pairs {
+            inner: self.inner.clone(),
+            last: self.last.clone(),
+        }
+    }
+}
+
 /// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
 ///
 /// Refer to the [module documentation] for details about punctuated sequences.
@@ -503,6 +518,7 @@
 /// Refer to the [module documentation] for details about punctuated sequences.
 ///
 /// [module documentation]: index.html
+#[derive(Clone)]
 pub struct IntoPairs<T, P> {
     inner: vec::IntoIter<(T, P)>,
     last: option::IntoIter<T>,
@@ -530,25 +546,25 @@
 /// Refer to the [module documentation] for details about punctuated sequences.
 ///
 /// [module documentation]: index.html
+#[derive(Clone)]
 pub struct IntoIter<T, P> {
-    inner: vec::IntoIter<(T, P)>,
-    last: option::IntoIter<T>,
+    inner: vec::IntoIter<T>,
+
+    // TODO: remove P type parameter in the next breaking change
+    marker: PhantomData<P>,
 }
 
 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())
+        self.inner.next()
     }
 }
 
 impl<T, P> ExactSizeIterator for IntoIter<T, P> {
     fn len(&self) -> usize {
-        self.inner.len() + self.last.len()
+        self.inner.len()
     }
 }
 
@@ -558,7 +574,14 @@
 ///
 /// [module documentation]: index.html
 pub struct Iter<'a, T: 'a> {
-    inner: Box<ExactSizeIterator<Item = &'a T> + 'a>,
+    // The `Item = &'a T` needs to be specified to support rustc 1.31 and older.
+    // On modern compilers we would be able to write just IterTrait<'a, T> where
+    // Item can be inferred unambiguously from the supertrait.
+    inner: Box<IterTrait<'a, T, Item = &'a T> + 'a>,
+}
+
+trait IterTrait<'a, T: 'a>: ExactSizeIterator<Item = &'a T> {
+    fn clone_box(&self) -> Box<IterTrait<'a, T, Item = &'a T> + 'a>;
 }
 
 struct PrivateIter<'a, T: 'a, P: 'a> {
@@ -575,6 +598,15 @@
     }
 }
 
+// No Clone bound on T.
+impl<'a, T> Clone for Iter<'a, T> {
+    fn clone(&self) -> Self {
+        Iter {
+            inner: self.inner.clone_box(),
+        }
+    }
+}
+
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = &'a T;
 
@@ -606,6 +638,25 @@
     }
 }
 
+// No Clone bound on T or P.
+impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
+    fn clone(&self) -> Self {
+        PrivateIter {
+            inner: self.inner.clone(),
+            last: self.last.clone(),
+        }
+    }
+}
+
+impl<'a, T: 'a, I: 'a> IterTrait<'a, T> for I
+where
+    I: ExactSizeIterator<Item = &'a T> + Clone,
+{
+    fn clone_box(&self) -> Box<IterTrait<'a, T, Item = &'a T> + 'a> {
+        Box::new(self.clone())
+    }
+}
+
 /// An iterator over mutably borrowed values of type `&mut T`.
 ///
 /// Refer to the [module documentation] for details about punctuated sequences.
@@ -666,6 +717,7 @@
 /// Refer to the [module documentation] for details about punctuated sequences.
 ///
 /// [module documentation]: index.html
+#[cfg_attr(feature = "clone-impls", derive(Clone))]
 pub enum Pair<T, P> {
     Punctuated(T, P),
     End(T),
diff --git a/src/sealed.rs b/src/sealed.rs
new file mode 100644
index 0000000..0b11bc9
--- /dev/null
+++ b/src/sealed.rs
@@ -0,0 +1,4 @@
+#[cfg(feature = "parsing")]
+pub mod lookahead {
+    pub trait Sealed: Copy {}
+}
diff --git a/syn.json b/syn.json
index 8a023e5..13fcc1b 100644
--- a/syn.json
+++ b/syn.json
@@ -1,5 +1,5 @@
 {
-  "version": "0.15.31",
+  "version": "0.15.33",
   "types": [
     {
       "ident": "Abi",
diff --git a/tests/common/eq.rs b/tests/common/eq.rs
index 33699c7..5b0745e 100644
--- a/tests/common/eq.rs
+++ b/tests/common/eq.rs
@@ -10,19 +10,19 @@
 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, Guard, 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, ParenthesizedArgs, 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,
+    AngleBracketedArgs, AnonConst, Arg, ArgSource, Arm, AsmDialect, AsyncArgument, 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, Guard, Ident, ImplItem,
+    ImplItemKind, ImplPolarity, InlineAsm, InlineAsmOutput, IntTy, IsAsync, IsAuto, Item, ItemKind,
+    Label, Lifetime, LitIntType, LitKind, Local, LocalSource, MacDelimiter, MacStmtStyle, Mac_,
+    MacroDef, MethodSig, Mod, Movability, MutTy, Mutability, NodeId, ParenthesizedArgs, 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};
@@ -265,8 +265,9 @@
 
 spanless_eq_struct!(AngleBracketedArgs; span args bindings);
 spanless_eq_struct!(AnonConst; id value);
-spanless_eq_struct!(Arg; ty pat id);
+spanless_eq_struct!(Arg; ty pat id source);
 spanless_eq_struct!(Arm; attrs pats guard body);
+spanless_eq_struct!(AsyncArgument; ident arg move_stmt pat_stmt);
 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);
@@ -288,7 +289,7 @@
 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!(Local; pat ty init id span attrs source);
 spanless_eq_struct!(Mac_; path delim tts);
 spanless_eq_struct!(MacroDef; tokens legacy);
 spanless_eq_struct!(MethodSig; header decl);
@@ -312,6 +313,7 @@
 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!(ArgSource; Normal AsyncFn(0));
 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);
@@ -332,9 +334,10 @@
 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!(IsAsync; Async(closure_id return_impl_trait_id arguments) NotAsync);
 spanless_eq_enum!(IsAuto; Yes No);
 spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
+spanless_eq_enum!(LocalSource; Normal AsyncFn);
 spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
 spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
 spanless_eq_enum!(Movability; Static Movable);
@@ -433,7 +436,7 @@
             tokens.push(TokenTree::Token(DUMMY_SP, Token::Not));
         }
         let lit = Lit::Str_(Symbol::intern(&contents));
-        let mut tts = vec![
+        let 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)),