Bug 1663715 - Update syn and proc-macro2 so that Firefox can build on Rust nightly again. r=froydnj
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 08 Sep 2020 17:00:48 +0000
changeset 547906 e2cede25c027940ca4b36917a31163c278a4411f
parent 547905 a816580ea8a998b84f6dbddfe5683e2748455e5b
child 547907 d5da409374a343e9eab4e55e52e7c93e969561bc
push id125855
push userealvarez@mozilla.com
push dateTue, 08 Sep 2020 21:59:40 +0000
treeherderautoland@e2cede25c027 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1663715, 76482
milestone82.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1663715 - Update syn and proc-macro2 so that Firefox can build on Rust nightly again. r=froydnj Generated with: cargo update -p syn --precise 1.0.40 ./mach vendor rust Rust issue: https://github.com/rust-lang/rust/issues/76482 Differential Revision: https://phabricator.services.mozilla.com/D89473
Cargo.lock
third_party/rust/proc-macro2/.cargo-checksum.json
third_party/rust/proc-macro2/Cargo.toml
third_party/rust/proc-macro2/README.md
third_party/rust/proc-macro2/build.rs
third_party/rust/proc-macro2/src/detection.rs
third_party/rust/proc-macro2/src/fallback.rs
third_party/rust/proc-macro2/src/lib.rs
third_party/rust/proc-macro2/src/parse.rs
third_party/rust/proc-macro2/src/strnom.rs
third_party/rust/proc-macro2/src/wrapper.rs
third_party/rust/proc-macro2/tests/comments.rs
third_party/rust/proc-macro2/tests/test.rs
third_party/rust/proc-macro2/tests/test_fmt.rs
third_party/rust/syn/.cargo-checksum.json
third_party/rust/syn/Cargo.toml
third_party/rust/syn/README.md
third_party/rust/syn/benches/file.rs
third_party/rust/syn/benches/rust.rs
third_party/rust/syn/build.rs
third_party/rust/syn/src/attr.rs
third_party/rust/syn/src/buffer.rs
third_party/rust/syn/src/custom_keyword.rs
third_party/rust/syn/src/custom_punctuation.rs
third_party/rust/syn/src/data.rs
third_party/rust/syn/src/derive.rs
third_party/rust/syn/src/discouraged.rs
third_party/rust/syn/src/error.rs
third_party/rust/syn/src/expr.rs
third_party/rust/syn/src/ext.rs
third_party/rust/syn/src/file.rs
third_party/rust/syn/src/gen/clone.rs
third_party/rust/syn/src/gen/debug.rs
third_party/rust/syn/src/gen/eq.rs
third_party/rust/syn/src/gen/fold.rs
third_party/rust/syn/src/gen/hash.rs
third_party/rust/syn/src/gen/visit.rs
third_party/rust/syn/src/gen/visit_mut.rs
third_party/rust/syn/src/generics.rs
third_party/rust/syn/src/item.rs
third_party/rust/syn/src/keyword.rs
third_party/rust/syn/src/lib.rs
third_party/rust/syn/src/lifetime.rs
third_party/rust/syn/src/lit.rs
third_party/rust/syn/src/mac.rs
third_party/rust/syn/src/macros.rs
third_party/rust/syn/src/op.rs
third_party/rust/syn/src/parse.rs
third_party/rust/syn/src/parse_macro_input.rs
third_party/rust/syn/src/parse_quote.rs
third_party/rust/syn/src/pat.rs
third_party/rust/syn/src/path.rs
third_party/rust/syn/src/punctuated.rs
third_party/rust/syn/src/reserved.rs
third_party/rust/syn/src/spanned.rs
third_party/rust/syn/src/stmt.rs
third_party/rust/syn/src/token.rs
third_party/rust/syn/src/tt.rs
third_party/rust/syn/src/ty.rs
third_party/rust/syn/src/verbatim.rs
third_party/rust/syn/src/whitespace.rs
third_party/rust/syn/tests/.gitignore
third_party/rust/syn/tests/clone.sh
third_party/rust/syn/tests/common/eq.rs
third_party/rust/syn/tests/common/mod.rs
third_party/rust/syn/tests/common/parse.rs
third_party/rust/syn/tests/debug/gen.rs
third_party/rust/syn/tests/debug/mod.rs
third_party/rust/syn/tests/features/error.rs
third_party/rust/syn/tests/features/mod.rs
third_party/rust/syn/tests/macros/mod.rs
third_party/rust/syn/tests/repo/mod.rs
third_party/rust/syn/tests/repo/progress.rs
third_party/rust/syn/tests/test_asyncness.rs
third_party/rust/syn/tests/test_attribute.rs
third_party/rust/syn/tests/test_derive_input.rs
third_party/rust/syn/tests/test_expr.rs
third_party/rust/syn/tests/test_generics.rs
third_party/rust/syn/tests/test_grouping.rs
third_party/rust/syn/tests/test_ident.rs
third_party/rust/syn/tests/test_item.rs
third_party/rust/syn/tests/test_iterators.rs
third_party/rust/syn/tests/test_lit.rs
third_party/rust/syn/tests/test_meta.rs
third_party/rust/syn/tests/test_parse_buffer.rs
third_party/rust/syn/tests/test_parse_stream.rs
third_party/rust/syn/tests/test_pat.rs
third_party/rust/syn/tests/test_path.rs
third_party/rust/syn/tests/test_precedence.rs
third_party/rust/syn/tests/test_receiver.rs
third_party/rust/syn/tests/test_round_trip.rs
third_party/rust/syn/tests/test_shebang.rs
third_party/rust/syn/tests/test_should_parse.rs
third_party/rust/syn/tests/test_size.rs
third_party/rust/syn/tests/test_stmt.rs
third_party/rust/syn/tests/test_token_trees.rs
third_party/rust/syn/tests/test_ty.rs
third_party/rust/syn/tests/test_visibility.rs
third_party/rust/syn/tests/zzz_stable.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3816,19 +3816,19 @@ checksum = "ecd45702f76d6d3c75a80564378a
 dependencies = [
  "proc-macro2",
  "quote",
  "syn",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0"
+version = "1.0.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "procedural-masquerade"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4812,19 +4812,19 @@ dependencies = [
  "cc",
  "gleam",
  "glsl-to-cxx",
  "webrender_build",
 ]
 
 [[package]]
 name = "syn"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
 dependencies = [
  "proc-macro2",
  "quote",
  "unicode-xid",
 ]
 
 [[package]]
 name = "sync-guid"
--- a/third_party/rust/proc-macro2/.cargo-checksum.json
+++ b/third_party/rust/proc-macro2/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"e2c1fc6ed317eeef8462fcd192f6b6389e1d84f0d7afeac78f12c23903deddf8","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"362a2156f7645528061b6e8487a2eb0f32f1693012ed82ee57afa05c039bba0d","build.rs":"0cc6e2cb919ddbff59cf1d810283939f97a59f0037540c0f2ee3453237635ff8","src/fallback.rs":"5c6379a90735e27abcc40253b223158c6b1e5784f3850bc423335363e87ef038","src/lib.rs":"ae5251296ad3fcd8b600919a993fec0afd8b56da3e11fef6bc7265b273129936","src/strnom.rs":"37f7791f73f123817ad5403af1d4e2a0714be27401729a2d451bc80b1f26bac9","src/wrapper.rs":"81372e910604217a625aa71c47d43e65f4e008456eae93ac39325c9abf10701a","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"c2652e3ae1dfcb94d2e6313b29712c5dcbd0fe62026913e67bb7cebd7560aade","tests/test.rs":"8c427be9cba1fa8d4a16647e53e3545e5863e29e2c0b311c93c9dd1399abf6a1"},"package":"90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0"}
\ No newline at end of file
+{"files":{"Cargo.toml":"c20c4c52342e65ea11ad8382edc636e628e8f8c5ab7cffddc32426b2fe8fe4cd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"e1f9d4fc22cff2c049f166a403b41458632a94357890d31cf0e3ad83807fb430","build.rs":"332185d7ad4c859210f5edd7a76bc95146c8277726a2f81417f34927c4424d68","src/detection.rs":"9d25d896889e65330858f2d6f6223c1b98cd1dad189813ad4161ff189fbda2b8","src/fallback.rs":"239f9a25c0f2ab57592288d944c7f1a0f887536b6d4dc2428a17640af8d10a41","src/lib.rs":"2b1d98424c9b23b547dabf85554120e5e65472026a0f3f711b3a097bca7c32fe","src/parse.rs":"500edee9773132e27e44d0fdaa042b1cb9451e29e65124493986f51710c0664c","src/wrapper.rs":"d36c0dced7ec0e7585c1f935cda836080bcae6de1de3d7851d962e9e11a3ac48","tests/comments.rs":"ea6cbe6f4c8852e6a0612893c7d4f2c144a2e6a134a6c3db641a320cbfc3c800","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"c2652e3ae1dfcb94d2e6313b29712c5dcbd0fe62026913e67bb7cebd7560aade","tests/test.rs":"310c856e27ff61c9ec7f0a5cd96031aac02971557b1621f5e17b089d58e79bcd","tests/test_fmt.rs":"745dfdc41d09c5308c221395eb43f2041f0a1413d2927a813bc2ad4554438fe2"},"package":"175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"}
\ No newline at end of file
--- a/third_party/rust/proc-macro2/Cargo.toml
+++ b/third_party/rust/proc-macro2/Cargo.toml
@@ -8,36 +8,35 @@
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 edition = "2018"
 name = "proc-macro2"
-version = "1.0.5"
-authors = ["Alex Crichton <alex@alexcrichton.com>"]
-description = "A stable implementation of the upcoming new `proc_macro` API. Comes with an\noption, off by default, to also reimplement itself in terms of the upstream\nunstable API.\n"
-homepage = "https://github.com/alexcrichton/proc-macro2"
+version = "1.0.20"
+authors = ["Alex Crichton <alex@alexcrichton.com>", "David Tolnay <dtolnay@gmail.com>"]
+description = "A substitute implementation of the compiler's `proc_macro` API to decouple\ntoken-based libraries from the procedural macro use case.\n"
 documentation = "https://docs.rs/proc-macro2"
 readme = "README.md"
 keywords = ["macros"]
+categories = ["development-tools::procedural-macro-helpers"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/alexcrichton/proc-macro2"
 [package.metadata.docs.rs]
 rustc-args = ["--cfg", "procmacro2_semver_exempt"]
 rustdoc-args = ["--cfg", "procmacro2_semver_exempt"]
+targets = ["x86_64-unknown-linux-gnu"]
 
-[lib]
-name = "proc_macro2"
+[package.metadata.playground]
+features = ["span-locations"]
 [dependencies.unicode-xid]
 version = "0.2"
 [dev-dependencies.quote]
 version = "1.0"
 default_features = false
 
 [features]
 default = ["proc-macro"]
 nightly = []
 proc-macro = []
 span-locations = []
-[badges.travis-ci]
-repository = "alexcrichton/proc-macro2"
--- a/third_party/rust/proc-macro2/README.md
+++ b/third_party/rust/proc-macro2/README.md
@@ -1,11 +1,11 @@
 # proc-macro2
 
-[![Build Status](https://api.travis-ci.com/alexcrichton/proc-macro2.svg?branch=master)](https://travis-ci.com/alexcrichton/proc-macro2)
+[![Build Status](https://img.shields.io/github/workflow/status/alexcrichton/proc-macro2/build%20and%20test)](https://github.com/alexcrichton/proc-macro2/actions)
 [![Latest Version](https://img.shields.io/crates/v/proc-macro2.svg)](https://crates.io/crates/proc-macro2)
 [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2)
 
 A wrapper around the procedural macro API of the compiler's `proc_macro` crate.
 This library serves two purposes:
 
 - **Bring proc-macro-like functionality to other contexts like build.rs and
   main.rs.** Types from `proc_macro` are entirely specific to procedural macros
--- a/third_party/rust/proc-macro2/build.rs
+++ b/third_party/rust/proc-macro2/build.rs
@@ -9,16 +9,20 @@
 // "wrap_proc_macro"
 //     Wrap types from libproc_macro rather than polyfilling the whole API.
 //     Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
 //     because we can't emulate the unstable API without emulating everything
 //     else. Also enabled unconditionally on nightly, in which case the
 //     procmacro2_semver_exempt surface area is implemented by using the
 //     nightly-only proc_macro API.
 //
+//  "hygiene"
+//    Enable Span::mixed_site() and non-dummy behavior of Span::resolved_at
+//    and Span::located_at. Enabled on Rust 1.45+.
+//
 // "proc_macro_span"
 //     Enable non-dummy behavior of Span::start and Span::end methods which
 //     requires an unstable compiler feature. Enabled when building with
 //     nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable
 //     features.
 //
 // "super_unstable"
 //     Implement the semver exempt API in terms of the nightly-only proc_macro
@@ -52,16 +56,24 @@ fn main() {
         // https://github.com/alexcrichton/proc-macro2/issues/147
         println!("cargo:rustc-cfg=procmacro2_semver_exempt");
     }
 
     if semver_exempt || cfg!(feature = "span-locations") {
         println!("cargo:rustc-cfg=span_locations");
     }
 
+    if version.minor < 39 {
+        println!("cargo:rustc-cfg=no_bind_by_move_pattern_guard");
+    }
+
+    if version.minor >= 45 {
+        println!("cargo:rustc-cfg=hygiene");
+    }
+
     let target = env::var("TARGET").unwrap();
     if !enable_use_proc_macro(&target) {
         return;
     }
 
     println!("cargo:rustc-cfg=use_proc_macro");
 
     if version.nightly || !semver_exempt {
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2/src/detection.rs
@@ -0,0 +1,67 @@
+use std::panic::{self, PanicInfo};
+use std::sync::atomic::*;
+use std::sync::Once;
+
+static WORKS: AtomicUsize = AtomicUsize::new(0);
+static INIT: Once = Once::new();
+
+pub(crate) fn inside_proc_macro() -> bool {
+    match WORKS.load(Ordering::SeqCst) {
+        1 => return false,
+        2 => return true,
+        _ => {}
+    }
+
+    INIT.call_once(initialize);
+    inside_proc_macro()
+}
+
+pub(crate) fn force_fallback() {
+    WORKS.store(1, Ordering::SeqCst);
+}
+
+pub(crate) fn unforce_fallback() {
+    initialize();
+}
+
+// Swap in a null panic hook to avoid printing "thread panicked" to stderr,
+// then use catch_unwind to determine whether the compiler's proc_macro is
+// working. When proc-macro2 is used from outside of a procedural macro all
+// of the proc_macro crate's APIs currently panic.
+//
+// The Once is to prevent the possibility of this ordering:
+//
+//     thread 1 calls take_hook, gets the user's original hook
+//     thread 1 calls set_hook with the null hook
+//     thread 2 calls take_hook, thinks null hook is the original hook
+//     thread 2 calls set_hook with the null hook
+//     thread 1 calls set_hook with the actual original hook
+//     thread 2 calls set_hook with what it thinks is the original hook
+//
+// in which the user's hook has been lost.
+//
+// There is still a race condition where a panic in a different thread can
+// happen during the interval that the user's original panic hook is
+// unregistered such that their hook is incorrectly not called. This is
+// sufficiently unlikely and less bad than printing panic messages to stderr
+// on correct use of this crate. Maybe there is a libstd feature request
+// here. For now, if a user needs to guarantee that this failure mode does
+// not occur, they need to call e.g. `proc_macro2::Span::call_site()` from
+// the main thread before launching any other threads.
+fn initialize() {
+    type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static;
+
+    let null_hook: Box<PanicHook> = Box::new(|_panic_info| { /* ignore */ });
+    let sanity_check = &*null_hook as *const PanicHook;
+    let original_hook = panic::take_hook();
+    panic::set_hook(null_hook);
+
+    let works = panic::catch_unwind(proc_macro::Span::call_site).is_ok();
+    WORKS.store(works as usize + 1, Ordering::SeqCst);
+
+    let hopefully_null_hook = panic::take_hook();
+    panic::set_hook(original_hook);
+    if sanity_check != &*hopefully_null_hook {
+        panic!("observed race condition in proc_macro2::inside_proc_macro");
+    }
+}
--- a/third_party/rust/proc-macro2/src/fallback.rs
+++ b/third_party/rust/proc-macro2/src/fallback.rs
@@ -1,41 +1,121 @@
+use crate::parse::{token_stream, Cursor};
+use crate::{Delimiter, Spacing, TokenTree};
 #[cfg(span_locations)]
 use std::cell::RefCell;
 #[cfg(span_locations)]
 use std::cmp;
-use std::fmt;
-use std::iter;
+use std::fmt::{self, Debug, Display};
+use std::iter::FromIterator;
+use std::mem;
 use std::ops::RangeBounds;
 #[cfg(procmacro2_semver_exempt)]
 use std::path::Path;
 use std::path::PathBuf;
 use std::str::FromStr;
 use std::vec;
-
-use crate::strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult};
-use crate::{Delimiter, Punct, Spacing, TokenTree};
 use unicode_xid::UnicodeXID;
 
+/// Force use of proc-macro2's fallback implementation of the API for now, even
+/// if the compiler's implementation is available.
+pub fn force() {
+    #[cfg(wrap_proc_macro)]
+    crate::detection::force_fallback();
+}
+
+/// Resume using the compiler's implementation of the proc macro API if it is
+/// available.
+pub fn unforce() {
+    #[cfg(wrap_proc_macro)]
+    crate::detection::unforce_fallback();
+}
+
 #[derive(Clone)]
-pub struct TokenStream {
-    inner: Vec<TokenTree>,
+pub(crate) struct TokenStream {
+    pub(crate) inner: Vec<TokenTree>,
 }
 
 #[derive(Debug)]
-pub struct LexError;
+pub(crate) struct LexError;
 
 impl TokenStream {
     pub fn new() -> TokenStream {
         TokenStream { inner: Vec::new() }
     }
 
     pub fn is_empty(&self) -> bool {
         self.inner.len() == 0
     }
+
+    fn take_inner(&mut self) -> Vec<TokenTree> {
+        mem::replace(&mut self.inner, Vec::new())
+    }
+
+    fn push_token(&mut self, token: TokenTree) {
+        // https://github.com/alexcrichton/proc-macro2/issues/235
+        match token {
+            #[cfg(not(no_bind_by_move_pattern_guard))]
+            TokenTree::Literal(crate::Literal {
+                #[cfg(wrap_proc_macro)]
+                    inner: crate::imp::Literal::Fallback(literal),
+                #[cfg(not(wrap_proc_macro))]
+                    inner: literal,
+                ..
+            }) if literal.text.starts_with('-') => {
+                push_negative_literal(self, literal);
+            }
+            #[cfg(no_bind_by_move_pattern_guard)]
+            TokenTree::Literal(crate::Literal {
+                #[cfg(wrap_proc_macro)]
+                    inner: crate::imp::Literal::Fallback(literal),
+                #[cfg(not(wrap_proc_macro))]
+                    inner: literal,
+                ..
+            }) => {
+                if literal.text.starts_with('-') {
+                    push_negative_literal(self, literal);
+                } else {
+                    self.inner
+                        .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
+                }
+            }
+            _ => self.inner.push(token),
+        }
+
+        #[cold]
+        fn push_negative_literal(stream: &mut TokenStream, mut literal: Literal) {
+            literal.text.remove(0);
+            let mut punct = crate::Punct::new('-', Spacing::Alone);
+            punct.set_span(crate::Span::_new_stable(literal.span));
+            stream.inner.push(TokenTree::Punct(punct));
+            stream
+                .inner
+                .push(TokenTree::Literal(crate::Literal::_new_stable(literal)));
+        }
+    }
+}
+
+// Nonrecursive to prevent stack overflow.
+impl Drop for TokenStream {
+    fn drop(&mut self) {
+        while let Some(token) = self.inner.pop() {
+            let group = match token {
+                TokenTree::Group(group) => group.inner,
+                _ => continue,
+            };
+            #[cfg(wrap_proc_macro)]
+            let group = match group {
+                crate::imp::Group::Fallback(group) => group,
+                _ => continue,
+            };
+            let mut group = group;
+            self.inner.extend(group.stream.take_inner());
+        }
+    }
 }
 
 #[cfg(span_locations)]
 fn get_cursor(src: &str) -> Cursor {
     // Create a dummy file & add it to the source map
     SOURCE_MAP.with(|cm| {
         let mut cm = cm.borrow_mut();
         let name = format!("<parsed string {}>", cm.files.len());
@@ -54,68 +134,49 @@ fn get_cursor(src: &str) -> Cursor {
 
 impl FromStr for TokenStream {
     type Err = LexError;
 
     fn from_str(src: &str) -> Result<TokenStream, LexError> {
         // Create a dummy file & add it to the source map
         let cursor = get_cursor(src);
 
-        match token_stream(cursor) {
-            Ok((input, output)) => {
-                if skip_whitespace(input).len() != 0 {
-                    Err(LexError)
-                } else {
-                    Ok(output)
-                }
-            }
-            Err(LexError) => Err(LexError),
+        let (rest, tokens) = token_stream(cursor)?;
+        if rest.is_empty() {
+            Ok(tokens)
+        } else {
+            Err(LexError)
         }
     }
 }
 
-impl fmt::Display for TokenStream {
+impl Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut joint = false;
         for (i, tt) in self.inner.iter().enumerate() {
             if i != 0 && !joint {
                 write!(f, " ")?;
             }
             joint = false;
-            match *tt {
-                TokenTree::Group(ref tt) => {
-                    let (start, end) = match tt.delimiter() {
-                        Delimiter::Parenthesis => ("(", ")"),
-                        Delimiter::Brace => ("{", "}"),
-                        Delimiter::Bracket => ("[", "]"),
-                        Delimiter::None => ("", ""),
-                    };
-                    if tt.stream().into_iter().next().is_none() {
-                        write!(f, "{} {}", start, end)?
-                    } else {
-                        write!(f, "{} {} {}", start, tt.stream(), end)?
-                    }
+            match tt {
+                TokenTree::Group(tt) => Display::fmt(tt, f),
+                TokenTree::Ident(tt) => Display::fmt(tt, f),
+                TokenTree::Punct(tt) => {
+                    joint = tt.spacing() == Spacing::Joint;
+                    Display::fmt(tt, f)
                 }
-                TokenTree::Ident(ref tt) => write!(f, "{}", tt)?,
-                TokenTree::Punct(ref tt) => {
-                    write!(f, "{}", tt.as_char())?;
-                    match tt.spacing() {
-                        Spacing::Alone => {}
-                        Spacing::Joint => joint = true,
-                    }
-                }
-                TokenTree::Literal(ref tt) => write!(f, "{}", tt)?,
-            }
+                TokenTree::Literal(tt) => Display::fmt(tt, f),
+            }?
         }
 
         Ok(())
     }
 }
 
-impl fmt::Debug for TokenStream {
+impl Debug for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str("TokenStream ")?;
         f.debug_list().entries(self.clone()).finish()
     }
 }
 
 #[cfg(use_proc_macro)]
 impl From<proc_macro::TokenStream> for TokenStream {
@@ -134,122 +195,107 @@ impl From<TokenStream> for proc_macro::T
             .to_string()
             .parse()
             .expect("failed to parse to compiler tokens")
     }
 }
 
 impl From<TokenTree> for TokenStream {
     fn from(tree: TokenTree) -> TokenStream {
-        TokenStream { inner: vec![tree] }
+        let mut stream = TokenStream::new();
+        stream.push_token(tree);
+        stream
     }
 }
 
-impl iter::FromIterator<TokenTree> for TokenStream {
-    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
-        let mut v = Vec::new();
-
-        for token in streams.into_iter() {
-            v.push(token);
-        }
-
-        TokenStream { inner: v }
+impl FromIterator<TokenTree> for TokenStream {
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
+        let mut stream = TokenStream::new();
+        stream.extend(tokens);
+        stream
     }
 }
 
-impl iter::FromIterator<TokenStream> for TokenStream {
+impl FromIterator<TokenStream> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
         let mut v = Vec::new();
 
-        for stream in streams.into_iter() {
-            v.extend(stream.inner);
+        for mut stream in streams {
+            v.extend(stream.take_inner());
         }
 
         TokenStream { inner: v }
     }
 }
 
 impl Extend<TokenTree> for TokenStream {
-    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
-        self.inner.extend(streams);
+    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
+        tokens.into_iter().for_each(|token| self.push_token(token));
     }
 }
 
 impl Extend<TokenStream> for TokenStream {
     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
-        self.inner
-            .extend(streams.into_iter().flat_map(|stream| stream));
+        self.inner.extend(streams.into_iter().flatten());
     }
 }
 
-pub type TokenTreeIter = vec::IntoIter<TokenTree>;
+pub(crate) type TokenTreeIter = vec::IntoIter<TokenTree>;
 
 impl IntoIterator for TokenStream {
     type Item = TokenTree;
     type IntoIter = TokenTreeIter;
 
-    fn into_iter(self) -> TokenTreeIter {
-        self.inner.into_iter()
+    fn into_iter(mut self) -> TokenTreeIter {
+        self.take_inner().into_iter()
     }
 }
 
 #[derive(Clone, PartialEq, Eq)]
-pub struct SourceFile {
+pub(crate) struct SourceFile {
     path: PathBuf,
 }
 
 impl SourceFile {
     /// Get the path to this source file as a string.
     pub fn path(&self) -> PathBuf {
         self.path.clone()
     }
 
     pub fn is_real(&self) -> bool {
         // XXX(nika): Support real files in the future?
         false
     }
 }
 
-impl fmt::Debug for SourceFile {
+impl Debug for SourceFile {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("SourceFile")
             .field("path", &self.path())
             .field("is_real", &self.is_real())
             .finish()
     }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct LineColumn {
+pub(crate) struct LineColumn {
     pub line: usize,
     pub column: usize,
 }
 
 #[cfg(span_locations)]
 thread_local! {
     static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
         // NOTE: We start with a single dummy file which all call_site() and
         // def_site() spans reference.
-        files: vec![{
+        files: vec![FileInfo {
             #[cfg(procmacro2_semver_exempt)]
-            {
-                FileInfo {
-                    name: "<unspecified>".to_owned(),
-                    span: Span { lo: 0, hi: 0 },
-                    lines: vec![0],
-                }
-            }
-
-            #[cfg(not(procmacro2_semver_exempt))]
-            {
-                FileInfo {
-                    span: Span { lo: 0, hi: 0 },
-                    lines: vec![0],
-                }
-            }
+            name: "<unspecified>".to_owned(),
+            span: Span { lo: 0, hi: 0 },
+            lines: vec![0],
         }],
     });
 }
 
 #[cfg(span_locations)]
 struct FileInfo {
     #[cfg(procmacro2_semver_exempt)]
     name: String,
@@ -277,26 +323,31 @@ impl FileInfo {
         }
     }
 
     fn span_within(&self, span: Span) -> bool {
         span.lo >= self.span.lo && span.hi <= self.span.hi
     }
 }
 
-/// Computesthe offsets of each line in the given source string.
+/// Computes the offsets of each line in the given source string
+/// and the total number of characters
 #[cfg(span_locations)]
-fn lines_offsets(s: &str) -> Vec<usize> {
+fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
     let mut lines = vec![0];
-    let mut prev = 0;
-    while let Some(len) = s[prev..].find('\n') {
-        prev += len + 1;
-        lines.push(prev);
+    let mut total = 0;
+
+    for ch in s.chars() {
+        total += 1;
+        if ch == '\n' {
+            lines.push(total);
+        }
     }
-    lines
+
+    (total, lines)
 }
 
 #[cfg(span_locations)]
 struct SourceMap {
     files: Vec<FileInfo>,
 }
 
 #[cfg(span_locations)]
@@ -305,81 +356,83 @@ impl SourceMap {
         // Add 1 so there's always space between files.
         //
         // We'll always have at least 1 file, as we initialize our files list
         // with a dummy file.
         self.files.last().unwrap().span.hi + 1
     }
 
     fn add_file(&mut self, name: &str, src: &str) -> Span {
-        let lines = lines_offsets(src);
+        let (len, lines) = lines_offsets(src);
         let lo = self.next_start_pos();
         // XXX(nika): Shouild we bother doing a checked cast or checked add here?
         let span = Span {
             lo,
-            hi: lo + (src.len() as u32),
+            hi: lo + (len as u32),
         };
 
-        #[cfg(procmacro2_semver_exempt)]
         self.files.push(FileInfo {
+            #[cfg(procmacro2_semver_exempt)]
             name: name.to_owned(),
             span,
             lines,
         });
 
         #[cfg(not(procmacro2_semver_exempt))]
-        self.files.push(FileInfo { span, lines });
         let _ = name;
 
         span
     }
 
     fn fileinfo(&self, span: Span) -> &FileInfo {
         for file in &self.files {
             if file.span_within(span) {
                 return file;
             }
         }
         panic!("Invalid span with no related FileInfo!");
     }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq)]
-pub struct Span {
+pub(crate) struct Span {
     #[cfg(span_locations)]
-    lo: u32,
+    pub(crate) lo: u32,
     #[cfg(span_locations)]
-    hi: u32,
+    pub(crate) hi: u32,
 }
 
 impl Span {
     #[cfg(not(span_locations))]
     pub fn call_site() -> Span {
         Span {}
     }
 
     #[cfg(span_locations)]
     pub fn call_site() -> Span {
         Span { lo: 0, hi: 0 }
     }
 
+    #[cfg(hygiene)]
+    pub fn mixed_site() -> Span {
+        Span::call_site()
+    }
+
     #[cfg(procmacro2_semver_exempt)]
     pub fn def_site() -> Span {
         Span::call_site()
     }
 
-    #[cfg(procmacro2_semver_exempt)]
     pub fn resolved_at(&self, _other: Span) -> Span {
         // Stable spans consist only of line/column information, so
         // `resolved_at` and `located_at` only select which span the
         // caller wants line/column information from.
         *self
     }
 
-    #[cfg(procmacro2_semver_exempt)]
     pub fn located_at(&self, other: Span) -> Span {
         other
     }
 
     #[cfg(procmacro2_semver_exempt)]
     pub fn source_file(&self) -> SourceFile {
         SOURCE_MAP.with(|cm| {
             let cm = cm.borrow();
@@ -422,36 +475,69 @@ impl Span {
                 return None;
             }
             Some(Span {
                 lo: cmp::min(self.lo, other.lo),
                 hi: cmp::max(self.hi, other.hi),
             })
         })
     }
+
+    #[cfg(not(span_locations))]
+    fn first_byte(self) -> Self {
+        self
+    }
+
+    #[cfg(span_locations)]
+    fn first_byte(self) -> Self {
+        Span {
+            lo: self.lo,
+            hi: cmp::min(self.lo.saturating_add(1), self.hi),
+        }
+    }
+
+    #[cfg(not(span_locations))]
+    fn last_byte(self) -> Self {
+        self
+    }
+
+    #[cfg(span_locations)]
+    fn last_byte(self) -> Self {
+        Span {
+            lo: cmp::max(self.hi.saturating_sub(1), self.lo),
+            hi: self.hi,
+        }
+    }
 }
 
-impl fmt::Debug for Span {
+impl Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        #[cfg(procmacro2_semver_exempt)]
+        #[cfg(span_locations)]
         return write!(f, "bytes({}..{})", self.lo, self.hi);
 
-        #[cfg(not(procmacro2_semver_exempt))]
+        #[cfg(not(span_locations))]
         write!(f, "Span")
     }
 }
 
-pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
-    if cfg!(procmacro2_semver_exempt) {
+pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
+    #[cfg(span_locations)]
+    {
+        if span.lo == 0 && span.hi == 0 {
+            return;
+        }
+    }
+
+    if cfg!(span_locations) {
         debug.field("span", &span);
     }
 }
 
 #[derive(Clone)]
-pub struct Group {
+pub(crate) struct Group {
     delimiter: Delimiter,
     stream: TokenStream,
     span: Span,
 }
 
 impl Group {
     pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
         Group {
@@ -469,58 +555,67 @@ impl Group {
         self.stream.clone()
     }
 
     pub fn span(&self) -> Span {
         self.span
     }
 
     pub fn span_open(&self) -> Span {
-        self.span
+        self.span.first_byte()
     }
 
     pub fn span_close(&self) -> Span {
-        self.span
+        self.span.last_byte()
     }
 
     pub fn set_span(&mut self, span: Span) {
         self.span = span;
     }
 }
 
-impl fmt::Display for Group {
+impl Display for Group {
+    // We attempt to match libproc_macro's formatting.
+    // Empty parens: ()
+    // Nonempty parens: (...)
+    // Empty brackets: []
+    // Nonempty brackets: [...]
+    // Empty braces: { }
+    // Nonempty braces: { ... }
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let (left, right) = match self.delimiter {
+        let (open, close) = match self.delimiter {
             Delimiter::Parenthesis => ("(", ")"),
-            Delimiter::Brace => ("{", "}"),
+            Delimiter::Brace => ("{ ", "}"),
             Delimiter::Bracket => ("[", "]"),
             Delimiter::None => ("", ""),
         };
 
-        f.write_str(left)?;
-        self.stream.fmt(f)?;
-        f.write_str(right)?;
+        f.write_str(open)?;
+        Display::fmt(&self.stream, f)?;
+        if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
+            f.write_str(" ")?;
+        }
+        f.write_str(close)?;
 
         Ok(())
     }
 }
 
-impl fmt::Debug for Group {
+impl Debug for Group {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let mut debug = fmt.debug_struct("Group");
         debug.field("delimiter", &self.delimiter);
         debug.field("stream", &self.stream);
-        #[cfg(procmacro2_semver_exempt)]
-        debug.field("span", &self.span);
+        debug_span_field_if_nontrivial(&mut debug, self.span);
         debug.finish()
     }
 }
 
 #[derive(Clone)]
-pub struct Ident {
+pub(crate) struct Ident {
     sym: String,
     span: Span,
     raw: bool,
 }
 
 impl Ident {
     fn _new(string: &str, raw: bool, span: Span) -> Ident {
         validate_ident(string);
@@ -544,26 +639,24 @@ impl Ident {
         self.span
     }
 
     pub fn set_span(&mut self, span: Span) {
         self.span = span;
     }
 }
 
-#[inline]
-fn is_ident_start(c: char) -> bool {
+pub(crate) fn is_ident_start(c: char) -> bool {
     ('a' <= c && c <= 'z')
         || ('A' <= c && c <= 'Z')
         || c == '_'
         || (c > '\x7f' && UnicodeXID::is_xid_start(c))
 }
 
-#[inline]
-fn is_ident_continue(c: char) -> bool {
+pub(crate) fn is_ident_continue(c: char) -> bool {
     ('a' <= c && c <= 'z')
         || ('A' <= c && c <= 'Z')
         || c == '_'
         || ('0' <= c && c <= '9')
         || (c > '\x7f' && UnicodeXID::is_xid_continue(c))
 }
 
 fn validate_ident(string: &str) {
@@ -610,49 +703,49 @@ where
         if self.raw {
             other.starts_with("r#") && self.sym == other[2..]
         } else {
             self.sym == other
         }
     }
 }
 
-impl fmt::Display for Ident {
+impl Display for Ident {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if self.raw {
-            "r#".fmt(f)?;
+            f.write_str("r#")?;
         }
-        self.sym.fmt(f)
+        Display::fmt(&self.sym, f)
     }
 }
 
-impl fmt::Debug for Ident {
+impl Debug for Ident {
     // Ident(proc_macro), Ident(r#union)
-    #[cfg(not(procmacro2_semver_exempt))]
+    #[cfg(not(span_locations))]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut debug = f.debug_tuple("Ident");
         debug.field(&format_args!("{}", self));
         debug.finish()
     }
 
     // Ident {
     //     sym: proc_macro,
     //     span: bytes(128..138)
     // }
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let mut debug = f.debug_struct("Ident");
         debug.field("sym", &format_args!("{}", self));
-        debug.field("span", &self.span);
+        debug_span_field_if_nontrivial(&mut debug, self.span);
         debug.finish()
     }
 }
 
 #[derive(Clone)]
-pub struct Literal {
+pub(crate) struct Literal {
     text: String,
     span: Span,
 }
 
 macro_rules! suffixed_numbers {
     ($($name:ident => $kind:ident,)*) => ($(
         pub fn $name(n: $kind) -> Literal {
             Literal::_new(format!(concat!("{}", stringify!($kind)), n))
@@ -664,17 +757,17 @@ macro_rules! unsuffixed_numbers {
     ($($name:ident => $kind:ident,)*) => ($(
         pub fn $name(n: $kind) -> Literal {
             Literal::_new(n.to_string())
         }
     )*)
 }
 
 impl Literal {
-    fn _new(text: String) -> Literal {
+    pub(crate) fn _new(text: String) -> Literal {
         Literal {
             text,
             span: Span::call_site(),
         }
     }
 
     suffixed_numbers! {
         u8_suffixed => u8,
@@ -706,61 +799,62 @@ impl Literal {
         i32_unsuffixed => i32,
         i64_unsuffixed => i64,
         i128_unsuffixed => i128,
         isize_unsuffixed => isize,
     }
 
     pub fn f32_unsuffixed(f: f32) -> Literal {
         let mut s = f.to_string();
-        if !s.contains(".") {
+        if !s.contains('.') {
             s.push_str(".0");
         }
         Literal::_new(s)
     }
 
     pub fn f64_unsuffixed(f: f64) -> Literal {
         let mut s = f.to_string();
-        if !s.contains(".") {
+        if !s.contains('.') {
             s.push_str(".0");
         }
         Literal::_new(s)
     }
 
     pub fn string(t: &str) -> Literal {
         let mut text = String::with_capacity(t.len() + 2);
         text.push('"');
         for c in t.chars() {
             if c == '\'' {
-                // escape_default turns this into "\'" which is unnecessary.
+                // escape_debug turns this into "\'" which is unnecessary.
                 text.push(c);
             } else {
-                text.extend(c.escape_default());
+                text.extend(c.escape_debug());
             }
         }
         text.push('"');
         Literal::_new(text)
     }
 
     pub fn character(t: char) -> Literal {
         let mut text = String::new();
         text.push('\'');
         if t == '"' {
-            // escape_default turns this into '\"' which is unnecessary.
+            // escape_debug turns this into '\"' which is unnecessary.
             text.push(t);
         } else {
-            text.extend(t.escape_default());
+            text.extend(t.escape_debug());
         }
         text.push('\'');
         Literal::_new(text)
     }
 
     pub fn byte_string(bytes: &[u8]) -> Literal {
         let mut escaped = "b\"".to_string();
         for b in bytes {
+            #[allow(clippy::match_overlapping_arm)]
             match *b {
                 b'\0' => escaped.push_str(r"\0"),
                 b'\t' => escaped.push_str(r"\t"),
                 b'\n' => escaped.push_str(r"\n"),
                 b'\r' => escaped.push_str(r"\r"),
                 b'"' => escaped.push_str("\\\""),
                 b'\\' => escaped.push_str("\\\\"),
                 b'\x20'..=b'\x7E' => escaped.push(*b as char),
@@ -779,656 +873,22 @@ impl Literal {
         self.span = span;
     }
 
     pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> {
         None
     }
 }
 
-impl fmt::Display for Literal {
+impl Display for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.text.fmt(f)
-    }
-}
-
-impl fmt::Debug for Literal {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let mut debug = fmt.debug_struct("Literal");
-        debug.field("lit", &format_args!("{}", self.text));
-        #[cfg(procmacro2_semver_exempt)]
-        debug.field("span", &self.span);
-        debug.finish()
-    }
-}
-
-fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
-    let mut trees = Vec::new();
-    loop {
-        let input_no_ws = skip_whitespace(input);
-        if input_no_ws.rest.len() == 0 {
-            break;
-        }
-        if let Ok((a, tokens)) = doc_comment(input_no_ws) {
-            input = a;
-            trees.extend(tokens);
-            continue;
-        }
-
-        let (a, tt) = match token_tree(input_no_ws) {
-            Ok(p) => p,
-            Err(_) => break,
-        };
-        trees.push(tt);
-        input = a;
-    }
-    Ok((input, TokenStream { inner: trees }))
-}
-
-#[cfg(not(span_locations))]
-fn spanned<'a, T>(
-    input: Cursor<'a>,
-    f: fn(Cursor<'a>) -> PResult<'a, T>,
-) -> PResult<'a, (T, crate::Span)> {
-    let (a, b) = f(skip_whitespace(input))?;
-    Ok((a, ((b, crate::Span::_new_stable(Span::call_site())))))
-}
-
-#[cfg(span_locations)]
-fn spanned<'a, T>(
-    input: Cursor<'a>,
-    f: fn(Cursor<'a>) -> PResult<'a, T>,
-) -> PResult<'a, (T, crate::Span)> {
-    let input = skip_whitespace(input);
-    let lo = input.off;
-    let (a, b) = f(input)?;
-    let hi = a.off;
-    let span = crate::Span::_new_stable(Span { lo, hi });
-    Ok((a, (b, span)))
-}
-
-fn token_tree(input: Cursor) -> PResult<TokenTree> {
-    let (rest, (mut tt, span)) = spanned(input, token_kind)?;
-    tt.set_span(span);
-    Ok((rest, tt))
-}
-
-named!(token_kind -> TokenTree, alt!(
-    map!(group, |g| TokenTree::Group(crate::Group::_new_stable(g)))
-    |
-    map!(literal, |l| TokenTree::Literal(crate::Literal::_new_stable(l))) // must be before symbol
-    |
-    map!(op, TokenTree::Punct)
-    |
-    symbol_leading_ws
-));
-
-named!(group -> Group, alt!(
-    delimited!(
-        punct!("("),
-        token_stream,
-        punct!(")")
-    ) => { |ts| Group::new(Delimiter::Parenthesis, ts) }
-    |
-    delimited!(
-        punct!("["),
-        token_stream,
-        punct!("]")
-    ) => { |ts| Group::new(Delimiter::Bracket, ts) }
-    |
-    delimited!(
-        punct!("{"),
-        token_stream,
-        punct!("}")
-    ) => { |ts| Group::new(Delimiter::Brace, ts) }
-));
-
-fn symbol_leading_ws(input: Cursor) -> PResult<TokenTree> {
-    symbol(skip_whitespace(input))
-}
-
-fn symbol(input: Cursor) -> PResult<TokenTree> {
-    let raw = input.starts_with("r#");
-    let rest = input.advance((raw as usize) << 1);
-
-    let (rest, sym) = symbol_not_raw(rest)?;
-
-    if !raw {
-        let ident = crate::Ident::new(sym, crate::Span::call_site());
-        return Ok((rest, ident.into()));
-    }
-
-    if sym == "_" {
-        return Err(LexError);
-    }
-
-    let ident = crate::Ident::_new_raw(sym, crate::Span::call_site());
-    Ok((rest, ident.into()))
-}
-
-fn symbol_not_raw(input: Cursor) -> PResult<&str> {
-    let mut chars = input.char_indices();
-
-    match chars.next() {
-        Some((_, ch)) if is_ident_start(ch) => {}
-        _ => return Err(LexError),
-    }
-
-    let mut end = input.len();
-    for (i, ch) in chars {
-        if !is_ident_continue(ch) {
-            end = i;
-            break;
-        }
-    }
-
-    Ok((input.advance(end), &input.rest[..end]))
-}
-
-fn literal(input: Cursor) -> PResult<Literal> {
-    let input_no_ws = skip_whitespace(input);
-
-    match literal_nocapture(input_no_ws) {
-        Ok((a, ())) => {
-            let start = input.len() - input_no_ws.len();
-            let len = input_no_ws.len() - a.len();
-            let end = start + len;
-            Ok((a, Literal::_new(input.rest[start..end].to_string())))
-        }
-        Err(LexError) => Err(LexError),
+        Display::fmt(&self.text, f)
     }
 }
 
-named!(literal_nocapture -> (), alt!(
-    string
-    |
-    byte_string
-    |
-    byte
-    |
-    character
-    |
-    float
-    |
-    int
-));
-
-named!(string -> (), alt!(
-    quoted_string
-    |
-    preceded!(
-        punct!("r"),
-        raw_string
-    ) => { |_| () }
-));
-
-named!(quoted_string -> (), do_parse!(
-    punct!("\"") >>
-    cooked_string >>
-    tag!("\"") >>
-    option!(symbol_not_raw) >>
-    (())
-));
-
-fn cooked_string(input: Cursor) -> PResult<()> {
-    let mut chars = input.char_indices().peekable();
-    while let Some((byte_offset, ch)) = chars.next() {
-        match ch {
-            '"' => {
-                return Ok((input.advance(byte_offset), ()));
-            }
-            '\r' => {
-                if let Some((_, '\n')) = chars.next() {
-                    // ...
-                } else {
-                    break;
-                }
-            }
-            '\\' => match chars.next() {
-                Some((_, 'x')) => {
-                    if !backslash_x_char(&mut chars) {
-                        break;
-                    }
-                }
-                Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
-                | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {}
-                Some((_, 'u')) => {
-                    if !backslash_u(&mut chars) {
-                        break;
-                    }
-                }
-                Some((_, '\n')) | Some((_, '\r')) => {
-                    while let Some(&(_, ch)) = chars.peek() {
-                        if ch.is_whitespace() {
-                            chars.next();
-                        } else {
-                            break;
-                        }
-                    }
-                }
-                _ => break,
-            },
-            _ch => {}
-        }
-    }
-    Err(LexError)
-}
-
-named!(byte_string -> (), alt!(
-    delimited!(
-        punct!("b\""),
-        cooked_byte_string,
-        tag!("\"")
-    ) => { |_| () }
-    |
-    preceded!(
-        punct!("br"),
-        raw_string
-    ) => { |_| () }
-));
-
-fn cooked_byte_string(mut input: Cursor) -> PResult<()> {
-    let mut bytes = input.bytes().enumerate();
-    'outer: while let Some((offset, b)) = bytes.next() {
-        match b {
-            b'"' => {
-                return Ok((input.advance(offset), ()));
-            }
-            b'\r' => {
-                if let Some((_, b'\n')) = bytes.next() {
-                    // ...
-                } else {
-                    break;
-                }
-            }
-            b'\\' => match bytes.next() {
-                Some((_, b'x')) => {
-                    if !backslash_x_byte(&mut bytes) {
-                        break;
-                    }
-                }
-                Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\'))
-                | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {}
-                Some((newline, b'\n')) | Some((newline, b'\r')) => {
-                    let rest = input.advance(newline + 1);
-                    for (offset, ch) in rest.char_indices() {
-                        if !ch.is_whitespace() {
-                            input = rest.advance(offset);
-                            bytes = input.bytes().enumerate();
-                            continue 'outer;
-                        }
-                    }
-                    break;
-                }
-                _ => break,
-            },
-            b if b < 0x80 => {}
-            _ => break,
-        }
-    }
-    Err(LexError)
-}
-
-fn raw_string(input: Cursor) -> PResult<()> {
-    let mut chars = input.char_indices();
-    let mut n = 0;
-    while let Some((byte_offset, ch)) = chars.next() {
-        match ch {
-            '"' => {
-                n = byte_offset;
-                break;
-            }
-            '#' => {}
-            _ => return Err(LexError),
-        }
-    }
-    for (byte_offset, ch) in chars {
-        match ch {
-            '"' if input.advance(byte_offset + 1).starts_with(&input.rest[..n]) => {
-                let rest = input.advance(byte_offset + 1 + n);
-                return Ok((rest, ()));
-            }
-            '\r' => {}
-            _ => {}
-        }
-    }
-    Err(LexError)
-}
-
-named!(byte -> (), do_parse!(
-    punct!("b") >>
-    tag!("'") >>
-    cooked_byte >>
-    tag!("'") >>
-    (())
-));
-
-fn cooked_byte(input: Cursor) -> PResult<()> {
-    let mut bytes = input.bytes().enumerate();
-    let ok = match bytes.next().map(|(_, b)| b) {
-        Some(b'\\') => match bytes.next().map(|(_, b)| b) {
-            Some(b'x') => backslash_x_byte(&mut bytes),
-            Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'')
-            | Some(b'"') => true,
-            _ => false,
-        },
-        b => b.is_some(),
-    };
-    if ok {
-        match bytes.next() {
-            Some((offset, _)) => {
-                if input.chars().as_str().is_char_boundary(offset) {
-                    Ok((input.advance(offset), ()))
-                } else {
-                    Err(LexError)
-                }
-            }
-            None => Ok((input.advance(input.len()), ())),
-        }
-    } else {
-        Err(LexError)
-    }
-}
-
-named!(character -> (), do_parse!(
-    punct!("'") >>
-    cooked_char >>
-    tag!("'") >>
-    (())
-));
-
-fn cooked_char(input: Cursor) -> PResult<()> {
-    let mut chars = input.char_indices();
-    let ok = match chars.next().map(|(_, ch)| ch) {
-        Some('\\') => match chars.next().map(|(_, ch)| ch) {
-            Some('x') => backslash_x_char(&mut chars),
-            Some('u') => backslash_u(&mut chars),
-            Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => {
-                true
-            }
-            _ => false,
-        },
-        ch => ch.is_some(),
-    };
-    if ok {
-        match chars.next() {
-            Some((idx, _)) => Ok((input.advance(idx), ())),
-            None => Ok((input.advance(input.len()), ())),
-        }
-    } else {
-        Err(LexError)
+impl Debug for Literal {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        let mut debug = fmt.debug_struct("Literal");
+        debug.field("lit", &format_args!("{}", self.text));
+        debug_span_field_if_nontrivial(&mut debug, self.span);
+        debug.finish()
     }
 }
-
-macro_rules! next_ch {
-    ($chars:ident @ $pat:pat $(| $rest:pat)*) => {
-        match $chars.next() {
-            Some((_, ch)) => match ch {
-                $pat $(| $rest)*  => ch,
-                _ => return false,
-            },
-            None => return false
-        }
-    };
-}
-
-fn backslash_x_char<I>(chars: &mut I) -> bool
-where
-    I: Iterator<Item = (usize, char)>,
-{
-    next_ch!(chars @ '0'..='7');
-    next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
-    true
-}
-
-fn backslash_x_byte<I>(chars: &mut I) -> bool
-where
-    I: Iterator<Item = (usize, u8)>,
-{
-    next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
-    next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
-    true
-}
-
-fn backslash_u<I>(chars: &mut I) -> bool
-where
-    I: Iterator<Item = (usize, char)>,
-{
-    next_ch!(chars @ '{');
-    next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
-    loop {
-        let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}');
-        if c == '}' {
-            return true;
-        }
-    }
-}
-
-fn float(input: Cursor) -> PResult<()> {
-    let (mut rest, ()) = float_digits(input)?;
-    if let Some(ch) = rest.chars().next() {
-        if is_ident_start(ch) {
-            rest = symbol_not_raw(rest)?.0;
-        }
-    }
-    word_break(rest)
-}
-
-fn float_digits(input: Cursor) -> PResult<()> {
-    let mut chars = input.chars().peekable();
-    match chars.next() {
-        Some(ch) if ch >= '0' && ch <= '9' => {}
-        _ => return Err(LexError),
-    }
-
-    let mut len = 1;
-    let mut has_dot = false;
-    let mut has_exp = false;
-    while let Some(&ch) = chars.peek() {
-        match ch {
-            '0'..='9' | '_' => {
-                chars.next();
-                len += 1;
-            }
-            '.' => {
-                if has_dot {
-                    break;
-                }
-                chars.next();
-                if chars
-                    .peek()
-                    .map(|&ch| ch == '.' || is_ident_start(ch))
-                    .unwrap_or(false)
-                {
-                    return Err(LexError);
-                }
-                len += 1;
-                has_dot = true;
-            }
-            'e' | 'E' => {
-                chars.next();
-                len += 1;
-                has_exp = true;
-                break;
-            }
-            _ => break,
-        }
-    }
-
-    let rest = input.advance(len);
-    if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) {
-        return Err(LexError);
-    }
-
-    if has_exp {
-        let mut has_exp_value = false;
-        while let Some(&ch) = chars.peek() {
-            match ch {
-                '+' | '-' => {
-                    if has_exp_value {
-                        break;
-                    }
-                    chars.next();
-                    len += 1;
-                }
-                '0'..='9' => {
-                    chars.next();
-                    len += 1;
-                    has_exp_value = true;
-                }
-                '_' => {
-                    chars.next();
-                    len += 1;
-                }
-                _ => break,
-            }
-        }
-        if !has_exp_value {
-            return Err(LexError);
-        }
-    }
-
-    Ok((input.advance(len), ()))
-}
-
-fn int(input: Cursor) -> PResult<()> {
-    let (mut rest, ()) = digits(input)?;
-    if let Some(ch) = rest.chars().next() {
-        if is_ident_start(ch) {
-            rest = symbol_not_raw(rest)?.0;
-        }
-    }
-    word_break(rest)
-}
-
-fn digits(mut input: Cursor) -> PResult<()> {
-    let base = if input.starts_with("0x") {
-        input = input.advance(2);
-        16
-    } else if input.starts_with("0o") {
-        input = input.advance(2);
-        8
-    } else if input.starts_with("0b") {
-        input = input.advance(2);
-        2
-    } else {
-        10
-    };
-
-    let mut len = 0;
-    let mut empty = true;
-    for b in input.bytes() {
-        let digit = match b {
-            b'0'..=b'9' => (b - b'0') as u64,
-            b'a'..=b'f' => 10 + (b - b'a') as u64,
-            b'A'..=b'F' => 10 + (b - b'A') as u64,
-            b'_' => {
-                if empty && base == 10 {
-                    return Err(LexError);
-                }
-                len += 1;
-                continue;
-            }
-            _ => break,
-        };
-        if digit >= base {
-            return Err(LexError);
-        }
-        len += 1;
-        empty = false;
-    }
-    if empty {
-        Err(LexError)
-    } else {
-        Ok((input.advance(len), ()))
-    }
-}
-
-fn op(input: Cursor) -> PResult<Punct> {
-    let input = skip_whitespace(input);
-    match op_char(input) {
-        Ok((rest, '\'')) => {
-            symbol(rest)?;
-            Ok((rest, Punct::new('\'', Spacing::Joint)))
-        }
-        Ok((rest, ch)) => {
-            let kind = match op_char(rest) {
-                Ok(_) => Spacing::Joint,
-                Err(LexError) => Spacing::Alone,
-            };
-            Ok((rest, Punct::new(ch, kind)))
-        }
-        Err(LexError) => Err(LexError),
-    }
-}
-
-fn op_char(input: Cursor) -> PResult<char> {
-    if input.starts_with("//") || input.starts_with("/*") {
-        // Do not accept `/` of a comment as an op.
-        return Err(LexError);
-    }
-
-    let mut chars = input.chars();
-    let first = match chars.next() {
-        Some(ch) => ch,
-        None => {
-            return Err(LexError);
-        }
-    };
-    let recognized = "~!@#$%^&*-=+|;:,<.>/?'";
-    if recognized.contains(first) {
-        Ok((input.advance(first.len_utf8()), first))
-    } else {
-        Err(LexError)
-    }
-}
-
-fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> {
-    let mut trees = Vec::new();
-    let (rest, ((comment, inner), span)) = spanned(input, doc_comment_contents)?;
-    trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone)));
-    if inner {
-        trees.push(Punct::new('!', Spacing::Alone).into());
-    }
-    let mut stream = vec![
-        TokenTree::Ident(crate::Ident::new("doc", span)),
-        TokenTree::Punct(Punct::new('=', Spacing::Alone)),
-        TokenTree::Literal(crate::Literal::string(comment)),
-    ];
-    for tt in stream.iter_mut() {
-        tt.set_span(span);
-    }
-    let group = Group::new(Delimiter::Bracket, stream.into_iter().collect());
-    trees.push(crate::Group::_new_stable(group).into());
-    for tt in trees.iter_mut() {
-        tt.set_span(span);
-    }
-    Ok((rest, trees))
-}
-
-named!(doc_comment_contents -> (&str, bool), alt!(
-    do_parse!(
-        punct!("//!") >>
-        s: take_until_newline_or_eof!() >>
-        ((s, true))
-    )
-    |
-    do_parse!(
-        option!(whitespace) >>
-        peek!(tag!("/*!")) >>
-        s: block_comment >>
-        ((s, true))
-    )
-    |
-    do_parse!(
-        punct!("///") >>
-        not!(tag!("/")) >>
-        s: take_until_newline_or_eof!() >>
-        ((s, false))
-    )
-    |
-    do_parse!(
-        option!(whitespace) >>
-        peek!(tuple!(tag!("/**"), not!(tag!("*")))) >>
-        s: block_comment >>
-        ((s, false))
-    )
-));
--- a/third_party/rust/proc-macro2/src/lib.rs
+++ b/third_party/rust/proc-macro2/src/lib.rs
@@ -73,37 +73,44 @@
 //!
 //! # Thread-Safety
 //!
 //! Most types in this crate are `!Sync` because the underlying compiler
 //! types make use of thread-local memory, meaning they cannot be accessed from
 //! a different thread.
 
 // Proc-macro2 types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.5")]
+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.20")]
 #![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))]
 #![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))]
+#![allow(clippy::needless_doctest_main)]
 
 #[cfg(use_proc_macro)]
 extern crate proc_macro;
 
 use std::cmp::Ordering;
-use std::fmt;
+use std::fmt::{self, Debug, Display};
 use std::hash::{Hash, Hasher};
 use std::iter::FromIterator;
 use std::marker;
 use std::ops::RangeBounds;
 #[cfg(procmacro2_semver_exempt)]
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::str::FromStr;
 
-#[macro_use]
-mod strnom;
-mod fallback;
+mod parse;
+
+#[cfg(wrap_proc_macro)]
+mod detection;
+
+// Public for proc_macro2::fallback::force() and unforce(), but those are quite
+// a niche use case so we omit it from rustdoc.
+#[doc(hidden)]
+pub mod fallback;
 
 #[cfg(not(wrap_proc_macro))]
 use crate::fallback as imp;
 #[path = "wrapper.rs"]
 #[cfg(wrap_proc_macro)]
 mod imp;
 
 /// An abstract stream of tokens, or more concretely a sequence of token trees.
@@ -223,32 +230,32 @@ impl FromIterator<TokenStream> for Token
         TokenStream::_new(streams.into_iter().map(|i| i.inner).collect())
     }
 }
 
 /// Prints the token stream as a string that is supposed to be losslessly
 /// convertible back into the same token stream (modulo spans), except for
 /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative
 /// numeric literals.
-impl fmt::Display for TokenStream {
+impl Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Display::fmt(&self.inner, f)
     }
 }
 
 /// Prints token in a form convenient for debugging.
-impl fmt::Debug for TokenStream {
+impl Debug for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Debug::fmt(&self.inner, f)
     }
 }
 
-impl fmt::Debug for LexError {
+impl Debug for LexError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Debug::fmt(&self.inner, f)
     }
 }
 
 /// The source file of a given `Span`.
 ///
 /// This type is semver exempt and not exposed by default.
 #[cfg(procmacro2_semver_exempt)]
 #[derive(Clone, PartialEq, Eq)]
@@ -286,19 +293,19 @@ impl SourceFile {
     /// Returns `true` if this source file is a real source file, and not
     /// generated by an external macro's expansion.
     pub fn is_real(&self) -> bool {
         self.inner.is_real()
     }
 }
 
 #[cfg(procmacro2_semver_exempt)]
-impl fmt::Debug for SourceFile {
+impl Debug for SourceFile {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Debug::fmt(&self.inner, f)
     }
 }
 
 /// A line-column pair representing the start or end of a `Span`.
 ///
 /// This type is semver exempt and not exposed by default.
 #[cfg(span_locations)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -306,16 +313,32 @@ pub struct LineColumn {
     /// The 1-indexed line in the source file on which the span starts or ends
     /// (inclusive).
     pub line: usize,
     /// The 0-indexed column (in UTF-8 characters) in the source file on which
     /// the span starts or ends (inclusive).
     pub column: usize,
 }
 
+#[cfg(span_locations)]
+impl Ord for LineColumn {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.line
+            .cmp(&other.line)
+            .then(self.column.cmp(&other.column))
+    }
+}
+
+#[cfg(span_locations)]
+impl PartialOrd for LineColumn {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
 /// A region of source code, along with macro expansion information.
 #[derive(Copy, Clone)]
 pub struct Span {
     inner: imp::Span,
     _marker: marker::PhantomData<Rc<()>>,
 }
 
 impl Span {
@@ -337,38 +360,42 @@ impl Span {
     ///
     /// Identifiers created with this span will be resolved as if they were
     /// written directly at the macro call location (call-site hygiene) and
     /// other code at the macro call site will be able to refer to them as well.
     pub fn call_site() -> Span {
         Span::_new(imp::Span::call_site())
     }
 
+    /// The span located at the invocation of the procedural macro, but with
+    /// local variables, labels, and `$crate` resolved at the definition site
+    /// of the macro. This is the same hygiene behavior as `macro_rules`.
+    ///
+    /// This function requires Rust 1.45 or later.
+    #[cfg(hygiene)]
+    pub fn mixed_site() -> Span {
+        Span::_new(imp::Span::mixed_site())
+    }
+
     /// A span that resolves at the macro definition site.
     ///
     /// This method is semver exempt and not exposed by default.
     #[cfg(procmacro2_semver_exempt)]
     pub fn def_site() -> Span {
         Span::_new(imp::Span::def_site())
     }
 
     /// Creates a new span with the same line/column information as `self` but
     /// that resolves symbols as though it were at `other`.
-    ///
-    /// This method is semver exempt and not exposed by default.
-    #[cfg(procmacro2_semver_exempt)]
     pub fn resolved_at(&self, other: Span) -> Span {
         Span::_new(self.inner.resolved_at(other.inner))
     }
 
     /// Creates a new span with the same name resolution behavior as `self` but
     /// with the line/column information of `other`.
-    ///
-    /// This method is semver exempt and not exposed by default.
-    #[cfg(procmacro2_semver_exempt)]
     pub fn located_at(&self, other: Span) -> Span {
         Span::_new(self.inner.located_at(other.inner))
     }
 
     /// Convert `proc_macro2::Span` to `proc_macro::Span`.
     ///
     /// This method is available when building with a nightly compiler, or when
     /// building with rustc 1.29+ *without* semver exempt features.
@@ -434,19 +461,19 @@ impl Span {
     /// This method is semver exempt and not exposed by default.
     #[cfg(procmacro2_semver_exempt)]
     pub fn eq(&self, other: &Span) -> bool {
         self.inner.eq(&other.inner)
     }
 }
 
 /// Prints a span in a form convenient for debugging.
-impl fmt::Debug for Span {
+impl Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Debug::fmt(&self.inner, f)
     }
 }
 
 /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
 #[derive(Clone)]
 pub enum TokenTree {
     /// A token stream surrounded by bracket delimiters.
     Group(Group),
@@ -457,35 +484,35 @@ pub enum TokenTree {
     /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
     Literal(Literal),
 }
 
 impl TokenTree {
     /// Returns the span of this tree, delegating to the `span` method of
     /// the contained token or a delimited stream.
     pub fn span(&self) -> Span {
-        match *self {
-            TokenTree::Group(ref t) => t.span(),
-            TokenTree::Ident(ref t) => t.span(),
-            TokenTree::Punct(ref t) => t.span(),
-            TokenTree::Literal(ref t) => t.span(),
+        match self {
+            TokenTree::Group(t) => t.span(),
+            TokenTree::Ident(t) => t.span(),
+            TokenTree::Punct(t) => t.span(),
+            TokenTree::Literal(t) => t.span(),
         }
     }
 
     /// Configures the span for *only this token*.
     ///
     /// Note that if this token is a `Group` then this method will not configure
     /// the span of each of the internal tokens, this will simply delegate to
     /// the `set_span` method of each variant.
     pub fn set_span(&mut self, span: Span) {
-        match *self {
-            TokenTree::Group(ref mut t) => t.set_span(span),
-            TokenTree::Ident(ref mut t) => t.set_span(span),
-            TokenTree::Punct(ref mut t) => t.set_span(span),
-            TokenTree::Literal(ref mut t) => t.set_span(span),
+        match self {
+            TokenTree::Group(t) => t.set_span(span),
+            TokenTree::Ident(t) => t.set_span(span),
+            TokenTree::Punct(t) => t.set_span(span),
+            TokenTree::Literal(t) => t.set_span(span),
         }
     }
 }
 
 impl From<Group> for TokenTree {
     fn from(g: Group) -> TokenTree {
         TokenTree::Group(g)
     }
@@ -508,42 +535,42 @@ impl From<Literal> for TokenTree {
         TokenTree::Literal(g)
     }
 }
 
 /// Prints the token tree as a string that is supposed to be losslessly
 /// convertible back into the same token tree (modulo spans), except for
 /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative
 /// numeric literals.
-impl fmt::Display for TokenTree {
+impl Display for TokenTree {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            TokenTree::Group(ref t) => t.fmt(f),
-            TokenTree::Ident(ref t) => t.fmt(f),
-            TokenTree::Punct(ref t) => t.fmt(f),
-            TokenTree::Literal(ref t) => t.fmt(f),
+        match self {
+            TokenTree::Group(t) => Display::fmt(t, f),
+            TokenTree::Ident(t) => Display::fmt(t, f),
+            TokenTree::Punct(t) => Display::fmt(t, f),
+            TokenTree::Literal(t) => Display::fmt(t, f),
         }
     }
 }
 
 /// Prints token tree in a form convenient for debugging.
-impl fmt::Debug for TokenTree {
+impl Debug for TokenTree {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Each of these has the name in the struct type in the derived debug,
         // so don't bother with an extra layer of indirection
-        match *self {
-            TokenTree::Group(ref t) => t.fmt(f),
-            TokenTree::Ident(ref t) => {
+        match self {
+            TokenTree::Group(t) => Debug::fmt(t, f),
+            TokenTree::Ident(t) => {
                 let mut debug = f.debug_struct("Ident");
                 debug.field("sym", &format_args!("{}", t));
                 imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner);
                 debug.finish()
             }
-            TokenTree::Punct(ref t) => t.fmt(f),
-            TokenTree::Literal(ref t) => t.fmt(f),
+            TokenTree::Punct(t) => Debug::fmt(t, f),
+            TokenTree::Literal(t) => Debug::fmt(t, f),
         }
     }
 }
 
 /// A delimited token stream.
 ///
 /// A `Group` internally contains a `TokenStream` which is surrounded by
 /// `Delimiter`s.
@@ -646,25 +673,25 @@ impl Group {
     pub fn set_span(&mut self, span: Span) {
         self.inner.set_span(span.inner)
     }
 }
 
 /// Prints the group as a string that should be losslessly convertible back
 /// into the same group (modulo spans), except for possibly `TokenTree::Group`s
 /// with `Delimiter::None` delimiters.
-impl fmt::Display for Group {
+impl Display for Group {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.inner, formatter)
+        Display::fmt(&self.inner, formatter)
     }
 }
 
-impl fmt::Debug for Group {
+impl Debug for Group {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.inner, formatter)
+        Debug::fmt(&self.inner, formatter)
     }
 }
 
 /// An `Punct` is an single punctuation character like `+`, `-` or `#`.
 ///
 /// Multicharacter operators like `+=` are represented as two instances of
 /// `Punct` with different forms of `Spacing` returned.
 #[derive(Clone)]
@@ -725,23 +752,23 @@ impl Punct {
     /// Configure the span for this punctuation character.
     pub fn set_span(&mut self, span: Span) {
         self.span = span;
     }
 }
 
 /// Prints the punctuation character as a string that should be losslessly
 /// convertible back into the same character.
-impl fmt::Display for Punct {
+impl Display for Punct {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.op.fmt(f)
+        Display::fmt(&self.op, f)
     }
 }
 
-impl fmt::Debug for Punct {
+impl Debug for Punct {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let mut debug = fmt.debug_struct("Punct");
         debug.field("op", &self.op);
         debug.field("spacing", &self.spacing);
         imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner);
         debug.finish()
     }
 }
@@ -915,25 +942,25 @@ impl Ord for Ident {
 impl Hash for Ident {
     fn hash<H: Hasher>(&self, hasher: &mut H) {
         self.to_string().hash(hasher)
     }
 }
 
 /// Prints the identifier as a string that should be losslessly convertible back
 /// into the same identifier.
-impl fmt::Display for Ident {
+impl Display for Ident {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Display::fmt(&self.inner, f)
     }
 }
 
-impl fmt::Debug for Ident {
+impl Debug for Ident {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Debug::fmt(&self.inner, f)
     }
 }
 
 /// A literal string (`"hello"`), byte string (`b"hello"`), character (`'a'`),
 /// byte character (`b'a'`), an integer or floating point number with or without
 /// a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
 ///
 /// Boolean literals like `true` and `false` do not belong here, they are
@@ -1135,36 +1162,36 @@ impl Literal {
     /// nightly compiler, this method will always return `None`.
     ///
     /// [`proc_macro::Literal::subspan`]: https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.subspan
     pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
         self.inner.subspan(range).map(Span::_new)
     }
 }
 
-impl fmt::Debug for Literal {
+impl Debug for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Debug::fmt(&self.inner, f)
     }
 }
 
-impl fmt::Display for Literal {
+impl Display for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.inner.fmt(f)
+        Display::fmt(&self.inner, f)
     }
 }
 
 /// Public implementation details for the `TokenStream` type, such as iterators.
 pub mod token_stream {
-    use std::fmt;
+    use crate::{imp, TokenTree};
+    use std::fmt::{self, Debug};
     use std::marker;
     use std::rc::Rc;
 
     pub use crate::TokenStream;
-    use crate::{imp, TokenTree};
 
     /// An iterator over `TokenStream`'s `TokenTree`s.
     ///
     /// The iteration is "shallow", e.g. the iterator doesn't recurse into
     /// delimited groups, and returns whole groups as token trees.
     #[derive(Clone)]
     pub struct IntoIter {
         inner: imp::TokenTreeIter,
@@ -1174,19 +1201,19 @@ pub mod token_stream {
     impl Iterator for IntoIter {
         type Item = TokenTree;
 
         fn next(&mut self) -> Option<TokenTree> {
             self.inner.next()
         }
     }
 
-    impl fmt::Debug for IntoIter {
+    impl Debug for IntoIter {
         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            self.inner.fmt(f)
+            Debug::fmt(&self.inner, f)
         }
     }
 
     impl IntoIterator for TokenStream {
         type Item = TokenTree;
         type IntoIter = IntoIter;
 
         fn into_iter(self) -> IntoIter {
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2/src/parse.rs
@@ -0,0 +1,791 @@
+use crate::fallback::{
+    is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream,
+};
+use crate::{Delimiter, Punct, Spacing, TokenTree};
+use std::str::{Bytes, CharIndices, Chars};
+use unicode_xid::UnicodeXID;
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub(crate) struct Cursor<'a> {
+    pub rest: &'a str,
+    #[cfg(span_locations)]
+    pub off: u32,
+}
+
+impl<'a> Cursor<'a> {
+    fn advance(&self, bytes: usize) -> Cursor<'a> {
+        let (_front, rest) = self.rest.split_at(bytes);
+        Cursor {
+            rest,
+            #[cfg(span_locations)]
+            off: self.off + _front.chars().count() as u32,
+        }
+    }
+
+    fn starts_with(&self, s: &str) -> bool {
+        self.rest.starts_with(s)
+    }
+
+    pub(crate) fn is_empty(&self) -> bool {
+        self.rest.is_empty()
+    }
+
+    fn len(&self) -> usize {
+        self.rest.len()
+    }
+
+    fn as_bytes(&self) -> &'a [u8] {
+        self.rest.as_bytes()
+    }
+
+    fn bytes(&self) -> Bytes<'a> {
+        self.rest.bytes()
+    }
+
+    fn chars(&self) -> Chars<'a> {
+        self.rest.chars()
+    }
+
+    fn char_indices(&self) -> CharIndices<'a> {
+        self.rest.char_indices()
+    }
+
+    fn parse(&self, tag: &str) -> Result<Cursor<'a>, LexError> {
+        if self.starts_with(tag) {
+            Ok(self.advance(tag.len()))
+        } else {
+            Err(LexError)
+        }
+    }
+}
+
+type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>;
+
+fn skip_whitespace(input: Cursor) -> Cursor {
+    let mut s = input;
+
+    while !s.is_empty() {
+        let byte = s.as_bytes()[0];
+        if byte == b'/' {
+            if s.starts_with("//")
+                && (!s.starts_with("///") || s.starts_with("////"))
+                && !s.starts_with("//!")
+            {
+                let (cursor, _) = take_until_newline_or_eof(s);
+                s = cursor;
+                continue;
+            } else if s.starts_with("/**/") {
+                s = s.advance(4);
+                continue;
+            } else if s.starts_with("/*")
+                && (!s.starts_with("/**") || s.starts_with("/***"))
+                && !s.starts_with("/*!")
+            {
+                match block_comment(s) {
+                    Ok((rest, _)) => {
+                        s = rest;
+                        continue;
+                    }
+                    Err(LexError) => return s,
+                }
+            }
+        }
+        match byte {
+            b' ' | 0x09..=0x0d => {
+                s = s.advance(1);
+                continue;
+            }
+            b if b <= 0x7f => {}
+            _ => {
+                let ch = s.chars().next().unwrap();
+                if is_whitespace(ch) {
+                    s = s.advance(ch.len_utf8());
+                    continue;
+                }
+            }
+        }
+        return s;
+    }
+    s
+}
+
+fn block_comment(input: Cursor) -> PResult<&str> {
+    if !input.starts_with("/*") {
+        return Err(LexError);
+    }
+
+    let mut depth = 0;
+    let bytes = input.as_bytes();
+    let mut i = 0;
+    let upper = bytes.len() - 1;
+
+    while i < upper {
+        if bytes[i] == b'/' && bytes[i + 1] == b'*' {
+            depth += 1;
+            i += 1; // eat '*'
+        } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
+            depth -= 1;
+            if depth == 0 {
+                return Ok((input.advance(i + 2), &input.rest[..i + 2]));
+            }
+            i += 1; // eat '/'
+        }
+        i += 1;
+    }
+
+    Err(LexError)
+}
+
+fn is_whitespace(ch: char) -> bool {
+    // Rust treats left-to-right mark and right-to-left mark as whitespace
+    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
+}
+
+fn word_break(input: Cursor) -> Result<Cursor, LexError> {
+    match input.chars().next() {
+        Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError),
+        Some(_) | None => Ok(input),
+    }
+}
+
+pub(crate) fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
+    let mut trees = Vec::new();
+    let mut stack = Vec::new();
+
+    loop {
+        input = skip_whitespace(input);
+
+        if let Ok((rest, tt)) = doc_comment(input) {
+            trees.extend(tt);
+            input = rest;
+            continue;
+        }
+
+        #[cfg(span_locations)]
+        let lo = input.off;
+
+        let first = match input.bytes().next() {
+            Some(first) => first,
+            None => break,
+        };
+
+        if let Some(open_delimiter) = match first {
+            b'(' => Some(Delimiter::Parenthesis),
+            b'[' => Some(Delimiter::Bracket),
+            b'{' => Some(Delimiter::Brace),
+            _ => None,
+        } {
+            input = input.advance(1);
+            let frame = (open_delimiter, trees);
+            #[cfg(span_locations)]
+            let frame = (lo, frame);
+            stack.push(frame);
+            trees = Vec::new();
+        } else if let Some(close_delimiter) = match first {
+            b')' => Some(Delimiter::Parenthesis),
+            b']' => Some(Delimiter::Bracket),
+            b'}' => Some(Delimiter::Brace),
+            _ => None,
+        } {
+            input = input.advance(1);
+            let frame = stack.pop().ok_or(LexError)?;
+            #[cfg(span_locations)]
+            let (lo, frame) = frame;
+            let (open_delimiter, outer) = frame;
+            if open_delimiter != close_delimiter {
+                return Err(LexError);
+            }
+            let mut g = Group::new(open_delimiter, TokenStream { inner: trees });
+            g.set_span(Span {
+                #[cfg(span_locations)]
+                lo,
+                #[cfg(span_locations)]
+                hi: input.off,
+            });
+            trees = outer;
+            trees.push(TokenTree::Group(crate::Group::_new_stable(g)));
+        } else {
+            let (rest, mut tt) = leaf_token(input)?;
+            tt.set_span(crate::Span::_new_stable(Span {
+                #[cfg(span_locations)]
+                lo,
+                #[cfg(span_locations)]
+                hi: rest.off,
+            }));
+            trees.push(tt);
+            input = rest;
+        }
+    }
+
+    if stack.is_empty() {
+        Ok((input, TokenStream { inner: trees }))
+    } else {
+        Err(LexError)
+    }
+}
+
+fn leaf_token(input: Cursor) -> PResult<TokenTree> {
+    if let Ok((input, l)) = literal(input) {
+        // must be parsed before ident
+        Ok((input, TokenTree::Literal(crate::Literal::_new_stable(l))))
+    } else if let Ok((input, p)) = op(input) {
+        Ok((input, TokenTree::Punct(p)))
+    } else if let Ok((input, i)) = ident(input) {
+        Ok((input, TokenTree::Ident(i)))
+    } else {
+        Err(LexError)
+    }
+}
+
+fn ident(input: Cursor) -> PResult<crate::Ident> {
+    let raw = input.starts_with("r#");
+    let rest = input.advance((raw as usize) << 1);
+
+    let (rest, sym) = ident_not_raw(rest)?;
+
+    if !raw {
+        let ident = crate::Ident::new(sym, crate::Span::call_site());
+        return Ok((rest, ident));
+    }
+
+    if sym == "_" {
+        return Err(LexError);
+    }
+
+    let ident = crate::Ident::_new_raw(sym, crate::Span::call_site());
+    Ok((rest, ident))
+}
+
+fn ident_not_raw(input: Cursor) -> PResult<&str> {
+    let mut chars = input.char_indices();
+
+    match chars.next() {
+        Some((_, ch)) if is_ident_start(ch) => {}
+        _ => return Err(LexError),
+    }
+
+    let mut end = input.len();
+    for (i, ch) in chars {
+        if !is_ident_continue(ch) {
+            end = i;
+            break;
+        }
+    }
+
+    Ok((input.advance(end), &input.rest[..end]))
+}
+
+fn literal(input: Cursor) -> PResult<Literal> {
+    match literal_nocapture(input) {
+        Ok(a) => {
+            let end = input.len() - a.len();
+            Ok((a, Literal::_new(input.rest[..end].to_string())))
+        }
+        Err(LexError) => Err(LexError),
+    }
+}
+
+fn literal_nocapture(input: Cursor) -> Result<Cursor, LexError> {
+    if let Ok(ok) = string(input) {
+        Ok(ok)
+    } else if let Ok(ok) = byte_string(input) {
+        Ok(ok)
+    } else if let Ok(ok) = byte(input) {
+        Ok(ok)
+    } else if let Ok(ok) = character(input) {
+        Ok(ok)
+    } else if let Ok(ok) = float(input) {
+        Ok(ok)
+    } else if let Ok(ok) = int(input) {
+        Ok(ok)
+    } else {
+        Err(LexError)
+    }
+}
+
+fn literal_suffix(input: Cursor) -> Cursor {
+    match ident_not_raw(input) {
+        Ok((input, _)) => input,
+        Err(LexError) => input,
+    }
+}
+
+fn string(input: Cursor) -> Result<Cursor, LexError> {
+    if let Ok(input) = input.parse("\"") {
+        cooked_string(input)
+    } else if let Ok(input) = input.parse("r") {
+        raw_string(input)
+    } else {
+        Err(LexError)
+    }
+}
+
+fn cooked_string(input: Cursor) -> Result<Cursor, LexError> {
+    let mut chars = input.char_indices().peekable();
+
+    while let Some((i, ch)) = chars.next() {
+        match ch {
+            '"' => {
+                let input = input.advance(i + 1);
+                return Ok(literal_suffix(input));
+            }
+            '\r' => {
+                if let Some((_, '\n')) = chars.next() {
+                    // ...
+                } else {
+                    break;
+                }
+            }
+            '\\' => match chars.next() {
+                Some((_, 'x')) => {
+                    if !backslash_x_char(&mut chars) {
+                        break;
+                    }
+                }
+                Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
+                | Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {}
+                Some((_, 'u')) => {
+                    if !backslash_u(&mut chars) {
+                        break;
+                    }
+                }
+                Some((_, '\n')) | Some((_, '\r')) => {
+                    while let Some(&(_, ch)) = chars.peek() {
+                        if ch.is_whitespace() {
+                            chars.next();
+                        } else {
+                            break;
+                        }
+                    }
+                }
+                _ => break,
+            },
+            _ch => {}
+        }
+    }
+    Err(LexError)
+}
+
+fn byte_string(input: Cursor) -> Result<Cursor, LexError> {
+    if let Ok(input) = input.parse("b\"") {
+        cooked_byte_string(input)
+    } else if let Ok(input) = input.parse("br") {
+        raw_string(input)
+    } else {
+        Err(LexError)
+    }
+}
+
+fn cooked_byte_string(mut input: Cursor) -> Result<Cursor, LexError> {
+    let mut bytes = input.bytes().enumerate();
+    'outer: while let Some((offset, b)) = bytes.next() {
+        match b {
+            b'"' => {
+                let input = input.advance(offset + 1);
+                return Ok(literal_suffix(input));
+            }
+            b'\r' => {
+                if let Some((_, b'\n')) = bytes.next() {
+                    // ...
+                } else {
+                    break;
+                }
+            }
+            b'\\' => match bytes.next() {
+                Some((_, b'x')) => {
+                    if !backslash_x_byte(&mut bytes) {
+                        break;
+                    }
+                }
+                Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\'))
+                | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {}
+                Some((newline, b'\n')) | Some((newline, b'\r')) => {
+                    let rest = input.advance(newline + 1);
+                    for (offset, ch) in rest.char_indices() {
+                        if !ch.is_whitespace() {
+                            input = rest.advance(offset);
+                            bytes = input.bytes().enumerate();
+                            continue 'outer;
+                        }
+                    }
+                    break;
+                }
+                _ => break,
+            },
+            b if b < 0x80 => {}
+            _ => break,
+        }
+    }
+    Err(LexError)
+}
+
+fn raw_string(input: Cursor) -> Result<Cursor, LexError> {
+    let mut chars = input.char_indices();
+    let mut n = 0;
+    while let Some((i, ch)) = chars.next() {
+        match ch {
+            '"' => {
+                n = i;
+                break;
+            }
+            '#' => {}
+            _ => return Err(LexError),
+        }
+    }
+    for (i, ch) in chars {
+        match ch {
+            '"' if input.rest[i + 1..].starts_with(&input.rest[..n]) => {
+                let rest = input.advance(i + 1 + n);
+                return Ok(literal_suffix(rest));
+            }
+            '\r' => {}
+            _ => {}
+        }
+    }
+    Err(LexError)
+}
+
+fn byte(input: Cursor) -> Result<Cursor, LexError> {
+    let input = input.parse("b'")?;
+    let mut bytes = input.bytes().enumerate();
+    let ok = match bytes.next().map(|(_, b)| b) {
+        Some(b'\\') => match bytes.next().map(|(_, b)| b) {
+            Some(b'x') => backslash_x_byte(&mut bytes),
+            Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'')
+            | Some(b'"') => true,
+            _ => false,
+        },
+        b => b.is_some(),
+    };
+    if !ok {
+        return Err(LexError);
+    }
+    let (offset, _) = bytes.next().ok_or(LexError)?;
+    if !input.chars().as_str().is_char_boundary(offset) {
+        return Err(LexError);
+    }
+    let input = input.advance(offset).parse("'")?;
+    Ok(literal_suffix(input))
+}
+
+fn character(input: Cursor) -> Result<Cursor, LexError> {
+    let input = input.parse("'")?;
+    let mut chars = input.char_indices();
+    let ok = match chars.next().map(|(_, ch)| ch) {
+        Some('\\') => match chars.next().map(|(_, ch)| ch) {
+            Some('x') => backslash_x_char(&mut chars),
+            Some('u') => backslash_u(&mut chars),
+            Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => {
+                true
+            }
+            _ => false,
+        },
+        ch => ch.is_some(),
+    };
+    if !ok {
+        return Err(LexError);
+    }
+    let (idx, _) = chars.next().ok_or(LexError)?;
+    let input = input.advance(idx).parse("'")?;
+    Ok(literal_suffix(input))
+}
+
+macro_rules! next_ch {
+    ($chars:ident @ $pat:pat $(| $rest:pat)*) => {
+        match $chars.next() {
+            Some((_, ch)) => match ch {
+                $pat $(| $rest)* => ch,
+                _ => return false,
+            },
+            None => return false,
+        }
+    };
+}
+
+fn backslash_x_char<I>(chars: &mut I) -> bool
+where
+    I: Iterator<Item = (usize, char)>,
+{
+    next_ch!(chars @ '0'..='7');
+    next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+    true
+}
+
+fn backslash_x_byte<I>(chars: &mut I) -> bool
+where
+    I: Iterator<Item = (usize, u8)>,
+{
+    next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
+    next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
+    true
+}
+
+fn backslash_u<I>(chars: &mut I) -> bool
+where
+    I: Iterator<Item = (usize, char)>,
+{
+    next_ch!(chars @ '{');
+    next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+    loop {
+        let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}');
+        if c == '}' {
+            return true;
+        }
+    }
+}
+
+fn float(input: Cursor) -> Result<Cursor, LexError> {
+    let mut rest = float_digits(input)?;
+    if let Some(ch) = rest.chars().next() {
+        if is_ident_start(ch) {
+            rest = ident_not_raw(rest)?.0;
+        }
+    }
+    word_break(rest)
+}
+
+fn float_digits(input: Cursor) -> Result<Cursor, LexError> {
+    let mut chars = input.chars().peekable();
+    match chars.next() {
+        Some(ch) if ch >= '0' && ch <= '9' => {}
+        _ => return Err(LexError),
+    }
+
+    let mut len = 1;
+    let mut has_dot = false;
+    let mut has_exp = false;
+    while let Some(&ch) = chars.peek() {
+        match ch {
+            '0'..='9' | '_' => {
+                chars.next();
+                len += 1;
+            }
+            '.' => {
+                if has_dot {
+                    break;
+                }
+                chars.next();
+                if chars
+                    .peek()
+                    .map(|&ch| ch == '.' || is_ident_start(ch))
+                    .unwrap_or(false)
+                {
+                    return Err(LexError);
+                }
+                len += 1;
+                has_dot = true;
+            }
+            'e' | 'E' => {
+                chars.next();
+                len += 1;
+                has_exp = true;
+                break;
+            }
+            _ => break,
+        }
+    }
+
+    let rest = input.advance(len);
+    if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) {
+        return Err(LexError);
+    }
+
+    if has_exp {
+        let mut has_exp_value = false;
+        while let Some(&ch) = chars.peek() {
+            match ch {
+                '+' | '-' => {
+                    if has_exp_value {
+                        break;
+                    }
+                    chars.next();
+                    len += 1;
+                }
+                '0'..='9' => {
+                    chars.next();
+                    len += 1;
+                    has_exp_value = true;
+                }
+                '_' => {
+                    chars.next();
+                    len += 1;
+                }
+                _ => break,
+            }
+        }
+        if !has_exp_value {
+            return Err(LexError);
+        }
+    }
+
+    Ok(input.advance(len))
+}
+
+fn int(input: Cursor) -> Result<Cursor, LexError> {
+    let mut rest = digits(input)?;
+    if let Some(ch) = rest.chars().next() {
+        if is_ident_start(ch) {
+            rest = ident_not_raw(rest)?.0;
+        }
+    }
+    word_break(rest)
+}
+
+fn digits(mut input: Cursor) -> Result<Cursor, LexError> {
+    let base = if input.starts_with("0x") {
+        input = input.advance(2);
+        16
+    } else if input.starts_with("0o") {
+        input = input.advance(2);
+        8
+    } else if input.starts_with("0b") {
+        input = input.advance(2);
+        2
+    } else {
+        10
+    };
+
+    let mut len = 0;
+    let mut empty = true;
+    for b in input.bytes() {
+        let digit = match b {
+            b'0'..=b'9' => (b - b'0') as u64,
+            b'a'..=b'f' => 10 + (b - b'a') as u64,
+            b'A'..=b'F' => 10 + (b - b'A') as u64,
+            b'_' => {
+                if empty && base == 10 {
+                    return Err(LexError);
+                }
+                len += 1;
+                continue;
+            }
+            _ => break,
+        };
+        if digit >= base {
+            return Err(LexError);
+        }
+        len += 1;
+        empty = false;
+    }
+    if empty {
+        Err(LexError)
+    } else {
+        Ok(input.advance(len))
+    }
+}
+
+fn op(input: Cursor) -> PResult<Punct> {
+    match op_char(input) {
+        Ok((rest, '\'')) => {
+            ident(rest)?;
+            Ok((rest, Punct::new('\'', Spacing::Joint)))
+        }
+        Ok((rest, ch)) => {
+            let kind = match op_char(rest) {
+                Ok(_) => Spacing::Joint,
+                Err(LexError) => Spacing::Alone,
+            };
+            Ok((rest, Punct::new(ch, kind)))
+        }
+        Err(LexError) => Err(LexError),
+    }
+}
+
+fn op_char(input: Cursor) -> PResult<char> {
+    if input.starts_with("//") || input.starts_with("/*") {
+        // Do not accept `/` of a comment as an op.
+        return Err(LexError);
+    }
+
+    let mut chars = input.chars();
+    let first = match chars.next() {
+        Some(ch) => ch,
+        None => {
+            return Err(LexError);
+        }
+    };
+    let recognized = "~!@#$%^&*-=+|;:,<.>/?'";
+    if recognized.contains(first) {
+        Ok((input.advance(first.len_utf8()), first))
+    } else {
+        Err(LexError)
+    }
+}
+
+fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> {
+    #[cfg(span_locations)]
+    let lo = input.off;
+    let (rest, (comment, inner)) = doc_comment_contents(input)?;
+    let span = crate::Span::_new_stable(Span {
+        #[cfg(span_locations)]
+        lo,
+        #[cfg(span_locations)]
+        hi: rest.off,
+    });
+
+    let mut scan_for_bare_cr = comment;
+    while let Some(cr) = scan_for_bare_cr.find('\r') {
+        let rest = &scan_for_bare_cr[cr + 1..];
+        if !rest.starts_with('\n') {
+            return Err(LexError);
+        }
+        scan_for_bare_cr = rest;
+    }
+
+    let mut trees = Vec::new();
+    trees.push(TokenTree::Punct(Punct::new('#', Spacing::Alone)));
+    if inner {
+        trees.push(Punct::new('!', Spacing::Alone).into());
+    }
+    let mut stream = vec![
+        TokenTree::Ident(crate::Ident::new("doc", span)),
+        TokenTree::Punct(Punct::new('=', Spacing::Alone)),
+        TokenTree::Literal(crate::Literal::string(comment)),
+    ];
+    for tt in stream.iter_mut() {
+        tt.set_span(span);
+    }
+    let group = Group::new(Delimiter::Bracket, stream.into_iter().collect());
+    trees.push(crate::Group::_new_stable(group).into());
+    for tt in trees.iter_mut() {
+        tt.set_span(span);
+    }
+    Ok((rest, trees))
+}
+
+fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> {
+    if input.starts_with("//!") {
+        let input = input.advance(3);
+        let (input, s) = take_until_newline_or_eof(input);
+        Ok((input, (s, true)))
+    } else if input.starts_with("/*!") {
+        let (input, s) = block_comment(input)?;
+        Ok((input, (&s[3..s.len() - 2], true)))
+    } else if input.starts_with("///") {
+        let input = input.advance(3);
+        if input.starts_with("/") {
+            return Err(LexError);
+        }
+        let (input, s) = take_until_newline_or_eof(input);
+        Ok((input, (s, false)))
+    } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') {
+        let (input, s) = block_comment(input)?;
+        Ok((input, (&s[3..s.len() - 2], false)))
+    } else {
+        Err(LexError)
+    }
+}
+
+fn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) {
+    let chars = input.char_indices();
+
+    for (i, ch) in chars {
+        if ch == '\n' {
+            return (input.advance(i), &input.rest[..i]);
+        } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') {
+            return (input.advance(i + 1), &input.rest[..i]);
+        }
+    }
+
+    (input.advance(input.len()), input.rest)
+}
deleted file mode 100644
--- a/third_party/rust/proc-macro2/src/strnom.rs
+++ /dev/null
@@ -1,391 +0,0 @@
-//! Adapted from [`nom`](https://github.com/Geal/nom).
-
-use crate::fallback::LexError;
-use std::str::{Bytes, CharIndices, Chars};
-use unicode_xid::UnicodeXID;
-
-#[derive(Copy, Clone, Eq, PartialEq)]
-pub struct Cursor<'a> {
-    pub rest: &'a str,
-    #[cfg(span_locations)]
-    pub off: u32,
-}
-
-impl<'a> Cursor<'a> {
-    #[cfg(not(span_locations))]
-    pub fn advance(&self, amt: usize) -> Cursor<'a> {
-        Cursor {
-            rest: &self.rest[amt..],
-        }
-    }
-    #[cfg(span_locations)]
-    pub fn advance(&self, amt: usize) -> Cursor<'a> {
-        Cursor {
-            rest: &self.rest[amt..],
-            off: self.off + (amt as u32),
-        }
-    }
-
-    pub fn find(&self, p: char) -> Option<usize> {
-        self.rest.find(p)
-    }
-
-    pub fn starts_with(&self, s: &str) -> bool {
-        self.rest.starts_with(s)
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.rest.is_empty()
-    }
-
-    pub fn len(&self) -> usize {
-        self.rest.len()
-    }
-
-    pub fn as_bytes(&self) -> &'a [u8] {
-        self.rest.as_bytes()
-    }
-
-    pub fn bytes(&self) -> Bytes<'a> {
-        self.rest.bytes()
-    }
-
-    pub fn chars(&self) -> Chars<'a> {
-        self.rest.chars()
-    }
-
-    pub fn char_indices(&self) -> CharIndices<'a> {
-        self.rest.char_indices()
-    }
-}
-
-pub type PResult<'a, O> = Result<(Cursor<'a>, O), LexError>;
-
-pub fn whitespace(input: Cursor) -> PResult<()> {
-    if input.is_empty() {
-        return Err(LexError);
-    }
-
-    let bytes = input.as_bytes();
-    let mut i = 0;
-    while i < bytes.len() {
-        let s = input.advance(i);
-        if bytes[i] == b'/' {
-            if s.starts_with("//")
-                && (!s.starts_with("///") || s.starts_with("////"))
-                && !s.starts_with("//!")
-            {
-                if let Some(len) = s.find('\n') {
-                    i += len + 1;
-                    continue;
-                }
-                break;
-            } else if s.starts_with("/**/") {
-                i += 4;
-                continue;
-            } else if s.starts_with("/*")
-                && (!s.starts_with("/**") || s.starts_with("/***"))
-                && !s.starts_with("/*!")
-            {
-                let (_, com) = block_comment(s)?;
-                i += com.len();
-                continue;
-            }
-        }
-        match bytes[i] {
-            b' ' | 0x09..=0x0d => {
-                i += 1;
-                continue;
-            }
-            b if b <= 0x7f => {}
-            _ => {
-                let ch = s.chars().next().unwrap();
-                if is_whitespace(ch) {
-                    i += ch.len_utf8();
-                    continue;
-                }
-            }
-        }
-        return if i > 0 { Ok((s, ())) } else { Err(LexError) };
-    }
-    Ok((input.advance(input.len()), ()))
-}
-
-pub fn block_comment(input: Cursor) -> PResult<&str> {
-    if !input.starts_with("/*") {
-        return Err(LexError);
-    }
-
-    let mut depth = 0;
-    let bytes = input.as_bytes();
-    let mut i = 0;
-    let upper = bytes.len() - 1;
-    while i < upper {
-        if bytes[i] == b'/' && bytes[i + 1] == b'*' {
-            depth += 1;
-            i += 1; // eat '*'
-        } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
-            depth -= 1;
-            if depth == 0 {
-                return Ok((input.advance(i + 2), &input.rest[..i + 2]));
-            }
-            i += 1; // eat '/'
-        }
-        i += 1;
-    }
-    Err(LexError)
-}
-
-pub fn skip_whitespace(input: Cursor) -> Cursor {
-    match whitespace(input) {
-        Ok((rest, _)) => rest,
-        Err(LexError) => input,
-    }
-}
-
-fn is_whitespace(ch: char) -> bool {
-    // Rust treats left-to-right mark and right-to-left mark as whitespace
-    ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
-}
-
-pub fn word_break(input: Cursor) -> PResult<()> {
-    match input.chars().next() {
-        Some(ch) if UnicodeXID::is_xid_continue(ch) => Err(LexError),
-        Some(_) | None => Ok((input, ())),
-    }
-}
-
-macro_rules! named {
-    ($name:ident -> $o:ty, $submac:ident!( $($args:tt)* )) => {
-        fn $name<'a>(i: Cursor<'a>) -> $crate::strnom::PResult<'a, $o> {
-            $submac!(i, $($args)*)
-        }
-    };
-}
-
-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 @ Ok(_) => res,
-            _ => alt!($i, $($rest)*)
-        }
-    };
-
-    ($i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)+) => {
-        match $subrule!($i, $($args)*) {
-            Ok((i, o)) => Ok((i, $gen(o))),
-            Err(LexError) => 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)*) {
-            Ok((i, o)) => Ok((i, $gen(o))),
-            Err(LexError) => Err(LexError),
-        }
-    };
-
-    ($i:expr, $e:ident) => {
-        alt!($i, call!($e))
-    };
-
-    ($i:expr, $subrule:ident!( $($args:tt)*)) => {
-        $subrule!($i, $($args)*)
-    };
-}
-
-macro_rules! do_parse {
-    ($i:expr, ( $($rest:expr),* )) => {
-        Ok(($i, ( $($rest),* )))
-    };
-
-    ($i:expr, $e:ident >> $($rest:tt)*) => {
-        do_parse!($i, call!($e) >> $($rest)*)
-    };
-
-    ($i:expr, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => {
-        match $submac!($i, $($args)*) {
-            Err(LexError) => Err(LexError),
-            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)*) {
-            Err(LexError) => Err(LexError),
-            Ok((i, o)) => {
-                let $field = o;
-                do_parse!(i, $($rest)*)
-            },
-        }
-    };
-}
-
-macro_rules! peek {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        match $submac!($i, $($args)*) {
-            Ok((_, o)) => Ok(($i, o)),
-            Err(LexError) => Err(LexError),
-        }
-    };
-}
-
-macro_rules! call {
-    ($i:expr, $fun:expr $(, $args:expr)*) => {
-        $fun($i $(, $args)*)
-    };
-}
-
-macro_rules! option {
-    ($i:expr, $f:expr) => {
-        match $f($i) {
-            Ok((i, o)) => Ok((i, Some(o))),
-            Err(LexError) => Ok(($i, None)),
-        }
-    };
-}
-
-macro_rules! take_until_newline_or_eof {
-    ($i:expr,) => {{
-        if $i.len() == 0 {
-            Ok(($i, ""))
-        } else {
-            match $i.find('\n') {
-                Some(i) => Ok(($i.advance(i), &$i.rest[..i])),
-                None => Ok(($i.advance($i.len()), &$i.rest[..$i.len()])),
-            }
-        }
-    }};
-}
-
-macro_rules! tuple {
-    ($i:expr, $($rest:tt)*) => {
-        tuple_parser!($i, (), $($rest)*)
-    };
-}
-
-/// Do not use directly. Use `tuple!`.
-macro_rules! tuple_parser {
-    ($i:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => {
-        tuple_parser!($i, ($($parsed),*), call!($e), $($rest)*)
-    };
-
-    ($i:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
-        match $submac!($i, $($args)*) {
-            Err(LexError) => Err(LexError),
-            Ok((i, o)) => tuple_parser!(i, (o), $($rest)*),
-        }
-    };
-
-    ($i:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => {
-        match $submac!($i, $($args)*) {
-            Err(LexError) => Err(LexError),
-            Ok((i, o)) => tuple_parser!(i, ($($parsed)* , o), $($rest)*),
-        }
-    };
-
-    ($i:expr, ($($parsed:tt),*), $e:ident) => {
-        tuple_parser!($i, ($($parsed),*), call!($e))
-    };
-
-    ($i:expr, (), $submac:ident!( $($args:tt)* )) => {
-        $submac!($i, $($args)*)
-    };
-
-    ($i:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => {
-        match $submac!($i, $($args)*) {
-            Err(LexError) => Err(LexError),
-            Ok((i, o)) => Ok((i, ($($parsed),*, o)))
-        }
-    };
-
-    ($i:expr, ($($parsed:expr),*)) => {
-        Ok(($i, ($($parsed),*)))
-    };
-}
-
-macro_rules! not {
-    ($i:expr, $submac:ident!( $($args:tt)* )) => {
-        match $submac!($i, $($args)*) {
-            Ok((_, _)) => Err(LexError),
-            Err(LexError) => Ok(($i, ())),
-        }
-    };
-}
-
-macro_rules! tag {
-    ($i:expr, $tag:expr) => {
-        if $i.starts_with($tag) {
-            Ok(($i.advance($tag.len()), &$i.rest[..$tag.len()]))
-        } else {
-            Err(LexError)
-        }
-    };
-}
-
-macro_rules! punct {
-    ($i:expr, $punct:expr) => {
-        $crate::strnom::punct($i, $punct)
-    };
-}
-
-/// Do not use directly. Use `punct!`.
-pub fn punct<'a>(input: Cursor<'a>, token: &'static str) -> PResult<'a, &'a str> {
-    let input = skip_whitespace(input);
-    if input.starts_with(token) {
-        Ok((input.advance(token.len()), token))
-    } else {
-        Err(LexError)
-    }
-}
-
-macro_rules! preceded {
-    ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => {
-        match tuple!($i, $submac!($($args)*), $submac2!($($args2)*)) {
-            Ok((remaining, (_, o))) => Ok((remaining, o)),
-            Err(LexError) => Err(LexError),
-        }
-    };
-
-    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        preceded!($i, $submac!($($args)*), call!($g))
-    };
-}
-
-macro_rules! delimited {
-    ($i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)+) => {
-        match tuple_parser!($i, (), $submac!($($args)*), $($rest)*) {
-            Err(LexError) => Err(LexError),
-            Ok((i1, (_, o, _))) => Ok((i1, o))
-        }
-    };
-}
-
-macro_rules! map {
-    ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => {
-        match $submac!($i, $($args)*) {
-            Err(LexError) => Err(LexError),
-            Ok((i, o)) => Ok((i, call!(o, $g)))
-        }
-    };
-
-    ($i:expr, $f:expr, $g:expr) => {
-        map!($i, call!($f), $g)
-    };
-}
--- a/third_party/rust/proc-macro2/src/wrapper.rs
+++ b/third_party/rust/proc-macro2/src/wrapper.rs
@@ -1,96 +1,39 @@
-use std::fmt;
-use std::iter;
+use crate::detection::inside_proc_macro;
+use crate::{fallback, Delimiter, Punct, Spacing, TokenTree};
+use std::fmt::{self, Debug, Display};
+use std::iter::FromIterator;
 use std::ops::RangeBounds;
-use std::panic::{self, PanicInfo};
+use std::panic;
 #[cfg(super_unstable)]
 use std::path::PathBuf;
 use std::str::FromStr;
 
-use crate::{fallback, Delimiter, Punct, Spacing, TokenTree};
-
 #[derive(Clone)]
-pub enum TokenStream {
+pub(crate) enum TokenStream {
     Compiler(DeferredTokenStream),
     Fallback(fallback::TokenStream),
 }
 
 // Work around https://github.com/rust-lang/rust/issues/65080.
 // In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote,
 // we hold on to the appended tokens and do proc_macro::TokenStream::extend as
 // late as possible to batch together consecutive uses of the Extend impl.
 #[derive(Clone)]
-pub struct DeferredTokenStream {
+pub(crate) struct DeferredTokenStream {
     stream: proc_macro::TokenStream,
     extra: Vec<proc_macro::TokenTree>,
 }
 
-pub enum LexError {
+pub(crate) enum LexError {
     Compiler(proc_macro::LexError),
     Fallback(fallback::LexError),
 }
 
-fn nightly_works() -> bool {
-    use std::sync::atomic::*;
-    use std::sync::Once;
-
-    static WORKS: AtomicUsize = AtomicUsize::new(0);
-    static INIT: Once = Once::new();
-
-    match WORKS.load(Ordering::SeqCst) {
-        1 => return false,
-        2 => return true,
-        _ => {}
-    }
-
-    // Swap in a null panic hook to avoid printing "thread panicked" to stderr,
-    // then use catch_unwind to determine whether the compiler's proc_macro is
-    // working. When proc-macro2 is used from outside of a procedural macro all
-    // of the proc_macro crate's APIs currently panic.
-    //
-    // The Once is to prevent the possibility of this ordering:
-    //
-    //     thread 1 calls take_hook, gets the user's original hook
-    //     thread 1 calls set_hook with the null hook
-    //     thread 2 calls take_hook, thinks null hook is the original hook
-    //     thread 2 calls set_hook with the null hook
-    //     thread 1 calls set_hook with the actual original hook
-    //     thread 2 calls set_hook with what it thinks is the original hook
-    //
-    // in which the user's hook has been lost.
-    //
-    // There is still a race condition where a panic in a different thread can
-    // happen during the interval that the user's original panic hook is
-    // unregistered such that their hook is incorrectly not called. This is
-    // sufficiently unlikely and less bad than printing panic messages to stderr
-    // on correct use of this crate. Maybe there is a libstd feature request
-    // here. For now, if a user needs to guarantee that this failure mode does
-    // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from
-    // the main thread before launching any other threads.
-    INIT.call_once(|| {
-        type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static;
-
-        let null_hook: Box<PanicHook> = Box::new(|_panic_info| { /* ignore */ });
-        let sanity_check = &*null_hook as *const PanicHook;
-        let original_hook = panic::take_hook();
-        panic::set_hook(null_hook);
-
-        let works = panic::catch_unwind(|| proc_macro::Span::call_site()).is_ok();
-        WORKS.store(works as usize + 1, Ordering::SeqCst);
-
-        let hopefully_null_hook = panic::take_hook();
-        panic::set_hook(original_hook);
-        if sanity_check != &*hopefully_null_hook {
-            panic!("observed race condition in proc_macro2::nightly_works");
-        }
-    });
-    nightly_works()
-}
-
 fn mismatch() -> ! {
     panic!("stable/nightly mismatch")
 }
 
 impl DeferredTokenStream {
     fn new(stream: proc_macro::TokenStream) -> Self {
         DeferredTokenStream {
             stream,
@@ -98,28 +41,33 @@ impl DeferredTokenStream {
         }
     }
 
     fn is_empty(&self) -> bool {
         self.stream.is_empty() && self.extra.is_empty()
     }
 
     fn evaluate_now(&mut self) {
-        self.stream.extend(self.extra.drain(..));
+        // If-check provides a fast short circuit for the common case of `extra`
+        // being empty, which saves a round trip over the proc macro bridge.
+        // Improves macro expansion time in winrt by 6% in debug mode.
+        if !self.extra.is_empty() {
+            self.stream.extend(self.extra.drain(..));
+        }
     }
 
     fn into_token_stream(mut self) -> proc_macro::TokenStream {
         self.evaluate_now();
         self.stream
     }
 }
 
 impl TokenStream {
     pub fn new() -> TokenStream {
-        if nightly_works() {
+        if inside_proc_macro() {
             TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new()))
         } else {
             TokenStream::Fallback(fallback::TokenStream::new())
         }
     }
 
     pub fn is_empty(&self) -> bool {
         match self {
@@ -142,31 +90,37 @@ impl TokenStream {
         }
     }
 }
 
 impl FromStr for TokenStream {
     type Err = LexError;
 
     fn from_str(src: &str) -> Result<TokenStream, LexError> {
-        if nightly_works() {
+        if inside_proc_macro() {
             Ok(TokenStream::Compiler(DeferredTokenStream::new(
-                src.parse()?,
+                proc_macro_parse(src)?,
             )))
         } else {
             Ok(TokenStream::Fallback(src.parse()?))
         }
     }
 }
 
-impl fmt::Display for TokenStream {
+// Work around https://github.com/rust-lang/rust/issues/58736.
+fn proc_macro_parse(src: &str) -> Result<proc_macro::TokenStream, LexError> {
+    panic::catch_unwind(|| src.parse().map_err(LexError::Compiler))
+        .unwrap_or(Err(LexError::Fallback(fallback::LexError)))
+}
+
+impl Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f),
-            TokenStream::Fallback(tts) => tts.fmt(f),
+            TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f),
+            TokenStream::Fallback(tts) => Display::fmt(tts, f),
         }
     }
 }
 
 impl From<proc_macro::TokenStream> for TokenStream {
     fn from(inner: proc_macro::TokenStream) -> TokenStream {
         TokenStream::Compiler(DeferredTokenStream::new(inner))
     }
@@ -182,17 +136,17 @@ impl From<TokenStream> for proc_macro::T
 }
 
 impl From<fallback::TokenStream> for TokenStream {
     fn from(inner: fallback::TokenStream) -> TokenStream {
         TokenStream::Fallback(inner)
     }
 }
 
-// Assumes nightly_works().
+// Assumes inside_proc_macro().
 fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree {
     match token {
         TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(),
         TokenTree::Punct(tt) => {
             let spacing = match tt.spacing() {
                 Spacing::Joint => proc_macro::Spacing::Joint,
                 Spacing::Alone => proc_macro::Spacing::Alone,
             };
@@ -202,37 +156,37 @@ fn into_compiler_token(token: TokenTree)
         }
         TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(),
         TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(),
     }
 }
 
 impl From<TokenTree> for TokenStream {
     fn from(token: TokenTree) -> TokenStream {
-        if nightly_works() {
+        if inside_proc_macro() {
             TokenStream::Compiler(DeferredTokenStream::new(into_compiler_token(token).into()))
         } else {
             TokenStream::Fallback(token.into())
         }
     }
 }
 
-impl iter::FromIterator<TokenTree> for TokenStream {
+impl FromIterator<TokenTree> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
-        if nightly_works() {
+        if inside_proc_macro() {
             TokenStream::Compiler(DeferredTokenStream::new(
                 trees.into_iter().map(into_compiler_token).collect(),
             ))
         } else {
             TokenStream::Fallback(trees.into_iter().collect())
         }
     }
 }
 
-impl iter::FromIterator<TokenStream> for TokenStream {
+impl FromIterator<TokenStream> for TokenStream {
     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
         let mut streams = streams.into_iter();
         match streams.next() {
             Some(TokenStream::Compiler(mut first)) => {
                 first.evaluate_now();
                 first.stream.extend(streams.map(|s| match s {
                     TokenStream::Compiler(s) => s.into_token_stream(),
                     TokenStream::Fallback(_) => mismatch(),
@@ -247,75 +201,76 @@ impl iter::FromIterator<TokenStream> for
                 TokenStream::Fallback(first)
             }
             None => TokenStream::new(),
         }
     }
 }
 
 impl Extend<TokenTree> for TokenStream {
-    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
+    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, stream: I) {
         match self {
             TokenStream::Compiler(tts) => {
                 // Here is the reason for DeferredTokenStream.
-                tts.extra
-                    .extend(streams.into_iter().map(into_compiler_token));
+                for token in stream {
+                    tts.extra.push(into_compiler_token(token));
+                }
             }
-            TokenStream::Fallback(tts) => tts.extend(streams),
+            TokenStream::Fallback(tts) => tts.extend(stream),
         }
     }
 }
 
 impl Extend<TokenStream> for TokenStream {
     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
         match self {
             TokenStream::Compiler(tts) => {
                 tts.evaluate_now();
                 tts.stream
-                    .extend(streams.into_iter().map(|stream| stream.unwrap_nightly()));
+                    .extend(streams.into_iter().map(TokenStream::unwrap_nightly));
             }
             TokenStream::Fallback(tts) => {
-                tts.extend(streams.into_iter().map(|stream| stream.unwrap_stable()));
+                tts.extend(streams.into_iter().map(TokenStream::unwrap_stable));
             }
         }
     }
 }
 
-impl fmt::Debug for TokenStream {
+impl Debug for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            TokenStream::Compiler(tts) => tts.clone().into_token_stream().fmt(f),
-            TokenStream::Fallback(tts) => tts.fmt(f),
+            TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f),
+            TokenStream::Fallback(tts) => Debug::fmt(tts, f),
         }
     }
 }
 
 impl From<proc_macro::LexError> for LexError {
     fn from(e: proc_macro::LexError) -> LexError {
         LexError::Compiler(e)
     }
 }
 
 impl From<fallback::LexError> for LexError {
     fn from(e: fallback::LexError) -> LexError {
         LexError::Fallback(e)
     }
 }
 
-impl fmt::Debug for LexError {
+impl Debug for LexError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            LexError::Compiler(e) => e.fmt(f),
-            LexError::Fallback(e) => e.fmt(f),
+            LexError::Compiler(e) => Debug::fmt(e, f),
+            LexError::Fallback(e) => Debug::fmt(e, f),
         }
     }
 }
 
 #[derive(Clone)]
-pub enum TokenTreeIter {
+pub(crate) enum TokenTreeIter {
     Compiler(proc_macro::token_stream::IntoIter),
     Fallback(fallback::TokenTreeIter),
 }
 
 impl IntoIterator for TokenStream {
     type Item = TokenTree;
     type IntoIter = TokenTreeIter;
 
@@ -356,25 +311,25 @@ impl Iterator for TokenTreeIter {
     fn size_hint(&self) -> (usize, Option<usize>) {
         match self {
             TokenTreeIter::Compiler(tts) => tts.size_hint(),
             TokenTreeIter::Fallback(tts) => tts.size_hint(),
         }
     }
 }
 
-impl fmt::Debug for TokenTreeIter {
+impl Debug for TokenTreeIter {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("TokenTreeIter").finish()
     }
 }
 
 #[derive(Clone, PartialEq, Eq)]
 #[cfg(super_unstable)]
-pub enum SourceFile {
+pub(crate) enum SourceFile {
     Compiler(proc_macro::SourceFile),
     Fallback(fallback::SourceFile),
 }
 
 #[cfg(super_unstable)]
 impl SourceFile {
     fn nightly(sf: proc_macro::SourceFile) -> Self {
         SourceFile::Compiler(sf)
@@ -392,68 +347,87 @@ impl SourceFile {
         match self {
             SourceFile::Compiler(a) => a.is_real(),
             SourceFile::Fallback(a) => a.is_real(),
         }
     }
 }
 
 #[cfg(super_unstable)]
-impl fmt::Debug for SourceFile {
+impl Debug for SourceFile {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            SourceFile::Compiler(a) => a.fmt(f),
-            SourceFile::Fallback(a) => a.fmt(f),
+            SourceFile::Compiler(a) => Debug::fmt(a, f),
+            SourceFile::Fallback(a) => Debug::fmt(a, f),
         }
     }
 }
 
 #[cfg(any(super_unstable, feature = "span-locations"))]
-pub struct LineColumn {
+pub(crate) struct LineColumn {
     pub line: usize,
     pub column: usize,
 }
 
 #[derive(Copy, Clone)]
-pub enum Span {
+pub(crate) enum Span {
     Compiler(proc_macro::Span),
     Fallback(fallback::Span),
 }
 
 impl Span {
     pub fn call_site() -> Span {
-        if nightly_works() {
+        if inside_proc_macro() {
             Span::Compiler(proc_macro::Span::call_site())
         } else {
             Span::Fallback(fallback::Span::call_site())
         }
     }
 
+    #[cfg(hygiene)]
+    pub fn mixed_site() -> Span {
+        if inside_proc_macro() {
+            Span::Compiler(proc_macro::Span::mixed_site())
+        } else {
+            Span::Fallback(fallback::Span::mixed_site())
+        }
+    }
+
     #[cfg(super_unstable)]
     pub fn def_site() -> Span {
-        if nightly_works() {
+        if inside_proc_macro() {
             Span::Compiler(proc_macro::Span::def_site())
         } else {
             Span::Fallback(fallback::Span::def_site())
         }
     }
 
-    #[cfg(super_unstable)]
     pub fn resolved_at(&self, other: Span) -> Span {
         match (self, other) {
+            #[cfg(hygiene)]
             (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)),
+
+            // Name resolution affects semantics, but location is only cosmetic
+            #[cfg(not(hygiene))]
+            (Span::Compiler(_), Span::Compiler(_)) => other,
+
             (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)),
             _ => mismatch(),
         }
     }
 
-    #[cfg(super_unstable)]
     pub fn located_at(&self, other: Span) -> Span {
         match (self, other) {
+            #[cfg(hygiene)]
             (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)),
+
+            // Name resolution affects semantics, but location is only cosmetic
+            #[cfg(not(hygiene))]
+            (Span::Compiler(_), Span::Compiler(_)) => *self,
+
             (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)),
             _ => mismatch(),
         }
     }
 
     pub fn unwrap(self) -> proc_macro::Span {
         match self {
             Span::Compiler(s) => s,
@@ -537,36 +511,36 @@ impl From<proc_macro::Span> for crate::S
 }
 
 impl From<fallback::Span> for Span {
     fn from(inner: fallback::Span) -> Span {
         Span::Fallback(inner)
     }
 }
 
-impl fmt::Debug for Span {
+impl Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Span::Compiler(s) => s.fmt(f),
-            Span::Fallback(s) => s.fmt(f),
+            Span::Compiler(s) => Debug::fmt(s, f),
+            Span::Fallback(s) => Debug::fmt(s, f),
         }
     }
 }
 
-pub fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
+pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
     match span {
         Span::Compiler(s) => {
             debug.field("span", &s);
         }
         Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s),
     }
 }
 
 #[derive(Clone)]
-pub enum Group {
+pub(crate) enum Group {
     Compiler(proc_macro::Group),
     Fallback(fallback::Group),
 }
 
 impl Group {
     pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
         match stream {
             TokenStream::Compiler(tts) => {
@@ -647,36 +621,36 @@ impl Group {
 }
 
 impl From<fallback::Group> for Group {
     fn from(g: fallback::Group) -> Self {
         Group::Fallback(g)
     }
 }
 
-impl fmt::Display for Group {
+impl Display for Group {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Group::Compiler(group) => group.fmt(formatter),
-            Group::Fallback(group) => group.fmt(formatter),
+            Group::Compiler(group) => Display::fmt(group, formatter),
+            Group::Fallback(group) => Display::fmt(group, formatter),
         }
     }
 }
 
-impl fmt::Debug for Group {
+impl Debug for Group {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Group::Compiler(group) => group.fmt(formatter),
-            Group::Fallback(group) => group.fmt(formatter),
+            Group::Compiler(group) => Debug::fmt(group, formatter),
+            Group::Fallback(group) => Debug::fmt(group, formatter),
         }
     }
 }
 
 #[derive(Clone)]
-pub enum Ident {
+pub(crate) enum Ident {
     Compiler(proc_macro::Ident),
     Fallback(fallback::Ident),
 }
 
 impl Ident {
     pub fn new(string: &str, span: Span) -> Ident {
         match span {
             Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)),
@@ -742,56 +716,56 @@ where
         let other = other.as_ref();
         match self {
             Ident::Compiler(t) => t.to_string() == other,
             Ident::Fallback(t) => t == other,
         }
     }
 }
 
-impl fmt::Display for Ident {
+impl Display for Ident {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Ident::Compiler(t) => t.fmt(f),
-            Ident::Fallback(t) => t.fmt(f),
+            Ident::Compiler(t) => Display::fmt(t, f),
+            Ident::Fallback(t) => Display::fmt(t, f),
         }
     }
 }
 
-impl fmt::Debug for Ident {
+impl Debug for Ident {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Ident::Compiler(t) => t.fmt(f),
-            Ident::Fallback(t) => t.fmt(f),
+            Ident::Compiler(t) => Debug::fmt(t, f),
+            Ident::Fallback(t) => Debug::fmt(t, f),
         }
     }
 }
 
 #[derive(Clone)]
-pub enum Literal {
+pub(crate) enum Literal {
     Compiler(proc_macro::Literal),
     Fallback(fallback::Literal),
 }
 
 macro_rules! suffixed_numbers {
     ($($name:ident => $kind:ident,)*) => ($(
         pub fn $name(n: $kind) -> Literal {
-            if nightly_works() {
+            if inside_proc_macro() {
                 Literal::Compiler(proc_macro::Literal::$name(n))
             } else {
                 Literal::Fallback(fallback::Literal::$name(n))
             }
         }
     )*)
 }
 
 macro_rules! unsuffixed_integers {
     ($($name:ident => $kind:ident,)*) => ($(
         pub fn $name(n: $kind) -> Literal {
-            if nightly_works() {
+            if inside_proc_macro() {
                 Literal::Compiler(proc_macro::Literal::$name(n))
             } else {
                 Literal::Fallback(fallback::Literal::$name(n))
             }
         }
     )*)
 }
 
@@ -825,49 +799,49 @@ impl Literal {
         i16_unsuffixed => i16,
         i32_unsuffixed => i32,
         i64_unsuffixed => i64,
         i128_unsuffixed => i128,
         isize_unsuffixed => isize,
     }
 
     pub fn f32_unsuffixed(f: f32) -> Literal {
-        if nightly_works() {
+        if inside_proc_macro() {
             Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f))
         } else {
             Literal::Fallback(fallback::Literal::f32_unsuffixed(f))
         }
     }
 
     pub fn f64_unsuffixed(f: f64) -> Literal {
-        if nightly_works() {
+        if inside_proc_macro() {
             Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f))
         } else {
             Literal::Fallback(fallback::Literal::f64_unsuffixed(f))
         }
     }
 
     pub fn string(t: &str) -> Literal {
-        if nightly_works() {
+        if inside_proc_macro() {
             Literal::Compiler(proc_macro::Literal::string(t))
         } else {
             Literal::Fallback(fallback::Literal::string(t))
         }
     }
 
     pub fn character(t: char) -> Literal {
-        if nightly_works() {
+        if inside_proc_macro() {
             Literal::Compiler(proc_macro::Literal::character(t))
         } else {
             Literal::Fallback(fallback::Literal::character(t))
         }
     }
 
     pub fn byte_string(bytes: &[u8]) -> Literal {
-        if nightly_works() {
+        if inside_proc_macro() {
             Literal::Compiler(proc_macro::Literal::byte_string(bytes))
         } else {
             Literal::Fallback(fallback::Literal::byte_string(bytes))
         }
     }
 
     pub fn span(&self) -> Span {
         match self {
@@ -903,25 +877,25 @@ impl Literal {
 }
 
 impl From<fallback::Literal> for Literal {
     fn from(s: fallback::Literal) -> Literal {
         Literal::Fallback(s)
     }
 }
 
-impl fmt::Display for Literal {
+impl Display for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Literal::Compiler(t) => t.fmt(f),
-            Literal::Fallback(t) => t.fmt(f),
+            Literal::Compiler(t) => Display::fmt(t, f),
+            Literal::Fallback(t) => Display::fmt(t, f),
         }
     }
 }
 
-impl fmt::Debug for Literal {
+impl Debug for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Literal::Compiler(t) => t.fmt(f),
-            Literal::Fallback(t) => t.fmt(f),
+            Literal::Compiler(t) => Debug::fmt(t, f),
+            Literal::Fallback(t) => Debug::fmt(t, f),
         }
     }
 }
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2/tests/comments.rs
@@ -0,0 +1,103 @@
+use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree};
+
+// #[doc = "..."] -> "..."
+fn lit_of_outer_doc_comment(tokens: TokenStream) -> Literal {
+    lit_of_doc_comment(tokens, false)
+}
+
+// #![doc = "..."] -> "..."
+fn lit_of_inner_doc_comment(tokens: TokenStream) -> Literal {
+    lit_of_doc_comment(tokens, true)
+}
+
+fn lit_of_doc_comment(tokens: TokenStream, inner: bool) -> Literal {
+    let mut iter = tokens.clone().into_iter();
+    match iter.next().unwrap() {
+        TokenTree::Punct(punct) => {
+            assert_eq!(punct.as_char(), '#');
+            assert_eq!(punct.spacing(), Spacing::Alone);
+        }
+        _ => panic!("wrong token {:?}", tokens),
+    }
+    if inner {
+        match iter.next().unwrap() {
+            TokenTree::Punct(punct) => {
+                assert_eq!(punct.as_char(), '!');
+                assert_eq!(punct.spacing(), Spacing::Alone);
+            }
+            _ => panic!("wrong token {:?}", tokens),
+        }
+    }
+    iter = match iter.next().unwrap() {
+        TokenTree::Group(group) => {
+            assert_eq!(group.delimiter(), Delimiter::Bracket);
+            assert!(iter.next().is_none(), "unexpected token {:?}", tokens);
+            group.stream().into_iter()
+        }
+        _ => panic!("wrong token {:?}", tokens),
+    };
+    match iter.next().unwrap() {
+        TokenTree::Ident(ident) => assert_eq!(ident.to_string(), "doc"),
+        _ => panic!("wrong token {:?}", tokens),
+    }
+    match iter.next().unwrap() {
+        TokenTree::Punct(punct) => {
+            assert_eq!(punct.as_char(), '=');
+            assert_eq!(punct.spacing(), Spacing::Alone);
+        }
+        _ => panic!("wrong token {:?}", tokens),
+    }
+    match iter.next().unwrap() {
+        TokenTree::Literal(literal) => {
+            assert!(iter.next().is_none(), "unexpected token {:?}", tokens);
+            literal
+        }
+        _ => panic!("wrong token {:?}", tokens),
+    }
+}
+
+#[test]
+fn closed_immediately() {
+    let stream = "/**/".parse::<TokenStream>().unwrap();
+    let tokens = stream.into_iter().collect::<Vec<_>>();
+    assert!(tokens.is_empty(), "not empty -- {:?}", tokens);
+}
+
+#[test]
+fn incomplete() {
+    assert!("/*/".parse::<TokenStream>().is_err());
+}
+
+#[test]
+fn lit() {
+    let stream = "/// doc".parse::<TokenStream>().unwrap();
+    let lit = lit_of_outer_doc_comment(stream);
+    assert_eq!(lit.to_string(), "\" doc\"");
+
+    let stream = "//! doc".parse::<TokenStream>().unwrap();
+    let lit = lit_of_inner_doc_comment(stream);
+    assert_eq!(lit.to_string(), "\" doc\"");
+
+    let stream = "/** doc */".parse::<TokenStream>().unwrap();
+    let lit = lit_of_outer_doc_comment(stream);
+    assert_eq!(lit.to_string(), "\" doc \"");
+
+    let stream = "/*! doc */".parse::<TokenStream>().unwrap();
+    let lit = lit_of_inner_doc_comment(stream);
+    assert_eq!(lit.to_string(), "\" doc \"");
+}
+
+#[test]
+fn carriage_return() {
+    let stream = "///\r\n".parse::<TokenStream>().unwrap();
+    let lit = lit_of_outer_doc_comment(stream);
+    assert_eq!(lit.to_string(), "\"\"");
+
+    let stream = "/**\r\n*/".parse::<TokenStream>().unwrap();
+    let lit = lit_of_outer_doc_comment(stream);
+    assert_eq!(lit.to_string(), "\"\\r\\n\"");
+
+    "///\r".parse::<TokenStream>().unwrap_err();
+    "///\r \n".parse::<TokenStream>().unwrap_err();
+    "/**\r \n*/".parse::<TokenStream>().unwrap_err();
+}
--- a/third_party/rust/proc-macro2/tests/test.rs
+++ b/third_party/rust/proc-macro2/tests/test.rs
@@ -1,12 +1,11 @@
+use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree};
 use std::str::{self, FromStr};
 
-use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree};
-
 #[test]
 fn idents() {
     assert_eq!(
         Ident::new("String", Span::call_site()).to_string(),
         "String"
     );
     assert_eq!(Ident::new("fn", Span::call_site()).to_string(), "fn");
     assert_eq!(Ident::new("_", Span::call_site()).to_string(), "_");
@@ -105,16 +104,43 @@ fn literal_suffix() {
     assert_eq!(token_count("999u256"), 1);
     assert_eq!(token_count("999r#u256"), 3);
     assert_eq!(token_count("1."), 1);
     assert_eq!(token_count("1.f32"), 3);
     assert_eq!(token_count("1.0_0"), 1);
     assert_eq!(token_count("1._0"), 3);
     assert_eq!(token_count("1._m"), 3);
     assert_eq!(token_count("\"\"s"), 1);
+    assert_eq!(token_count("r\"\"r"), 1);
+    assert_eq!(token_count("b\"\"b"), 1);
+    assert_eq!(token_count("br\"\"br"), 1);
+    assert_eq!(token_count("r#\"\"#r"), 1);
+    assert_eq!(token_count("'c'c"), 1);
+    assert_eq!(token_count("b'b'b"), 1);
+}
+
+#[test]
+fn literal_iter_negative() {
+    let negative_literal = Literal::i32_suffixed(-3);
+    let tokens = TokenStream::from(TokenTree::Literal(negative_literal));
+    let mut iter = tokens.into_iter();
+    match iter.next().unwrap() {
+        TokenTree::Punct(punct) => {
+            assert_eq!(punct.as_char(), '-');
+            assert_eq!(punct.spacing(), Spacing::Alone);
+        }
+        unexpected => panic!("unexpected token {:?}", unexpected),
+    }
+    match iter.next().unwrap() {
+        TokenTree::Literal(literal) => {
+            assert_eq!(literal.to_string(), "3i32");
+        }
+        unexpected => panic!("unexpected token {:?}", unexpected),
+    }
+    assert!(iter.next().is_none());
 }
 
 #[test]
 fn roundtrip() {
     fn roundtrip(p: &str) {
         println!("parse: {}", p);
         let s = p.parse::<TokenStream>().unwrap().to_string();
         println!("first: {}", s);
@@ -161,46 +187,16 @@ fn fail() {
     fail("' static");
     fail("r#1");
     fail("r#_");
 }
 
 #[cfg(span_locations)]
 #[test]
 fn span_test() {
-    use proc_macro2::TokenTree;
-
-    fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) {
-        let ts = p.parse::<TokenStream>().unwrap();
-        check_spans_internal(ts, &mut lines);
-    }
-
-    fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) {
-        for i in ts {
-            if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() {
-                *lines = rest;
-
-                let start = i.span().start();
-                assert_eq!(start.line, sline, "sline did not match for {}", i);
-                assert_eq!(start.column, scol, "scol did not match for {}", i);
-
-                let end = i.span().end();
-                assert_eq!(end.line, eline, "eline did not match for {}", i);
-                assert_eq!(end.column, ecol, "ecol did not match for {}", i);
-
-                match i {
-                    TokenTree::Group(ref g) => {
-                        check_spans_internal(g.stream().clone(), lines);
-                    }
-                    _ => {}
-                }
-            }
-        }
-    }
-
     check_spans(
         "\
 /// This is a document comment
 testing 123
 {
   testing 234
 }",
         &[
@@ -269,59 +265,17 @@ fn span_join() {
         joined1.unwrap().source_file(),
         source1[0].span().source_file()
     );
 }
 
 #[test]
 fn no_panic() {
     let s = str::from_utf8(b"b\'\xc2\x86  \x00\x00\x00^\"").unwrap();
-    assert!(s.parse::<proc_macro2::TokenStream>().is_err());
-}
-
-#[test]
-fn tricky_doc_comment() {
-    let stream = "/**/".parse::<proc_macro2::TokenStream>().unwrap();
-    let tokens = stream.into_iter().collect::<Vec<_>>();
-    assert!(tokens.is_empty(), "not empty -- {:?}", tokens);
-
-    let stream = "/// doc".parse::<proc_macro2::TokenStream>().unwrap();
-    let tokens = stream.into_iter().collect::<Vec<_>>();
-    assert!(tokens.len() == 2, "not length 2 -- {:?}", tokens);
-    match tokens[0] {
-        proc_macro2::TokenTree::Punct(ref tt) => assert_eq!(tt.as_char(), '#'),
-        _ => panic!("wrong token {:?}", tokens[0]),
-    }
-    let mut tokens = match tokens[1] {
-        proc_macro2::TokenTree::Group(ref tt) => {
-            assert_eq!(tt.delimiter(), proc_macro2::Delimiter::Bracket);
-            tt.stream().into_iter()
-        }
-        _ => panic!("wrong token {:?}", tokens[0]),
-    };
-
-    match tokens.next().unwrap() {
-        proc_macro2::TokenTree::Ident(ref tt) => assert_eq!(tt.to_string(), "doc"),
-        t => panic!("wrong token {:?}", t),
-    }
-    match tokens.next().unwrap() {
-        proc_macro2::TokenTree::Punct(ref tt) => assert_eq!(tt.as_char(), '='),
-        t => panic!("wrong token {:?}", t),
-    }
-    match tokens.next().unwrap() {
-        proc_macro2::TokenTree::Literal(ref tt) => {
-            assert_eq!(tt.to_string(), "\" doc\"");
-        }
-        t => panic!("wrong token {:?}", t),
-    }
-    assert!(tokens.next().is_none());
-
-    let stream = "//! doc".parse::<proc_macro2::TokenStream>().unwrap();
-    let tokens = stream.into_iter().collect::<Vec<_>>();
-    assert!(tokens.len() == 3, "not length 3 -- {:?}", tokens);
+    assert!(s.parse::<TokenStream>().is_err());
 }
 
 #[test]
 fn op_before_comment() {
     let mut tts = TokenStream::from_str("~// comment").unwrap().into_iter();
     match tts.next().unwrap() {
         TokenTree::Punct(tt) => {
             assert_eq!(tt.as_char(), '~');
@@ -340,30 +294,30 @@ fn raw_identifier() {
     }
     assert!(tts.next().is_none());
 }
 
 #[test]
 fn test_debug_ident() {
     let ident = Ident::new("proc_macro", Span::call_site());
 
-    #[cfg(not(procmacro2_semver_exempt))]
+    #[cfg(not(span_locations))]
     let expected = "Ident(proc_macro)";
 
-    #[cfg(procmacro2_semver_exempt)]
-    let expected = "Ident { sym: proc_macro, span: bytes(0..0) }";
+    #[cfg(span_locations)]
+    let expected = "Ident { sym: proc_macro }";
 
     assert_eq!(expected, format!("{:?}", ident));
 }
 
 #[test]
 fn test_debug_tokenstream() {
     let tts = TokenStream::from_str("[a + 1]").unwrap();
 
-    #[cfg(not(procmacro2_semver_exempt))]
+    #[cfg(not(span_locations))]
     let expected = "\
 TokenStream [
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 sym: a,
             },
@@ -374,17 +328,17 @@ TokenStream [
             Literal {
                 lit: 1,
             },
         ],
     },
 ]\
     ";
 
-    #[cfg(not(procmacro2_semver_exempt))]
+    #[cfg(not(span_locations))]
     let expected_before_trailing_commas = "\
 TokenStream [
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 sym: a
             },
@@ -395,17 +349,17 @@ TokenStream [
             Literal {
                 lit: 1
             }
         ]
     }
 ]\
     ";
 
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     let expected = "\
 TokenStream [
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 sym: a,
                 span: bytes(2..3),
@@ -420,17 +374,17 @@ TokenStream [
                 span: bytes(6..7),
             },
         ],
         span: bytes(1..8),
     },
 ]\
     ";
 
-    #[cfg(procmacro2_semver_exempt)]
+    #[cfg(span_locations)]
     let expected_before_trailing_commas = "\
 TokenStream [
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 sym: a,
                 span: bytes(2..3)
@@ -459,8 +413,85 @@ TokenStream [
 }
 
 #[test]
 fn default_tokenstream_is_empty() {
     let default_token_stream: TokenStream = Default::default();
 
     assert!(default_token_stream.is_empty());
 }
+
+#[test]
+fn tuple_indexing() {
+    // This behavior may change depending on https://github.com/rust-lang/rust/pull/71322
+    let mut tokens = "tuple.0.0".parse::<TokenStream>().unwrap().into_iter();
+    assert_eq!("tuple", tokens.next().unwrap().to_string());
+    assert_eq!(".", tokens.next().unwrap().to_string());
+    assert_eq!("0.0", tokens.next().unwrap().to_string());
+    assert!(tokens.next().is_none());
+}
+
+#[cfg(span_locations)]
+#[test]
+fn non_ascii_tokens() {
+    check_spans("// abc", &[]);
+    check_spans("// ábc", &[]);
+    check_spans("// abc x", &[]);
+    check_spans("// ábc x", &[]);
+    check_spans("/* abc */ x", &[(1, 10, 1, 11)]);
+    check_spans("/* ábc */ x", &[(1, 10, 1, 11)]);
+    check_spans("/* ab\nc */ x", &[(2, 5, 2, 6)]);
+    check_spans("/* áb\nc */ x", &[(2, 5, 2, 6)]);
+    check_spans("/*** abc */ x", &[(1, 12, 1, 13)]);
+    check_spans("/*** ábc */ x", &[(1, 12, 1, 13)]);
+    check_spans(r#""abc""#, &[(1, 0, 1, 5)]);
+    check_spans(r#""ábc""#, &[(1, 0, 1, 5)]);
+    check_spans(r###"r#"abc"#"###, &[(1, 0, 1, 8)]);
+    check_spans(r###"r#"ábc"#"###, &[(1, 0, 1, 8)]);
+    check_spans("r#\"a\nc\"#", &[(1, 0, 2, 3)]);
+    check_spans("r#\"á\nc\"#", &[(1, 0, 2, 3)]);
+    check_spans("'a'", &[(1, 0, 1, 3)]);
+    check_spans("'á'", &[(1, 0, 1, 3)]);
+    check_spans("//! abc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
+    check_spans("//! ábc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
+    check_spans("//! abc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
+    check_spans("//! ábc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]);
+    check_spans("/*! abc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]);
+    check_spans("/*! ábc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]);
+    check_spans("/*! a\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]);
+    check_spans("/*! á\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]);
+    check_spans("abc", &[(1, 0, 1, 3)]);
+    check_spans("ábc", &[(1, 0, 1, 3)]);
+    check_spans("ábć", &[(1, 0, 1, 3)]);
+    check_spans("abc// foo", &[(1, 0, 1, 3)]);
+    check_spans("ábc// foo", &[(1, 0, 1, 3)]);
+    check_spans("ábć// foo", &[(1, 0, 1, 3)]);
+    check_spans("b\"a\\\n c\"", &[(1, 0, 2, 3)]);
+    check_spans("b\"a\\\n\u{00a0}c\"", &[(1, 0, 2, 3)]);
+}
+
+#[cfg(span_locations)]
+fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) {
+    let ts = p.parse::<TokenStream>().unwrap();
+    check_spans_internal(ts, &mut lines);
+    assert!(lines.is_empty(), "leftover ranges: {:?}", lines);
+}
+
+#[cfg(span_locations)]
+fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) {
+    for i in ts {
+        if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() {
+            *lines = rest;
+
+            let start = i.span().start();
+            assert_eq!(start.line, sline, "sline did not match for {}", i);
+            assert_eq!(start.column, scol, "scol did not match for {}", i);
+
+            let end = i.span().end();
+            assert_eq!(end.line, eline, "eline did not match for {}", i);
+            assert_eq!(end.column, ecol, "ecol did not match for {}", i);
+
+            if let TokenTree::Group(g) = i {
+                check_spans_internal(g.stream().clone(), lines);
+            }
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/third_party/rust/proc-macro2/tests/test_fmt.rs
@@ -0,0 +1,26 @@
+use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
+use std::iter::{self, FromIterator};
+
+#[test]
+fn test_fmt_group() {
+    let ident = Ident::new("x", Span::call_site());
+    let inner = TokenStream::from_iter(iter::once(TokenTree::Ident(ident)));
+    let parens_empty = Group::new(Delimiter::Parenthesis, TokenStream::new());
+    let parens_nonempty = Group::new(Delimiter::Parenthesis, inner.clone());
+    let brackets_empty = Group::new(Delimiter::Bracket, TokenStream::new());
+    let brackets_nonempty = Group::new(Delimiter::Bracket, inner.clone());
+    let braces_empty = Group::new(Delimiter::Brace, TokenStream::new());
+    let braces_nonempty = Group::new(Delimiter::Brace, inner.clone());
+    let none_empty = Group::new(Delimiter::None, TokenStream::new());
+    let none_nonempty = Group::new(Delimiter::None, inner.clone());
+
+    // Matches libproc_macro.
+    assert_eq!("()", parens_empty.to_string());
+    assert_eq!("(x)", parens_nonempty.to_string());
+    assert_eq!("[]", brackets_empty.to_string());
+    assert_eq!("[x]", brackets_nonempty.to_string());
+    assert_eq!("{ }", braces_empty.to_string());
+    assert_eq!("{ x }", braces_nonempty.to_string());
+    assert_eq!("", none_empty.to_string());
+    assert_eq!("x", none_nonempty.to_string());
+}
--- a/third_party/rust/syn/.cargo-checksum.json
+++ b/third_party/rust/syn/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{"Cargo.toml":"484d29864d333a361652fa4e24e1dcfab9efa47705ffd8c106d802eb03b78da7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"ca605417b6db8c995458f8407afaad6c177aedcc2274004283600f5638fa1b0c","benches/file.rs":"b45211cc4a0296a77aac2b4de16dbc6b5cb66adfb5afac00a77bccea87f43968","benches/rust.rs":"9cc0f62e944f1583d05c43a395a1556731501cf5976ef67a081f4f6387f883ba","build.rs":"7423ab199728d55c7d64c44b7c6729cfd93bd8273366a77707353003e27565d7","src/attr.rs":"cf81add298f0e75c35a9980a59bc3c2fd3fe933635830d1591374eeb2487c225","src/await.rs":"18f0b2ecb319991f891e300011424985e3cf33d166ea9f29f22d575fc8c83a76","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"2a432c11a3da67a21d46c2272bf9ce60a0bb20893b5750027bbd8ca3e843ab35","src/custom_keyword.rs":"589e46ec1be9a04d6de12c0b8cadf87cc1c05606ed46ddea62e9869cbca4a191","src/custom_punctuation.rs":"2ba2e294e15a0fce7ede3686c42b2891797079a724dd1193b66e7d305624c891","src/data.rs":"cc9b250d084e444782d3ff5e63c1ba387cbde8f7f2e977eab9846d920b4b8c3f","src/derive.rs":"c18878f14be5d5ab11fd7dda2d2ff1ff75c9662daf11eed033de62e4d0670a89","src/discouraged.rs":"50e10915695c4d14f64a78e20ecbef90a2cd53a7c26ee3426a2524a8ee5c9cbf","src/error.rs":"2c17a402f83ed5ae4ad96e753216771bef620235c2ff1ccc23f4bbafc7266fe1","src/export.rs":"dcae67456278c0339acfbcbb4737b8d37cfba5a150ae789f31f4be79abf7e726","src/expr.rs":"871d8eeb43cef02ef88de3bea7477b79b4eabc096a0899dde0e5750edf482f49","src/ext.rs":"b97ed549490b9248b5b5df31b3d5b08ba8791e23e6c5d3a1157a0363eb683ff3","src/file.rs":"3cc2bf5c709238d515a557f721f231c8c725b196400de051f945b549299d38a7","src/gen/fold.rs":"10b3ae33d0ce410d6bbe8b93be9d5f9e856c7dc8212133cc46b703f97d548190","src/gen/visit.rs":"e0f5798552d186024696b7bfc7219d4ff53b0e45f735a83e77cbb6b6578c5fa4","src/gen/visit_mut.rs":"9f7dda83907969971dba84d545aaa563b0728e54db97ffab5050fdf43a79c731","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"d845d7a828863123a5187fd0fe59c9dae3636f63bad302bd035792eed3dcb1ba","src/group.rs":"119b62d8481b4b1c327639bed40e114bf1969765250b68186628247fd4144b3b","src/ident.rs":"503156ce51a7ef0420892e8dbf2ecf8fe51f42a84d52cc2c05654e1a83020cbf","src/item.rs":"213f2f58c65ee1aa222f111bc9b1be681f8fb069caed04ca56586839979318d0","src/keyword.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/lib.rs":"24778e9f15e8025e75aca114c712716ada586b471adb3b3b69278f4d39b8a21b","src/lifetime.rs":"905359708f772ec858954badde69ee016d29e6eeba1dd205b268445b1aff6f3a","src/lit.rs":"5bb0bddb94cbd256e50e92dc091a0baa09f1be40a77058b897507f3b17191e5d","src/lookahead.rs":"5cce8b4cb345a85c24a452ea6d78eadb76f01ca0a789cbf5ce35108334904173","src/mac.rs":"6b468244cc07e3f2f10419f833d9e2ed23edbcd6dc34cf21c5947633699db964","src/macros.rs":"0d8c3bab47539aa2d00bec64e92c901ea2c9c0af74c868051c0905b82650f970","src/op.rs":"93cd44770bb110deadf807a01d9a666efe644b6e3010f4b51cae77ee7438cfbb","src/parse.rs":"5017123c249ebc65866af113a0ad671814b9873f47568180e6539a305eb0317d","src/parse_macro_input.rs":"f799aadb7216c2d333b579f48ed2fedfe07b5e96f004b25b569649ffbaa958d2","src/parse_quote.rs":"81575bf60b18b0d8624d7025a5bcc8dcd6633ad70c454dee2a06e4c391700b6c","src/pat.rs":"db0f2263b9813de1f4e3e3e0396fe0080b1e11c8090c6b4fb6fca3cfbe22bc96","src/path.rs":"32e685ac7fd2d4b9989802de8f326a8d47fa710f86ec3e45fd9d3ff8fdfe97ef","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"384e7b317b26f24118eb4b0c39e949ee9f4f3e700a4c80e462342c83b2cc3282","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"adddb6acae14a0fa340df302b932c31e34b259706ce56fd82ab597ec424500e1","src/stmt.rs":"fbccf2b4da7980fe6ea8d99457d291577c0f225b370c1dd97da41abf2a18fcf7","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"761d8d1793560eb2b631c36ddfdbb14ac65178405f095453aa0e75e8816bdbb9","src/tt.rs":"1e32ae216d14d895ff621bf32bc611f138aa00108b0090be2cbaa0affebe8e2a","src/ty.rs":"ce052e0079b65b66bea4e9502d2ff2c90ad4b867904bf7eb892eb60aa3ef219a","tests/clone.sh":"961243d42540d9992090efbbd5478b7aa395671db64a6c28cdadb6edc610ebdf","tests/common/eq.rs":"a42d339808fd32dd4bfd440c254add8c56d5e2cde3a6bf0c88621b618ce5eaa7","tests/common/mod.rs":"20a3300016351fa210a193fbb0db059ef5125fa7909585ded64790004d4977ed","tests/common/parse.rs":"17ba6d1e74aaa3f8096c6d379d803221f12d95cca69927be047d6ddf8367647f","tests/debug/gen.rs":"57bd5cf585e0b86ad00f29f09ff3db3390c4a756d503514a9b28407500dcea3c","tests/debug/mod.rs":"462d6fe34ee75c3ca1207d4db2ff3bdee5b430b9f9ca632e5671d1588d3f76b3","tests/features/error.rs":"e0581a2869cbd237c2bc18a0a85272296e1577bb5f7317a67fa85e28e04eea6f","tests/features/mod.rs":"66a2605ec54ede29208da350f2bed536dfa763b58408d64d3fca3b13de64b64f","tests/macros/mod.rs":"3f2d758c0ba76b93f54b0c1fc22ad50edff8ef42629ba4d47ac7d7f823da8359","tests/repo/mod.rs":"e851a68972c9194a9a8d7b68538b16ed79ae81cba55e1a2ce210d1b759fb1a21","tests/test_asyncness.rs":"b6c46118b036e6807d24eb0e1779244b4fca23dac0d8031e9843b3edec484ce8","tests/test_attribute.rs":"2d8f18a98c989d3f7adaaeb1aeebd4f8413365ace63feecb37cb3f9db9db4d8f","tests/test_derive_input.rs":"477d80f914c54b526f8ff229788dc0e7798d118f6dcfa348f4c99755edb347b9","tests/test_expr.rs":"f35ca80566849a36e6ba6403d9663519eff37e4224360c468fedff8b561a643e","tests/test_generics.rs":"83a5dc07f5c5701c12625399262f7120b66f01a742523f3eda28da2cf2c87eb3","tests/test_grouping.rs":"aadd75215addd9e5a8fa2f9472117d4cb80f1e8b84e07f4c0845675c9014164f","tests/test_ident.rs":"236c239dd66f543f084f44ff747d7bc3962cf11a019a279777fe972f6e17aa4c","tests/test_iterators.rs":"718938da14778dcba06324d36a99d9317c9d45d81a34c6a44c47e1fa38085e9f","tests/test_lit.rs":"7dff2661a5ac586d6ed2fe27501cb8ff62f4cf3f6c91f596bff6057c67ad7857","tests/test_meta.rs":"8444dee084882243b107dfc8a6aac27f9382f9774162d1ac8ed8ec30d60c048e","tests/test_parse_buffer.rs":"b244bb4bc41ff06d21f239e60a3d663fdec5aa4af33f2a354afef36d34f0aefc","tests/test_pat.rs":"41776b878efae9b8e340f21ffe6296e921cf309f618482efd98609c33e32c28b","tests/test_precedence.rs":"71f3ea52cda8b40166bb7416fb98774e6a653542497b521f8e183e283dcf579d","tests/test_round_trip.rs":"e0de37f45fa223b488d25a41beab185eb92abb7bf765a9f13fe5d870ff31f5f1","tests/test_should_parse.rs":"4da4e25ee2baa7e75135c375042a7f958de136c5698dab03f99ff7a774dcd463","tests/test_size.rs":"970150b9d49ef91ab4c8f8c6a59b83f9a68a02acb779f0280733a5efaec6487a","tests/test_token_trees.rs":"a07ea657bf03b9c667c821b2db2af49b176ca737e3e01217a73cca78b7f11380","tests/zzz_stable.rs":"961d4940a926db4ca523d834b060c62de988e6a8e01c9f5efaa7bb4c86745b47"},"package":"66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"}
\ No newline at end of file
+{"files":{"Cargo.toml":"28ddb678a5ccac4423435384c8b7116f804e896eabc5aae9d5c2bc666aaebbb4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"03f3b53cf858536a0883aa5b5882ee61dcd0f1e71c0930c9106fcfa1d6aad2df","benches/file.rs":"b4724fc7c0f48b8f488e2632a1064f6c0bf16ded3969680fc3f4a2369536269b","benches/rust.rs":"ea6291ef2d2a83d94a3312fe179d48259f8ec0b04c961993ddd181d0a4ab740e","build.rs":"aeca2312f05aec658eaa66980a0ef3d578837db107a55702b39419ea0422eb4a","src/attr.rs":"7d79482634d6544eb4a4825405407b53660d0f5f8b929f7e1671e005b9d92038","src/await.rs":"18f0b2ecb319991f891e300011424985e3cf33d166ea9f29f22d575fc8c83a76","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"cf2a4b3bdc247b80c85ff5625a1dfb7a5f517fd835f6e1518a7b924990e4c293","src/custom_keyword.rs":"9627467063e41776315a6a14b2aaea3875592d8e0ebd2dc6df1fc2f12c06f146","src/custom_punctuation.rs":"b00e7bee96eb473507527e39db65e74e71592dc06421d2cfe45ed899c17d4847","src/data.rs":"7aec9a745cd53ec95688afa353f6efb9576e7fc0143757b51d28bc3d900b1d2a","src/derive.rs":"fa71866df6e383673dd3329f455a9f953585b83f9739050be3bf1f8c6d526b96","src/discouraged.rs":"a1f3d85e20dedf50b1b7b4571d970a3a6e9b2de4afde7dd0c986fe240df2ba46","src/error.rs":"c3005b50e3132026250c5356d0d391bf96db8087f0f5f744de98e360d8a20a3e","src/export.rs":"dcae67456278c0339acfbcbb4737b8d37cfba5a150ae789f31f4be79abf7e726","src/expr.rs":"54455fd20041996653ca5379b03cdf3c2fc1b3dd2e1149b5bc6b1dd492545d55","src/ext.rs":"870086d9021e6a6fcefa2f00cd91b55c4b74dcee8f0f6a07e76d96fb44707d61","src/file.rs":"75167ebc77e7870122078eabde1b872c337142d4b0962c20cedffcaaa2a5b7c6","src/gen/clone.rs":"0845c1bf8624c3f235cd247b4eb748e7e16b4c240097cb0ff16751f688c079ae","src/gen/debug.rs":"d24fe37f4ce1dd74f2dc54136e893782d3c4d0908323c036c97599551a56960c","src/gen/eq.rs":"1e6ef09b17ca7f36861ef23ce2a6991b231ed5f087f046469b5f23da40f5b419","src/gen/fold.rs":"3f59e59ed8ad2ab5dd347bfbe41bbc785c2aabd8ae902087a584a6daed597182","src/gen/hash.rs":"e5b2a52587173076777233a9e57e2b3c8e0dd6d6f41d16fa7c9fde68b05c2bfc","src/gen/visit.rs":"23008c170d4dd3975232876a0a654921d9b6af57372cb9fcc133ca740588d666","src/gen/visit_mut.rs":"42886c3ee02ded72d9c3eec006e20431eaee0c6b90ddefc1a36ec7bf50c6a24a","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"d1c175284ca21e777ef0414c28383929b170ccb00aaf7a929eb18d3b05e18da8","src/group.rs":"119b62d8481b4b1c327639bed40e114bf1969765250b68186628247fd4144b3b","src/ident.rs":"503156ce51a7ef0420892e8dbf2ecf8fe51f42a84d52cc2c05654e1a83020cbf","src/item.rs":"c9ad9881e8cda8ee3f157f0c7602fc53d08a7e3288b9afc388c393689eac5aea","src/lib.rs":"558ad13779233b27bebc4b2fc8025eb1c7e57b32130dc1dd911391e27b427500","src/lifetime.rs":"f390fe06692fc51fbf3eb490bb9f795da70e4452f51c5b0df3bbaa899084ddf1","src/lit.rs":"9fab84e38756b092fbb055dcdf01e31d42d916c49e3eaae8c9019043b0ee4301","src/lookahead.rs":"5cce8b4cb345a85c24a452ea6d78eadb76f01ca0a789cbf5ce35108334904173","src/mac.rs":"e5cecea397fd01a44958162781d8d94343fe2a1b9b9754a5666c3d2ab4d7ef64","src/macros.rs":"2ce05b553f14da4ee550bb681cb0733b7186ad94719cd36f96d53e15fd02cf2b","src/op.rs":"449514e146deab0ab020bc6f764544c294dbc780941c9802bf60cf1b2839d550","src/parse.rs":"bde888c98ee259f2a73489a693515ed4875432b0d79486ac83aea19f441992a3","src/parse_macro_input.rs":"653a020f023cac0eccbc1fcc34aa7bf80567b43e5475deab4ad3e487a5363201","src/parse_quote.rs":"642f21e5fa54df4b7c373fb158289ee1005d49e1a49b1d194df5438faee71c46","src/pat.rs":"1473b258162cc822f1ee0c0869f521053ed345a140c39ed83b9b4dfb6f9f2aca","src/path.rs":"f119f0c2af12fabd360eac9a2312e0f6e6c28c633c9671bde6ef0bece7c5ba3c","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"212f5a601d6c2eb8b8fa679be1167b455b595bee964d2775b0101ebb16c3eaa5","src/reserved.rs":"3625eb2a64589a4992ab79a1674e9679f465bea613ab139a671df5337e88cee6","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"7d77714d585e6f42397091ffb3a799fd7b20c05c5442c737683c429ea7d409a5","src/stmt.rs":"3917fbc897f80efe838267833c55650ff8d636cb49a6d1084e28eff65d0e3ccd","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"a1ca6298bf6592cb80cbab1db4eac2fa4e3fa56729bb807bfb0f08ab0f229ca5","src/tt.rs":"1cc9e200624288322f800f32e3d6e2e53da946467bb312dd40a52c02cdcc4730","src/ty.rs":"cb167cbb16240c59a31b44adec175172caaf75ffef9a0bb168584b51bf105795","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"4b190a3833bdfd20a4cb1e3dff25a698751dec71d6f30249cf09426e061a4fb1","tests/common/mod.rs":"25ef6d7daa09bad3198a0e9e91b2812425f92db7c585c1e34a03a84d7362ccd8","tests/common/parse.rs":"8b7ba32f4988c30758c108536c4877dc5a039a237bf9b0687220ef2295797bbd","tests/debug/gen.rs":"d6e2abf2a7bb58a7895a60c2f094a98a4f85c9189d02011d0dcef6ef053f26e3","tests/debug/mod.rs":"868763d0ef1609a3ad5e05e9f1bfa0f813e91e7e9a36653414a188bb2fdaa425","tests/macros/mod.rs":"c0eafa4e3845fc08f6efe6021bac37822c0ac325eb7b51194a5f35236f648d92","tests/repo/mod.rs":"9e316b88d57ae213e81950c35e45443078ec90e702798353bc3528cb8a2810b6","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"610444351e3bf99366976bbf1da109c334a70ac9500caef366bcf9b68819829f","tests/test_expr.rs":"0ee83f6f6de950018c043efcc3e85776b4227dae3068309998a8d9709f2fc66c","tests/test_generics.rs":"9d713f90a79d6145efc89fb6f946029ca03486c632219950889da39940152ba0","tests/test_grouping.rs":"46c27baec4daaaf1e891892f0b0515ea8a44619071c7d0cc9192580916f1569f","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"461ed0c8648afffcea3217f52c9a88298182b4d39d73a11803b1281d99c98c25","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"2a46c5f2f2ad1dcbb7e9b0cd11b55861c5ff818c2c4c51351d07e2daa7c74674","tests/test_meta.rs":"1fc98af3279cadc3d8db3c7e8d4d7f9e9dbd4d17548cf6a2f6f4536ed65367f6","tests/test_parse_buffer.rs":"8bbe2d24ca8a3788f72c6908fc96c26d546f11c69687bf8d72727f851d5e2d27","tests/test_parse_stream.rs":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"2cb331fe404496d51e7cc7e283ae13c519a2265ca82e1c88e113296f860c2cba","tests/test_path.rs":"fcd5591e639fc787acc9763d828a811c8114525c9341282eefda8f331e082a51","tests/test_precedence.rs":"8d03656741b01e577d7501ce24332d1a4febec3e31a043e47c61062b8c527ed2","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"ba01bf4ec04cd2d6f9e4800c343563925ae960c5f16752dc0797fda4451b6cc2","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"5fae772bab66809d6708232f35cfb4a287882486763b0f763feec2ad79fbb68b","tests/test_stmt.rs":"17e4355843ee2982b51faba2721a18966f8c2b9422e16b052a123b8ee8b80752","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"5b7c0bfc4963d41920dd0b39fdea419e34f00409ba86ad4211d6c3c7e8bbe1c0","tests/test_visibility.rs":"3f958e2b3b5908005e756a80eea326a91eac97cc4ab60599bebde8d4b942d65c","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"}
\ No newline at end of file
--- a/third_party/rust/syn/Cargo.toml
+++ b/third_party/rust/syn/Cargo.toml
@@ -8,79 +8,90 @@
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
 # editing this file be aware that the upstream Cargo.toml
 # will likely look very different (and much more reasonable)
 
 [package]
 edition = "2018"
 name = "syn"
-version = "1.0.5"
+version = "1.0.40"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 include = ["/benches/**", "/build.rs", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**"]
 description = "Parser for Rust source code"
 documentation = "https://docs.rs/syn"
 readme = "README.md"
 categories = ["development-tools::procedural-macro-helpers"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/dtolnay/syn"
 [package.metadata.docs.rs]
 all-features = true
+targets = ["x86_64-unknown-linux-gnu"]
 
 [package.metadata.playground]
-all-features = true
-
-[lib]
-name = "syn"
+features = ["full", "visit", "visit-mut", "fold", "extra-traits"]
 
 [[bench]]
 name = "rust"
 harness = false
 required-features = ["full", "parsing"]
-edition = "2018"
 
 [[bench]]
 name = "file"
 required-features = ["full", "parsing"]
-edition = "2018"
 [dependencies.proc-macro2]
-version = "1.0"
+version = "1.0.13"
 default-features = false
 
 [dependencies.quote]
 version = "1.0"
 optional = true
 default-features = false
 
 [dependencies.unicode-xid]
 version = "0.2"
+[dev-dependencies.anyhow]
+version = "1.0"
+
+[dev-dependencies.flate2]
+version = "1.0"
+
 [dev-dependencies.insta]
-version = "0.9"
+version = "0.16"
 
 [dev-dependencies.rayon]
 version = "1.0"
 
 [dev-dependencies.ref-cast]
-version = "0.2"
+version = "1.0"
 
 [dev-dependencies.regex]
 version = "1.0"
 
+[dev-dependencies.reqwest]
+version = "0.10"
+features = ["blocking"]
+
+[dev-dependencies.syn-test-suite]
+version = "0"
+
+[dev-dependencies.tar]
+version = "0.4"
+
 [dev-dependencies.termcolor]
 version = "1.0"
 
 [dev-dependencies.walkdir]
 version = "2.1"
 
 [features]
 clone-impls = []
 default = ["derive", "parsing", "printing", "clone-impls", "proc-macro"]
 derive = []
 extra-traits = []
 fold = []
 full = []
 parsing = []
 printing = ["quote"]
 proc-macro = ["proc-macro2/proc-macro", "quote/proc-macro"]
+test = ["syn-test-suite/all-features"]
 visit = []
 visit-mut = []
-[badges.travis-ci]
-repository = "dtolnay/syn"
--- a/third_party/rust/syn/README.md
+++ b/third_party/rust/syn/README.md
@@ -1,15 +1,15 @@
 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/1.0/syn/)
-[![Rustc Version 1.31+](https://img.shields.io/badge/rustc-1.31+-lightgray.svg)](https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html)
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/syn-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/syn)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/syn.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/syn)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-syn-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/syn)
+[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/syn/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/syn/actions?query=branch%3Amaster)
 
 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 use in Rust procedural macros, but
 contains some APIs that may be useful more generally.
 
 - **Data structures** — Syn provides a complete syntax tree that can represent
@@ -41,20 +41,16 @@ contains some APIs that may be useful mo
 
 [`syn::File`]: https://docs.rs/syn/1.0/syn/struct.File.html
 [`syn::Item`]: https://docs.rs/syn/1.0/syn/enum.Item.html
 [`syn::Expr`]: https://docs.rs/syn/1.0/syn/enum.Expr.html
 [`syn::Type`]: https://docs.rs/syn/1.0/syn/enum.Type.html
 [`syn::DeriveInput`]: https://docs.rs/syn/1.0/syn/struct.DeriveInput.html
 [parser functions]: https://docs.rs/syn/1.0/syn/parse/index.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 rustc 1.31 and up.*
 
 [*Release notes*](https://github.com/dtolnay/syn/releases)
 
 <br>
 
 ## Resources
 
@@ -83,18 +79,16 @@ tokens back to the compiler to compile i
 syn = "1.0"
 quote = "1.0"
 
 [lib]
 proc-macro = true
 ```
 
 ```rust
-extern crate proc_macro;
-
 use proc_macro::TokenStream;
 use quote::quote;
 use syn::{parse_macro_input, DeriveInput};
 
 #[proc_macro_derive(MyMacro)]
 pub fn my_macro(input: TokenStream) -> TokenStream {
     // Parse the input tokens into a syntax tree
     let input = parse_macro_input!(input as DeriveInput);
@@ -266,17 +260,17 @@ incompatible ecosystems for proc macros 
 
 In general all of your code should be written against proc-macro2 rather than
 proc-macro. The one exception is in the signatures of procedural macro entry
 points, which are required by the language to use `proc_macro::TokenStream`.
 
 The proc-macro2 crate will automatically detect and use the compiler's data
 structures when a procedural macro is active.
 
-[proc-macro2]: https://docs.rs/proc-macro2/1.0.0/proc_macro2/
+[proc-macro2]: https://docs.rs/proc-macro2/1.0/proc_macro2/
 
 <br>
 
 #### License
 
 <sup>
 Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
 2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
--- a/third_party/rust/syn/benches/file.rs
+++ b/third_party/rust/syn/benches/file.rs
@@ -1,14 +1,21 @@
 // $ cargo bench --features full --bench file
 
 #![feature(rustc_private, test)]
+#![recursion_limit = "1024"]
 
 extern crate test;
 
+#[macro_use]
+#[path = "../tests/macros/mod.rs"]
+mod macros;
+
+#[path = "../tests/common/mod.rs"]
+mod common;
 #[path = "../tests/repo/mod.rs"]
 pub mod repo;
 
 use proc_macro2::TokenStream;
 use std::fs;
 use std::str::FromStr;
 use test::Bencher;
 
--- a/third_party/rust/syn/benches/rust.rs
+++ b/third_party/rust/syn/benches/rust.rs
@@ -1,15 +1,22 @@
 // $ cargo bench --features full --bench rust
 //
 // Syn only, useful for profiling:
 // $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full --bench rust
 
 #![cfg_attr(not(syn_only), feature(rustc_private))]
+#![recursion_limit = "1024"]
 
+#[macro_use]
+#[path = "../tests/macros/mod.rs"]
+mod macros;
+
+#[path = "../tests/common/mod.rs"]
+mod common;
 #[path = "../tests/repo/mod.rs"]
 mod repo;
 
 use std::fs;
 use std::time::{Duration, Instant};
 
 #[cfg(not(syn_only))]
 mod tokenstream_parse {
@@ -23,41 +30,45 @@ mod tokenstream_parse {
 
 mod syn_parse {
     pub fn bench(content: &str) -> Result<(), ()> {
         syn::parse_file(content).map(drop).map_err(drop)
     }
 }
 
 #[cfg(not(syn_only))]
-mod libsyntax_parse {
+mod librustc_parse {
     extern crate rustc_data_structures;
-    extern crate syntax;
-    extern crate syntax_pos;
+    extern crate rustc_errors;
+    extern crate rustc_parse;
+    extern crate rustc_session;
+    extern crate rustc_span;
 
     use rustc_data_structures::sync::Lrc;
-    use syntax::edition::Edition;
-    use syntax::errors::{emitter::Emitter, DiagnosticBuilder, Handler};
-    use syntax::parse::ParseSess;
-    use syntax::source_map::{FilePathMapping, SourceMap};
-    use syntax_pos::FileName;
+    use rustc_errors::{emitter::Emitter, Diagnostic, Handler};
+    use rustc_session::parse::ParseSess;
+    use rustc_span::source_map::{FilePathMapping, SourceMap};
+    use rustc_span::{edition::Edition, FileName};
 
     pub fn bench(content: &str) -> Result<(), ()> {
         struct SilentEmitter;
 
         impl Emitter for SilentEmitter {
-            fn emit_diagnostic(&mut self, _db: &DiagnosticBuilder) {}
+            fn emit_diagnostic(&mut self, _diag: &Diagnostic) {}
+            fn source_map(&self) -> Option<&Lrc<SourceMap>> {
+                None
+            }
         }
 
-        syntax::with_globals(Edition::Edition2018, || {
+        rustc_span::with_session_globals(Edition::Edition2018, || {
             let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
             let emitter = Box::new(SilentEmitter);
             let handler = Handler::with_emitter(false, None, emitter);
             let sess = ParseSess::with_span_handler(handler, cm);
-            if let Err(mut diagnostic) = syntax::parse::parse_crate_from_source_str(
+            if let Err(mut diagnostic) = rustc_parse::parse_crate_from_source_str(
                 FileName::Custom("bench".to_owned()),
                 content.to_owned(),
                 &sess,
             ) {
                 diagnostic.cancel();
                 return Err(());
             };
             Ok(())
@@ -99,21 +110,21 @@ fn exec(mut codepath: impl FnMut(&str) -
     assert_eq!(success, total);
     begin.elapsed()
 }
 
 fn main() {
     repo::clone_rust();
 
     macro_rules! testcases {
-        ($($(#[$cfg:meta])* $name:path,)*) => {
+        ($($(#[$cfg:meta])* $name:ident,)*) => {
             vec![
                 $(
                     $(#[$cfg])*
-                    (stringify!($name), $name as fn(&str) -> Result<(), ()>),
+                    (stringify!($name), $name::bench as fn(&str) -> Result<(), ()>),
                 )*
             ]
         };
     }
 
     #[cfg(not(syn_only))]
     {
         let mut lines = 0;
@@ -123,22 +134,22 @@ fn main() {
             files += 1;
             Ok(())
         });
         eprintln!("\n{} lines in {} files", lines, files);
     }
 
     for (name, f) in testcases!(
         #[cfg(not(syn_only))]
-        read_from_disk::bench,
+        read_from_disk,
         #[cfg(not(syn_only))]
-        tokenstream_parse::bench,
-        syn_parse::bench,
+        tokenstream_parse,
+        syn_parse,
         #[cfg(not(syn_only))]
-        libsyntax_parse::bench,
+        librustc_parse,
     ) {
         eprint!("{:20}", format!("{}:", name));
         let elapsed = exec(f);
         eprintln!(
             "elapsed={}.{:03}s",
             elapsed.as_secs(),
             elapsed.subsec_millis(),
         );
--- a/third_party/rust/syn/build.rs
+++ b/third_party/rust/syn/build.rs
@@ -1,11 +1,11 @@
 use std::env;
 use std::process::Command;
-use std::str::{self, FromStr};
+use std::str;
 
 // The rustc-cfg strings below are *not* public API. Please let us know by
 // opening a GitHub issue if your build environment requires some way to enable
 // these cfgs other than by executing our build script.
 fn main() {
     let compiler = match rustc_version() {
         Some(compiler) => compiler,
         None => return,
@@ -21,43 +21,19 @@ fn main() {
 }
 
 struct Compiler {
     minor: u32,
     nightly: bool,
 }
 
 fn rustc_version() -> Option<Compiler> {
-    let rustc = match env::var_os("RUSTC") {
-        Some(rustc) => rustc,
-        None => return None,
-    };
-
-    let output = match Command::new(rustc).arg("--version").output() {
-        Ok(output) => output,
-        Err(_) => return None,
-    };
-
-    let version = match str::from_utf8(&output.stdout) {
-        Ok(version) => version,
-        Err(_) => return None,
-    };
-
+    let rustc = env::var_os("RUSTC")?;
+    let output = Command::new(rustc).arg("--version").output().ok()?;
+    let version = str::from_utf8(&output.stdout).ok()?;
     let mut pieces = version.split('.');
     if pieces.next() != Some("rustc 1") {
         return None;
     }
-
-    let next = match pieces.next() {
-        Some(next) => next,
-        None => return None,
-    };
-
-    let minor = match u32::from_str(next) {
-        Ok(minor) => minor,
-        Err(_) => return None,
-    };
-
-    Some(Compiler {
-        minor: minor,
-        nightly: version.contains("nightly"),
-    })
+    let minor = pieces.next()?.parse().ok()?;
+    let nightly = version.contains("nightly");
+    Some(Compiler { minor, nightly })
 }
--- a/third_party/rust/syn/src/attr.rs
+++ b/third_party/rust/syn/src/attr.rs
@@ -4,25 +4,21 @@ use crate::punctuated::Punctuated;
 use std::iter;
 
 use proc_macro2::TokenStream;
 
 #[cfg(feature = "parsing")]
 use crate::parse::{Parse, ParseBuffer, ParseStream, Parser, Result};
 #[cfg(feature = "parsing")]
 use crate::punctuated::Pair;
-#[cfg(feature = "extra-traits")]
-use crate::tt::TokenStreamHelper;
-#[cfg(feature = "extra-traits")]
-use std::hash::{Hash, Hasher};
 
 ast_struct! {
     /// An attribute like `#[repr(transparent)]`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
     /// feature.*
     ///
     /// <br>
     ///
     /// # Syntax
     ///
     /// Rust has six types of attributes.
     ///
@@ -106,58 +102,69 @@ ast_struct! {
     /// If the attribute you are parsing is expected to conform to the
     /// conventional structured form of attribute, use [`parse_meta()`] to
     /// obtain that structured representation. If the attribute follows some
     /// other grammar of its own, use [`parse_args()`] to parse that into the
     /// expected data structure.
     ///
     /// [`parse_meta()`]: Attribute::parse_meta
     /// [`parse_args()`]: Attribute::parse_args
-    pub struct Attribute #manual_extra_traits {
+    ///
+    /// <p><br></p>
+    ///
+    /// # Doc comments
+    ///
+    /// The compiler transforms doc comments, such as `/// comment` and `/*!
+    /// comment */`, into attributes before macros are expanded. Each comment is
+    /// expanded into an attribute of the form `#[doc = r"comment"]`.
+    ///
+    /// As an example, the following `mod` items are expanded identically:
+    ///
+    /// ```
+    /// # use syn::{ItemMod, parse_quote};
+    /// let doc: ItemMod = parse_quote! {
+    ///     /// Single line doc comments
+    ///     /// We write so many!
+    ///     /**
+    ///      * Multi-line comments...
+    ///      * May span many lines
+    ///      */
+    ///     mod example {
+    ///         //! Of course, they can be inner too
+    ///         /*! And fit in a single line */
+    ///     }
+    /// };
+    /// let attr: ItemMod = parse_quote! {
+    ///     #[doc = r" Single line doc comments"]
+    ///     #[doc = r" We write so many!"]
+    ///     #[doc = r"
+    ///      * Multi-line comments...
+    ///      * May span many lines
+    ///      "]
+    ///     mod example {
+    ///         #![doc = r" Of course, they can be inner too"]
+    ///         #![doc = r" And fit in a single line "]
+    ///     }
+    /// };
+    /// assert_eq!(doc, attr);
+    /// ```
+    pub struct Attribute {
         pub pound_token: Token![#],
         pub style: AttrStyle,
         pub bracket_token: token::Bracket,
         pub path: Path,
         pub tokens: 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.tokens) == TokenStreamHelper(&other.tokens)
-    }
-}
-
-#[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.tokens).hash(state);
-    }
-}
-
 impl Attribute {
     /// Parses the content of the attribute, consisting of the path and tokens,
     /// as a [`Meta`] if possible.
     ///
-    /// *This function is available if Syn is built with the `"parsing"`
+    /// *This function is available only if Syn is built with the `"parsing"`
     /// feature.*
     #[cfg(feature = "parsing")]
     pub fn parse_meta(&self) -> Result<Meta> {
         fn clone_ident_segment(segment: &PathSegment) -> PathSegment {
             PathSegment {
                 ident: segment.ident.clone(),
                 arguments: PathArguments::None,
             }
@@ -194,91 +201,95 @@ impl Attribute {
     ///   parser; and
     /// - the error message has a more useful span when `tokens` is empty.
     ///
     /// ```text
     /// #[my_attr(value < 5)]
     ///           ^^^^^^^^^ what gets parsed
     /// ```
     ///
-    /// *This function is available if Syn is built with the `"parsing"`
+    /// *This function is available only if Syn is built with the `"parsing"`
     /// feature.*
     #[cfg(feature = "parsing")]
     pub fn parse_args<T: Parse>(&self) -> Result<T> {
         self.parse_args_with(T::parse)
     }
 
     /// Parse the arguments to the attribute using the given parser.
     ///
-    /// *This function is available if Syn is built with the `"parsing"`
+    /// *This function is available only if Syn is built with the `"parsing"`
     /// feature.*
     #[cfg(feature = "parsing")]
     pub fn parse_args_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
         let parser = |input: ParseStream| {
             let args = enter_args(self, input)?;
             parse::parse_stream(parser, &args)
         };
         parser.parse2(self.tokens.clone())
     }
 
     /// Parses zero or more outer attributes from the stream.
     ///
-    /// *This function is available if Syn is built with the `"parsing"`
+    /// *This function is available only if Syn is built with the `"parsing"`
     /// feature.*
     #[cfg(feature = "parsing")]
     pub fn parse_outer(input: ParseStream) -> Result<Vec<Self>> {
         let mut attrs = Vec::new();
         while input.peek(Token![#]) {
             attrs.push(input.call(parsing::single_parse_outer)?);
         }
         Ok(attrs)
     }
 
     /// Parses zero or more inner attributes from the stream.
     ///
-    /// *This function is available if Syn is built with the `"parsing"`
+    /// *This function is available only if Syn is built with the `"parsing"`
     /// feature.*
     #[cfg(feature = "parsing")]
     pub fn parse_inner(input: ParseStream) -> Result<Vec<Self>> {
         let mut attrs = Vec::new();
         while input.peek(Token![#]) && input.peek2(Token![!]) {
             attrs.push(input.call(parsing::single_parse_inner)?);
         }
         Ok(attrs)
     }
 }
 
 #[cfg(feature = "parsing")]
-fn error_expected_args(attr: &Attribute) -> Error {
+fn expected_parentheses(attr: &Attribute) -> String {
     let style = match attr.style {
         AttrStyle::Outer => "#",
         AttrStyle::Inner(_) => "#!",
     };
 
     let mut path = String::new();
     for segment in &attr.path.segments {
         if !path.is_empty() || attr.path.leading_colon.is_some() {
             path += "::";
         }
         path += &segment.ident.to_string();
     }
 
-    let msg = format!("expected attribute arguments: {}[{}(...)]", style, path);
-
-    #[cfg(feature = "printing")]
-    return Error::new_spanned(attr, msg);
-
-    #[cfg(not(feature = "printing"))]
-    return Error::new(attr.bracket_token.span, msg);
+    format!("{}[{}(...)]", style, path)
 }
 
 #[cfg(feature = "parsing")]
 fn enter_args<'a>(attr: &Attribute, input: ParseStream<'a>) -> Result<ParseBuffer<'a>> {
     if input.is_empty() {
-        return Err(error_expected_args(attr));
+        let expected = expected_parentheses(attr);
+        let msg = format!("expected attribute arguments in parentheses: {}", expected);
+        return Err(crate::error::new2(
+            attr.pound_token.span,
+            attr.bracket_token.span,
+            msg,
+        ));
+    } else if input.peek(Token![=]) {
+        let expected = expected_parentheses(attr);
+        let msg = format!("expected parentheses: {}", expected);
+        return Err(input.error(msg));
     };
 
     let content;
     if input.peek(token::Paren) {
         parenthesized!(content in input);
     } else if input.peek(token::Bracket) {
         bracketed!(content in input);
     } else if input.peek(token::Brace) {
@@ -293,41 +304,40 @@ fn enter_args<'a>(attr: &Attribute, inpu
         Err(input.error("unexpected token in attribute arguments"))
     }
 }
 
 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"`
+    /// *This type is available only 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"`
+    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
     /// feature.*
     ///
     /// ## Path
     ///
     /// A meta path is like the `test` in `#[test]`.
     ///
     /// ## List
     ///
@@ -355,29 +365,29 @@ ast_enum_of_structs! {
         /// A name-value pair within an attribute, like `feature = "nightly"`.
         NameValue(MetaNameValue),
     }
 }
 
 ast_struct! {
     /// A structured list within an attribute, like `derive(Copy, Clone)`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct MetaList {
         pub path: Path,
         pub paren_token: token::Paren,
         pub nested: Punctuated<NestedMeta, Token![,]>,
     }
 }
 
 ast_struct! {
     /// A name-value pair within an attribute, like `feature = "nightly"`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct MetaNameValue {
         pub path: Path,
         pub eq_token: Token![=],
         pub lit: Lit,
     }
 }
 
@@ -393,17 +403,17 @@ impl Meta {
             Meta::NameValue(meta) => &meta.path,
         }
     }
 }
 
 ast_enum_of_structs! {
     /// Element of a compile-time attribute list.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// *This type is available only 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::Path`.
         Meta(Meta),
 
         /// A Rust literal, like the `"new_name"` in `#[rename("new_name")]`.
         Lit(Lit),
@@ -424,18 +434,18 @@ ast_enum_of_structs! {
 ///     /* ... */
 /// }
 /// ```
 ///
 /// The implementation of this macro would want to parse its attribute arguments
 /// as type `AttributeArgs`.
 ///
 /// ```
-/// extern crate proc_macro;
-///
+/// # extern crate proc_macro;
+/// #
 /// use proc_macro::TokenStream;
 /// use syn::{parse_macro_input, AttributeArgs, ItemFn};
 ///
 /// # const IGNORE: &str = stringify! {
 /// #[proc_macro_attribute]
 /// # };
 /// pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
 ///     let args = parse_macro_input!(args as AttributeArgs);
@@ -459,27 +469,27 @@ 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,
+                AttrStyle::Inner(_) => 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,
+                AttrStyle::Outer => false,
             }
         }
         self.into_iter().filter(is_inner)
     }
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
--- a/third_party/rust/syn/src/buffer.rs
+++ b/third_party/rust/syn/src/buffer.rs
@@ -1,12 +1,12 @@
 //! A stably addressed token buffer supporting efficient traversal based on a
 //! cheaply copyable cursor.
 //!
-//! *This module is available if Syn is built with the `"parsing"` feature.*
+//! *This module is available only if Syn is built with the `"parsing"` feature.*
 
 // This module is heavily commented as it contains most of the 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", any(target_os = "unknown", target_os = "wasi"))),
     feature = "proc-macro"
@@ -31,17 +31,17 @@ enum Entry {
     // 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.
 ///
-/// *This type is available if Syn is built with the `"parsing"` feature.*
+/// *This type is available only 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 {
@@ -93,17 +93,17 @@ impl TokenBuffer {
         }
 
         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
+    /// *This method is available only if Syn is built with both the `"parsing"` and
     /// `"proc-macro"` features.*
     #[cfg(all(
         not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
         feature = "proc-macro"
     ))]
     pub fn new(stream: pm::TokenStream) -> TokenBuffer {
         Self::new2(stream.into())
     }
@@ -128,18 +128,17 @@ impl TokenBuffer {
 /// 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.
 ///
-/// *This type is available if Syn is built with the `"parsing"` feature.*
-#[derive(Copy, Clone, Eq, PartialEq)]
+/// *This type is available only if Syn is built with the `"parsing"` feature.*
 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,
     // Cursor is covariant in 'a. This field ensures that our pointers are still
     // valid.
@@ -196,37 +195,38 @@ impl<'a> Cursor<'a> {
 
     /// 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
+    /// While 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(group, buf) = self.entry() {
+        while let Entry::Group(group, buf) = self.entry() {
             if group.delimiter() == Delimiter::None {
                 // 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);
                 }
+            } else {
+                break;
             }
         }
     }
 
     /// 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>)> {
@@ -337,16 +337,54 @@ impl<'a> Cursor<'a> {
         match self.entry() {
             Entry::Group(group, _) => group.span(),
             Entry::Literal(l) => l.span(),
             Entry::Ident(t) => t.span(),
             Entry::Punct(o) => o.span(),
             Entry::End(..) => Span::call_site(),
         }
     }
+
+    /// Skip over the next token without cloning it. Returns `None` if this
+    /// cursor points to eof.
+    ///
+    /// This method treats `'lifetimes` as a single token.
+    pub(crate) fn skip(self) -> Option<Cursor<'a>> {
+        match self.entry() {
+            Entry::End(..) => None,
+
+            // Treat lifetimes as a single tt for the purposes of 'skip'.
+            Entry::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => {
+                let next = unsafe { self.bump() };
+                match next.entry() {
+                    Entry::Ident(_) => Some(unsafe { next.bump() }),
+                    _ => Some(next),
+                }
+            }
+            _ => Some(unsafe { self.bump() }),
+        }
+    }
+}
+
+impl<'a> Copy for Cursor<'a> {}
+
+impl<'a> Clone for Cursor<'a> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<'a> Eq for Cursor<'a> {}
+
+impl<'a> PartialEq for Cursor<'a> {
+    fn eq(&self, other: &Self) -> bool {
+        let Cursor { ptr, scope, marker } = self;
+        let _ = marker;
+        *ptr == other.ptr && *scope == other.scope
+    }
 }
 
 pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
     a.scope == b.scope
 }
 
 pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
     match cursor.entry() {
--- a/third_party/rust/syn/src/custom_keyword.rs
+++ b/third_party/rust/syn/src/custom_keyword.rs
@@ -81,46 +81,46 @@
 ///                 value: input.parse()?,
 ///             })
 ///         } else {
 ///             Err(lookahead.error())
 ///         }
 ///     }
 /// }
 /// ```
-#[macro_export(local_inner_macros)]
+#[macro_export]
 macro_rules! custom_keyword {
     ($ident:ident) => {
         #[allow(non_camel_case_types)]
         pub struct $ident {
             pub span: $crate::export::Span,
         }
 
         #[doc(hidden)]
-        #[allow(non_snake_case)]
+        #[allow(dead_code, non_snake_case)]
         pub fn $ident<__S: $crate::export::IntoSpans<[$crate::export::Span; 1]>>(
             span: __S,
         ) -> $ident {
             $ident {
                 span: $crate::export::IntoSpans::into_spans(span)[0],
             }
         }
 
         impl $crate::export::Default for $ident {
             fn default() -> Self {
                 $ident {
                     span: $crate::export::Span::call_site(),
                 }
             }
         }
 
-        impl_parse_for_custom_keyword!($ident);
-        impl_to_tokens_for_custom_keyword!($ident);
-        impl_clone_for_custom_keyword!($ident);
-        impl_extra_traits_for_custom_keyword!($ident);
+        $crate::impl_parse_for_custom_keyword!($ident);
+        $crate::impl_to_tokens_for_custom_keyword!($ident);
+        $crate::impl_clone_for_custom_keyword!($ident);
+        $crate::impl_extra_traits_for_custom_keyword!($ident);
     };
 }
 
 // Not public API.
 #[cfg(feature = "parsing")]
 #[doc(hidden)]
 #[macro_export]
 macro_rules! impl_parse_for_custom_keyword {
--- a/third_party/rust/syn/src/custom_punctuation.rs
+++ b/third_party/rust/syn/src/custom_punctuation.rs
@@ -69,67 +69,67 @@
 ///     Ok(tokens)
 /// }
 ///
 /// fn main() {
 ///     let input = r#" a::b </> c::d::e "#;
 ///     let _: PathSegments = syn::parse_str(input).unwrap();
 /// }
 /// ```
-#[macro_export(local_inner_macros)]
+#[macro_export]
 macro_rules! custom_punctuation {
     ($ident:ident, $($tt:tt)+) => {
         pub struct $ident {
-            pub spans: custom_punctuation_repr!($($tt)+),
+            pub spans: $crate::custom_punctuation_repr!($($tt)+),
         }
 
         #[doc(hidden)]
-        #[allow(non_snake_case)]
-        pub fn $ident<__S: $crate::export::IntoSpans<custom_punctuation_repr!($($tt)+)>>(
+        #[allow(dead_code, non_snake_case)]
+        pub fn $ident<__S: $crate::export::IntoSpans<$crate::custom_punctuation_repr!($($tt)+)>>(
             spans: __S,
         ) -> $ident {
-            let _validate_len = 0 $(+ custom_punctuation_len!(strict, $tt))*;
+            let _validate_len = 0 $(+ $crate::custom_punctuation_len!(strict, $tt))*;
             $ident {
                 spans: $crate::export::IntoSpans::into_spans(spans)
             }
         }
 
         impl $crate::export::Default for $ident {
             fn default() -> Self {
                 $ident($crate::export::Span::call_site())
             }
         }
 
-        impl_parse_for_custom_punctuation!($ident, $($tt)+);
-        impl_to_tokens_for_custom_punctuation!($ident, $($tt)+);
-        impl_clone_for_custom_punctuation!($ident, $($tt)+);
-        impl_extra_traits_for_custom_punctuation!($ident, $($tt)+);
+        $crate::impl_parse_for_custom_punctuation!($ident, $($tt)+);
+        $crate::impl_to_tokens_for_custom_punctuation!($ident, $($tt)+);
+        $crate::impl_clone_for_custom_punctuation!($ident, $($tt)+);
+        $crate::impl_extra_traits_for_custom_punctuation!($ident, $($tt)+);
     };
 }
 
 // Not public API.
 #[cfg(feature = "parsing")]
 #[doc(hidden)]
-#[macro_export(local_inner_macros)]
+#[macro_export]
 macro_rules! impl_parse_for_custom_punctuation {
     ($ident:ident, $($tt:tt)+) => {
         impl $crate::token::CustomToken for $ident {
             fn peek(cursor: $crate::buffer::Cursor) -> bool {
-                $crate::token::parsing::peek_punct(cursor, stringify_punct!($($tt)+))
+                $crate::token::parsing::peek_punct(cursor, $crate::stringify_punct!($($tt)+))
             }
 
             fn display() -> &'static $crate::export::str {
-                custom_punctuation_concat!("`", stringify_punct!($($tt)+), "`")
+                concat!("`", $crate::stringify_punct!($($tt)+), "`")
             }
         }
 
         impl $crate::parse::Parse for $ident {
             fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
-                let spans: custom_punctuation_repr!($($tt)+) =
-                    $crate::token::parsing::punct(input, stringify_punct!($($tt)+))?;
+                let spans: $crate::custom_punctuation_repr!($($tt)+) =
+                    $crate::token::parsing::punct(input, $crate::stringify_punct!($($tt)+))?;
                 Ok($ident(spans))
             }
         }
     };
 }
 
 // Not public API.
 #[cfg(not(feature = "parsing"))]
@@ -137,22 +137,22 @@ macro_rules! impl_parse_for_custom_punct
 #[macro_export]
 macro_rules! impl_parse_for_custom_punctuation {
     ($ident:ident, $($tt:tt)+) => {};
 }
 
 // Not public API.
 #[cfg(feature = "printing")]
 #[doc(hidden)]
-#[macro_export(local_inner_macros)]
+#[macro_export]
 macro_rules! impl_to_tokens_for_custom_punctuation {
     ($ident:ident, $($tt:tt)+) => {
         impl $crate::export::ToTokens for $ident {
             fn to_tokens(&self, tokens: &mut $crate::export::TokenStream2) {
-                $crate::token::printing::punct(stringify_punct!($($tt)+), &self.spans, tokens)
+                $crate::token::printing::punct($crate::stringify_punct!($($tt)+), &self.spans, tokens)
             }
         }
     };
 }
 
 // Not public API.
 #[cfg(not(feature = "printing"))]
 #[doc(hidden)]
@@ -216,26 +216,26 @@ macro_rules! impl_extra_traits_for_custo
 #[doc(hidden)]
 #[macro_export]
 macro_rules! impl_extra_traits_for_custom_punctuation {
     ($ident:ident, $($tt:tt)+) => {};
 }
 
 // Not public API.
 #[doc(hidden)]
-#[macro_export(local_inner_macros)]
+#[macro_export]
 macro_rules! custom_punctuation_repr {
     ($($tt:tt)+) => {
-        [$crate::export::Span; 0 $(+ custom_punctuation_len!(lenient, $tt))+]
+        [$crate::export::Span; 0 $(+ $crate::custom_punctuation_len!(lenient, $tt))+]
     };
 }
 
 // Not public API.
 #[doc(hidden)]
-#[macro_export(local_inner_macros)]
+#[macro_export]
 #[rustfmt::skip]
 macro_rules! custom_punctuation_len {
     ($mode:ident, +)     => { 1 };
     ($mode:ident, +=)    => { 2 };
     ($mode:ident, &)     => { 1 };
     ($mode:ident, &&)    => { 2 };
     ($mode:ident, &=)    => { 2 };
     ($mode:ident, @)     => { 1 };
@@ -274,17 +274,17 @@ macro_rules! custom_punctuation_len {
     ($mode:ident, <<=)   => { 3 };
     ($mode:ident, >>)    => { 2 };
     ($mode:ident, >>=)   => { 3 };
     ($mode:ident, *)     => { 1 };
     ($mode:ident, -)     => { 1 };
     ($mode:ident, -=)    => { 2 };
     ($mode:ident, ~)     => { 1 };
     (lenient, $tt:tt)    => { 0 };
-    (strict, $tt:tt)     => {{ custom_punctuation_unexpected!($tt); 0 }};
+    (strict, $tt:tt)     => {{ $crate::custom_punctuation_unexpected!($tt); 0 }};
 }
 
 // Not public API.
 #[doc(hidden)]
 #[macro_export]
 macro_rules! custom_punctuation_unexpected {
     () => {};
 }
@@ -292,18 +292,8 @@ macro_rules! custom_punctuation_unexpect
 // Not public API.
 #[doc(hidden)]
 #[macro_export]
 macro_rules! stringify_punct {
     ($($tt:tt)+) => {
         concat!($(stringify!($tt)),+)
     };
 }
-
-// Not public API.
-// Without this, local_inner_macros breaks when looking for concat!
-#[doc(hidden)]
-#[macro_export]
-macro_rules! custom_punctuation_concat {
-    ($($tt:tt)*) => {
-        concat!($($tt)*)
-    };
-}
--- a/third_party/rust/syn/src/data.rs
+++ b/third_party/rust/syn/src/data.rs
@@ -1,15 +1,15 @@
 use super::*;
 use crate::punctuated::Punctuated;
 
 ast_struct! {
     /// An enum variant.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// *This type is available only 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,
 
@@ -19,17 +19,17 @@ ast_struct! {
         /// 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"`
+    /// *This type is available only 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
     //
@@ -47,28 +47,28 @@ ast_enum_of_structs! {
         Unit,
     }
 }
 
 ast_struct! {
     /// 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
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct FieldsNamed {
         pub brace_token: token::Brace,
         pub named: Punctuated<Field, Token![,]>,
     }
 }
 
 ast_struct! {
     /// 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
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct FieldsUnnamed {
         pub paren_token: token::Paren,
         pub unnamed: Punctuated<Field, Token![,]>,
     }
 }
 
 impl Fields {
@@ -88,16 +88,34 @@ impl Fields {
     /// struct or variant's fields uniformly.
     pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
         match self {
             Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
             Fields::Named(f) => f.named.iter_mut(),
             Fields::Unnamed(f) => f.unnamed.iter_mut(),
         }
     }
+
+    /// Returns the number of fields.
+    pub fn len(&self) -> usize {
+        match self {
+            Fields::Unit => 0,
+            Fields::Named(f) => f.named.len(),
+            Fields::Unnamed(f) => f.unnamed.len(),
+        }
+    }
+
+    /// Returns `true` if there are zero fields.
+    pub fn is_empty(&self) -> bool {
+        match self {
+            Fields::Unit => true,
+            Fields::Named(f) => f.named.is_empty(),
+            Fields::Unnamed(f) => f.unnamed.is_empty(),
+        }
+    }
 }
 
 impl IntoIterator for Fields {
     type Item = Field;
     type IntoIter = punctuated::IntoIter<Field>;
 
     fn into_iter(self) -> Self::IntoIter {
         match self {
@@ -124,17 +142,17 @@ impl<'a> IntoIterator for &'a mut Fields
     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"`
+    /// *This type is available only 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,
 
@@ -149,17 +167,17 @@ ast_struct! {
         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"`
+    /// *This type is available only 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
     //
@@ -179,58 +197,61 @@ ast_enum_of_structs! {
         /// An inherited visibility, which usually means private.
         Inherited,
     }
 }
 
 ast_struct! {
     /// A public visibility level: `pub`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct VisPublic {
         pub pub_token: Token![pub],
     }
 }
 
 ast_struct! {
     /// A crate-level visibility: `crate`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct VisCrate {
         pub crate_token: Token![crate],
     }
 }
 
 ast_struct! {
     /// 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
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct VisRestricted {
         pub pub_token: Token![pub],
         pub paren_token: token::Paren,
         pub in_token: Option<Token![in]>,
         pub path: Box<Path>,
     }
 }
 
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
 
     use crate::ext::IdentExt;
+    use crate::parse::discouraged::Speculative;
     use crate::parse::{Parse, ParseStream, Result};
 
     impl Parse for Variant {
         fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
+            let _visibility: Visibility = input.parse()?;
             Ok(Variant {
-                attrs: input.call(Attribute::parse_outer)?,
+                attrs,
                 ident: input.parse()?,
                 fields: {
                     if input.peek(token::Brace) {
                         Fields::Named(input.parse()?)
                     } else if input.peek(token::Paren) {
                         Fields::Unnamed(input.parse()?)
                     } else {
                         Fields::Unit
@@ -290,68 +311,99 @@ pub mod parsing {
                 colon_token: None,
                 ty: input.parse()?,
             })
         }
     }
 
     impl Parse for Visibility {
         fn parse(input: ParseStream) -> Result<Self> {
+            // Recognize an empty None-delimited group, as produced by a $:vis
+            // matcher that matched no tokens.
+            if input.peek(token::Group) {
+                let ahead = input.fork();
+                let group = crate::group::parse_group(&ahead)?;
+                if group.content.is_empty() {
+                    input.advance_to(&ahead);
+                    return Ok(Visibility::Inherited);
+                }
+            }
+
             if input.peek(Token![pub]) {
                 Self::parse_pub(input)
             } else if input.peek(Token![crate]) {
                 Self::parse_crate(input)
             } else {
                 Ok(Visibility::Inherited)
             }
         }
     }
 
     impl Visibility {
         fn parse_pub(input: ParseStream) -> Result<Self> {
             let pub_token = input.parse::<Token![pub]>()?;
 
             if input.peek(token::Paren) {
-                // TODO: optimize using advance_to
                 let ahead = input.fork();
-                let mut content;
-                parenthesized!(content in ahead);
 
+                let content;
+                let paren_token = parenthesized!(content in ahead);
                 if content.peek(Token![crate])
                     || content.peek(Token![self])
                     || content.peek(Token![super])
                 {
+                    let path = content.call(Ident::parse_any)?;
+
+                    // Ensure there are no additional tokens within `content`.
+                    // Without explicitly checking, we may misinterpret a tuple
+                    // field as a restricted visibility, causing a parse error.
+                    // e.g. `pub (crate::A, crate::B)` (Issue #720).
+                    if content.is_empty() {
+                        input.advance_to(&ahead);
+                        return Ok(Visibility::Restricted(VisRestricted {
+                            pub_token,
+                            paren_token,
+                            in_token: None,
+                            path: Box::new(Path::from(path)),
+                        }));
+                    }
+                } else if content.peek(Token![in]) {
+                    let in_token: Token![in] = content.parse()?;
+                    let path = content.call(Path::parse_mod_style)?;
+
+                    input.advance_to(&ahead);
                     return Ok(Visibility::Restricted(VisRestricted {
                         pub_token,
-                        paren_token: parenthesized!(content in input),
-                        in_token: None,
-                        path: Box::new(Path::from(content.call(Ident::parse_any)?)),
-                    }));
-                } else if content.peek(Token![in]) {
-                    return Ok(Visibility::Restricted(VisRestricted {
-                        pub_token,
-                        paren_token: parenthesized!(content in input),
-                        in_token: Some(content.parse()?),
-                        path: Box::new(content.call(Path::parse_mod_style)?),
+                        paren_token,
+                        in_token: Some(in_token),
+                        path: Box::new(path),
                     }));
                 }
             }
 
             Ok(Visibility::Public(VisPublic { pub_token }))
         }
 
         fn parse_crate(input: ParseStream) -> Result<Self> {
             if input.peek2(Token![::]) {
                 Ok(Visibility::Inherited)
             } else {
                 Ok(Visibility::Crate(VisCrate {
                     crate_token: input.parse()?,
                 }))
             }
         }
+
+        #[cfg(feature = "full")]
+        pub(crate) fn is_some(&self) -> bool {
+            match self {
+                Visibility::Inherited => false,
+                _ => true,
+            }
+        }
     }
 }
 
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
 
     use proc_macro2::TokenStream;
--- a/third_party/rust/syn/src/derive.rs
+++ b/third_party/rust/syn/src/derive.rs
@@ -1,15 +1,15 @@
 use super::*;
 use crate::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.*
+    /// *This type is available only 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.
@@ -21,17 +21,17 @@ ast_struct! {
         /// 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.*
+    /// *This type is available only 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
     //
     // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
@@ -48,41 +48,41 @@ ast_enum_of_structs! {
     }
 
     do_not_generate_to_tokens
 }
 
 ast_struct! {
     /// A struct input to a `proc_macro_derive` macro.
     ///
-    /// *This type is available if Syn is built with the `"derive"`
+    /// *This type is available only if Syn is built with the `"derive"`
     /// feature.*
     pub struct DataStruct {
         pub struct_token: Token![struct],
         pub fields: Fields,
         pub semi_token: Option<Token![;]>,
     }
 }
 
 ast_struct! {
     /// An enum input to a `proc_macro_derive` macro.
     ///
-    /// *This type is available if Syn is built with the `"derive"`
+    /// *This type is available only if Syn is built with the `"derive"`
     /// feature.*
     pub struct DataEnum {
         pub enum_token: Token![enum],
         pub brace_token: token::Brace,
         pub variants: Punctuated<Variant, Token![,]>,
     }
 }
 
 ast_struct! {
     /// An untagged union input to a `proc_macro_derive` macro.
     ///
-    /// *This type is available if Syn is built with the `"derive"`
+    /// *This type is available only if Syn is built with the `"derive"`
     /// feature.*
     pub struct DataUnion {
         pub union_token: Token![union],
         pub fields: FieldsNamed,
     }
 }
 
 #[cfg(feature = "parsing")]
--- a/third_party/rust/syn/src/discouraged.rs
+++ b/third_party/rust/syn/src/discouraged.rs
@@ -11,17 +11,17 @@ pub trait Speculative {
     /// stream to the fork to "commit" the parsing from the fork to the main
     /// stream.
     ///
     /// If you can avoid doing this, you should, as it limits the ability to
     /// generate useful errors. That said, it is often the only way to parse
     /// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem
     /// is that when the fork fails to parse an `A`, it's impossible to tell
     /// whether that was because of a syntax error and the user meant to provide
-    /// an `A`, or that the `A`s are finished and its time to start parsing
+    /// an `A`, or that the `A`s are finished and it's time to start parsing
     /// `B`s. Use with care.
     ///
     /// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by
     /// parsing `B*` and removing the leading members of `A` from the
     /// repetition, bypassing the need to involve the downsides associated with
     /// speculative parsing.
     ///
     /// [`ParseStream::fork`]: ParseBuffer::fork
@@ -67,17 +67,16 @@ pub trait Speculative {
     /// # }
     ///
     /// impl Parse for PathSegment {
     ///     fn parse(input: ParseStream) -> Result<Self> {
     ///         if input.peek(Token![super])
     ///             || input.peek(Token![self])
     ///             || input.peek(Token![Self])
     ///             || input.peek(Token![crate])
-    ///             || input.peek(Token![extern])
     ///         {
     ///             let ident = input.call(Ident::parse_any)?;
     ///             return Ok(PathSegment::from(ident));
     ///         }
     ///
     ///         let ident = input.parse()?;
     ///         if input.peek(Token![::]) && input.peek3(Token![<]) {
     ///             return Ok(PathSegment {
@@ -159,13 +158,37 @@ pub trait Speculative {
 }
 
 impl<'a> Speculative for ParseBuffer<'a> {
     fn advance_to(&self, fork: &Self) {
         if !crate::buffer::same_scope(self.cursor(), fork.cursor()) {
             panic!("Fork was not derived from the advancing parse stream");
         }
 
+        let (self_unexp, self_sp) = inner_unexpected(self);
+        let (fork_unexp, fork_sp) = inner_unexpected(fork);
+        if !Rc::ptr_eq(&self_unexp, &fork_unexp) {
+            match (fork_sp, self_sp) {
+                // Unexpected set on the fork, but not on `self`, copy it over.
+                (Some(span), None) => {
+                    self_unexp.set(Unexpected::Some(span));
+                }
+                // Unexpected unset. Use chain to propagate errors from fork.
+                (None, None) => {
+                    fork_unexp.set(Unexpected::Chain(self_unexp));
+
+                    // Ensure toplevel 'unexpected' tokens from the fork don't
+                    // bubble up the chain by replacing the root `unexpected`
+                    // pointer, only 'unexpected' tokens from existing group
+                    // parsers should bubble.
+                    fork.unexpected
+                        .set(Some(Rc::new(Cell::new(Unexpected::None))));
+                }
+                // Unexpected has been set on `self`. No changes needed.
+                (_, Some(_)) => {}
+            }
+        }
+
         // See comment on `cell` in the struct definition.
         self.cell
             .set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) })
     }
 }
--- a/third_party/rust/syn/src/error.rs
+++ b/third_party/rust/syn/src/error.rs
@@ -1,9 +1,8 @@
-use std;
 use std::fmt::{self, Debug, Display};
 use std::iter::FromIterator;
 use std::slice;
 use std::vec;
 
 use proc_macro2::{
     Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
 };
@@ -27,18 +26,18 @@ pub type Result<T> = std::result::Result
 /// message than simply panicking the macro.
 ///
 /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
 ///
 /// When parsing macro input, the [`parse_macro_input!`] macro handles the
 /// conversion to `compile_error!` automatically.
 ///
 /// ```
-/// extern crate proc_macro;
-///
+/// # extern crate proc_macro;
+/// #
 /// use proc_macro::TokenStream;
 /// use syn::{parse_macro_input, AttributeArgs, ItemFn};
 ///
 /// # const IGNORE: &str = stringify! {
 /// #[proc_macro_attribute]
 /// # };
 /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
 ///     let args = parse_macro_input!(args as AttributeArgs);
@@ -77,17 +76,16 @@ pub type Result<T> = std::result::Result
 /// #     use proc_macro2::TokenStream;
 /// #     use syn::{DeriveInput, Result};
 /// #
 /// #     pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
 /// #         unimplemented!()
 /// #     }
 /// # }
 /// ```
-#[derive(Clone)]
 pub struct Error {
     messages: Vec<ErrorMessage>,
 }
 
 struct ErrorMessage {
     // 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
     // errors to be Send and Sync to play nicely with the Failure crate, so pin
@@ -245,16 +243,27 @@ pub fn new_at<T: Display>(scope: Span, c
     if cursor.eof() {
         Error::new(scope, format!("unexpected end of input, {}", message))
     } else {
         let span = crate::buffer::open_span_of_group(cursor);
         Error::new(span, message)
     }
 }
 
+#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
+pub fn new2<T: Display>(start: Span, end: Span, message: T) -> Error {
+    Error {
+        messages: vec![ErrorMessage {
+            start_span: ThreadBound::new(start),
+            end_span: ThreadBound::new(end),
+            message: message.to_string(),
+        }],
+    }
+}
+
 impl Debug for Error {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         if self.messages.len() == 1 {
             formatter
                 .debug_tuple("Error")
                 .field(&self.messages[0])
                 .finish()
         } else {
@@ -273,16 +282,24 @@ impl Debug for ErrorMessage {
 }
 
 impl Display for Error {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         formatter.write_str(&self.messages[0].message)
     }
 }
 
+impl Clone for Error {
+    fn clone(&self) -> Self {
+        Error {
+            messages: self.messages.clone(),
+        }
+    }
+}
+
 impl Clone for ErrorMessage {
     fn clone(&self) -> Self {
         let start = self
             .start_span
             .get()
             .cloned()
             .unwrap_or_else(Span::call_site);
         let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
@@ -350,8 +367,16 @@ impl<'a> Iterator for Iter<'a> {
     type Item = Error;
 
     fn next(&mut self) -> Option<Self::Item> {
         Some(Error {
             messages: vec![self.messages.next()?.clone()],
         })
     }
 }
+
+impl Extend<Error> for Error {
+    fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T) {
+        for err in iter {
+            self.combine(err);
+        }
+    }
+}
--- a/third_party/rust/syn/src/expr.rs
+++ b/third_party/rust/syn/src/expr.rs
@@ -1,23 +1,26 @@
 use super::*;
 use crate::punctuated::Punctuated;
-#[cfg(feature = "extra-traits")]
-use crate::tt::TokenStreamHelper;
+#[cfg(feature = "full")]
+use crate::reserved::Reserved;
 use proc_macro2::{Span, TokenStream};
-#[cfg(feature = "extra-traits")]
+#[cfg(feature = "printing")]
+use quote::IdentFragment;
+#[cfg(feature = "printing")]
+use std::fmt::{self, Display};
 use std::hash::{Hash, Hasher};
-#[cfg(all(feature = "parsing", feature = "full"))]
+#[cfg(feature = "parsing")]
 use std::mem;
 
 ast_enum_of_structs! {
     /// A Rust expression.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or `"full"`
-    /// feature.*
+    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
+    /// feature, but most of the variants are not available unless "full" is enabled.*
     ///
     /// # 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;
@@ -78,17 +81,17 @@ ast_enum_of_structs! {
     /// if let Expr::Tuple(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 #manual_extra_traits {
+    pub enum Expr {
         /// A slice literal expression: `[a, b, c, d]`.
         Array(ExprArray),
 
         /// An assignment expression: `a = compute()`.
         Assign(ExprAssign),
 
         /// A compound assignment expression: `counter += 1`.
         AssignOp(ExprAssignOp),
@@ -223,191 +226,191 @@ ast_enum_of_structs! {
         #[doc(hidden)]
         __Nonexhaustive,
     }
 }
 
 ast_struct! {
     /// A slice literal expression: `[a, b, c, d]`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprArray #full {
         pub attrs: Vec<Attribute>,
         pub bracket_token: token::Bracket,
         pub elems: Punctuated<Expr, Token![,]>,
     }
 }
 
 ast_struct! {
     /// An assignment expression: `a = compute()`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprAssign #full {
         pub attrs: Vec<Attribute>,
         pub left: Box<Expr>,
         pub eq_token: Token![=],
         pub right: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// A compound assignment expression: `counter += 1`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprAssignOp #full {
         pub attrs: Vec<Attribute>,
         pub left: Box<Expr>,
         pub op: BinOp,
         pub right: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// An async block: `async { ... }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprAsync #full {
         pub attrs: Vec<Attribute>,
         pub async_token: Token![async],
         pub capture: Option<Token![move]>,
         pub block: Block,
     }
 }
 
 ast_struct! {
     /// An await expression: `fut.await`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprAwait #full {
         pub attrs: Vec<Attribute>,
         pub base: Box<Expr>,
         pub dot_token: Token![.],
         pub await_token: token::Await,
     }
 }
 
 ast_struct! {
     /// A binary operation: `a + b`, `a * b`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct ExprBinary {
         pub attrs: Vec<Attribute>,
         pub left: Box<Expr>,
         pub op: BinOp,
         pub right: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// A blocked scope: `{ ... }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprBlock #full {
         pub attrs: Vec<Attribute>,
         pub label: Option<Label>,
         pub block: Block,
     }
 }
 
 ast_struct! {
     /// A box expression: `box f`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprBox #full {
         pub attrs: Vec<Attribute>,
         pub box_token: Token![box],
         pub expr: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// A `break`, with an optional label to break and an optional
     /// expression.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprBreak #full {
         pub attrs: Vec<Attribute>,
         pub break_token: Token![break],
         pub label: Option<Lifetime>,
         pub expr: Option<Box<Expr>>,
     }
 }
 
 ast_struct! {
     /// A function call expression: `invoke(a, b)`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct ExprCall {
         pub attrs: Vec<Attribute>,
         pub func: Box<Expr>,
         pub paren_token: token::Paren,
         pub args: Punctuated<Expr, Token![,]>,
     }
 }
 
 ast_struct! {
     /// A cast expression: `foo as f64`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct ExprCast {
         pub attrs: Vec<Attribute>,
         pub expr: Box<Expr>,
         pub as_token: Token![as],
         pub ty: Box<Type>,
     }
 }
 
 ast_struct! {
     /// A closure expression: `|a, b| a + b`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct 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<Pat, Token![,]>,
         pub or2_token: Token![|],
         pub output: ReturnType,
         pub body: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// A `continue`, with an optional label.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprContinue #full {
         pub attrs: Vec<Attribute>,
         pub continue_token: Token![continue],
         pub label: Option<Lifetime>,
     }
 }
 
 ast_struct! {
     /// 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.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprField {
         pub attrs: Vec<Attribute>,
         pub base: Box<Expr>,
         pub dot_token: Token![.],
         pub member: Member,
     }
 }
 
 ast_struct! {
     /// A for loop: `for pat in expr { ... }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprForLoop #full {
         pub attrs: Vec<Attribute>,
         pub label: Option<Label>,
         pub for_token: Token![for],
         pub pat: Pat,
         pub in_token: Token![in],
         pub expr: Box<Expr>,
         pub body: Block,
@@ -416,538 +419,312 @@ ast_struct! {
 
 ast_struct! {
     /// 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.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprGroup #full {
         pub attrs: Vec<Attribute>,
         pub group_token: token::Group,
         pub expr: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// An `if` expression with an optional `else` block: `if expr { ... }
     /// else { ... }`.
     ///
     /// The `else` branch expression may only be an `If` or `Block`
     /// expression, not any of the other types of expression.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct 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>)>,
     }
 }
 
 ast_struct! {
     /// A square bracketed indexing expression: `vector[2]`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct ExprIndex {
         pub attrs: Vec<Attribute>,
         pub expr: Box<Expr>,
         pub bracket_token: token::Bracket,
         pub index: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// A `let` guard: `let Some(x) = opt`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprLet #full {
         pub attrs: Vec<Attribute>,
         pub let_token: Token![let],
         pub pat: Pat,
         pub eq_token: Token![=],
         pub expr: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// A literal in place of an expression: `1`, `"foo"`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct ExprLit {
         pub attrs: Vec<Attribute>,
         pub lit: Lit,
     }
 }
 
 ast_struct! {
     /// Conditionless loop: `loop { ... }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprLoop #full {
         pub attrs: Vec<Attribute>,
         pub label: Option<Label>,
         pub loop_token: Token![loop],
         pub body: Block,
     }
 }
 
 ast_struct! {
     /// A macro invocation expression: `format!("{}", q)`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprMacro #full {
         pub attrs: Vec<Attribute>,
         pub mac: Macro,
     }
 }
 
 ast_struct! {
     /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprMatch #full {
         pub attrs: Vec<Attribute>,
         pub match_token: Token![match],
         pub expr: Box<Expr>,
         pub brace_token: token::Brace,
         pub arms: Vec<Arm>,
     }
 }
 
 ast_struct! {
     /// A method call expression: `x.foo::<T>(a, b)`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct 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![,]>,
     }
 }
 
 ast_struct! {
     /// A parenthesized expression: `(a + b)`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprParen {
         pub attrs: Vec<Attribute>,
         pub paren_token: token::Paren,
         pub expr: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// 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
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct ExprPath {
         pub attrs: Vec<Attribute>,
         pub qself: Option<QSelf>,
         pub path: Path,
     }
 }
 
 ast_struct! {
     /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprRange #full {
         pub attrs: Vec<Attribute>,
         pub from: Option<Box<Expr>>,
         pub limits: RangeLimits,
         pub to: Option<Box<Expr>>,
     }
 }
 
 ast_struct! {
     /// A referencing operation: `&a` or `&mut a`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprReference #full {
         pub attrs: Vec<Attribute>,
         pub and_token: Token![&],
         pub raw: Reserved,
         pub mutability: Option<Token![mut]>,
         pub expr: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// An array literal constructed from one repeated element: `[0u8; N]`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprRepeat #full {
         pub attrs: Vec<Attribute>,
         pub bracket_token: token::Bracket,
         pub expr: Box<Expr>,
         pub semi_token: Token![;],
         pub len: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// A `return`, with an optional value to be returned.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprReturn #full {
         pub attrs: Vec<Attribute>,
         pub return_token: Token![return],
         pub expr: Option<Box<Expr>>,
     }
 }
 
 ast_struct! {
     /// 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.*
+    /// *This type is available only 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>>,
     }
 }
 
 ast_struct! {
     /// A try-expression: `expr?`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprTry #full {
         pub attrs: Vec<Attribute>,
         pub expr: Box<Expr>,
         pub question_token: Token![?],
     }
 }
 
 ast_struct! {
     /// A try block: `try { ... }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprTryBlock #full {
         pub attrs: Vec<Attribute>,
         pub try_token: Token![try],
         pub block: Block,
     }
 }
 
 ast_struct! {
     /// A tuple expression: `(a, b, c, d)`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprTuple #full {
         pub attrs: Vec<Attribute>,
         pub paren_token: token::Paren,
         pub elems: Punctuated<Expr, Token![,]>,
     }
 }
 
 ast_struct! {
     /// A type ascription expression: `foo: f64`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprType #full {
         pub attrs: Vec<Attribute>,
         pub expr: Box<Expr>,
         pub colon_token: Token![:],
         pub ty: Box<Type>,
     }
 }
 
 ast_struct! {
     /// A unary operation: `!x`, `*x`.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or
+    /// *This type is available only if Syn is built with the `"derive"` or
     /// `"full"` feature.*
     pub struct ExprUnary {
         pub attrs: Vec<Attribute>,
         pub op: UnOp,
         pub expr: Box<Expr>,
     }
 }
 
 ast_struct! {
     /// An unsafe block: `unsafe { ... }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprUnsafe #full {
         pub attrs: Vec<Attribute>,
         pub unsafe_token: Token![unsafe],
         pub block: Block,
     }
 }
 
 ast_struct! {
     /// A while loop: `while expr { ... }`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprWhile #full {
         pub attrs: Vec<Attribute>,
         pub label: Option<Label>,
         pub while_token: Token![while],
         pub cond: Box<Expr>,
         pub body: Block,
     }
 }
 
 ast_struct! {
     /// A yield expression: `yield expr`.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct ExprYield #full {
         pub attrs: Vec<Attribute>,
         pub yield_token: Token![yield],
         pub expr: Option<Box<Expr>>,
     }
 }
 
-#[cfg(feature = "extra-traits")]
-impl Eq for Expr {}
-
-#[cfg(feature = "extra-traits")]
-impl PartialEq for Expr {
-    fn eq(&self, other: &Self) -> bool {
-        match (self, other) {
-            (Expr::Array(this), Expr::Array(other)) => this == other,
-            (Expr::Assign(this), Expr::Assign(other)) => this == other,
-            (Expr::AssignOp(this), Expr::AssignOp(other)) => this == other,
-            (Expr::Async(this), Expr::Async(other)) => this == other,
-            (Expr::Await(this), Expr::Await(other)) => this == other,
-            (Expr::Binary(this), Expr::Binary(other)) => this == other,
-            (Expr::Block(this), Expr::Block(other)) => this == other,
-            (Expr::Box(this), Expr::Box(other)) => this == other,
-            (Expr::Break(this), Expr::Break(other)) => this == other,
-            (Expr::Call(this), Expr::Call(other)) => this == other,
-            (Expr::Cast(this), Expr::Cast(other)) => this == other,
-            (Expr::Closure(this), Expr::Closure(other)) => this == other,
-            (Expr::Continue(this), Expr::Continue(other)) => this == other,
-            (Expr::Field(this), Expr::Field(other)) => this == other,
-            (Expr::ForLoop(this), Expr::ForLoop(other)) => this == other,
-            (Expr::Group(this), Expr::Group(other)) => this == other,
-            (Expr::If(this), Expr::If(other)) => this == other,
-            (Expr::Index(this), Expr::Index(other)) => this == other,
-            (Expr::Let(this), Expr::Let(other)) => this == other,
-            (Expr::Lit(this), Expr::Lit(other)) => this == other,
-            (Expr::Loop(this), Expr::Loop(other)) => this == other,
-            (Expr::Macro(this), Expr::Macro(other)) => this == other,
-            (Expr::Match(this), Expr::Match(other)) => this == other,
-            (Expr::MethodCall(this), Expr::MethodCall(other)) => this == other,
-            (Expr::Paren(this), Expr::Paren(other)) => this == other,
-            (Expr::Path(this), Expr::Path(other)) => this == other,
-            (Expr::Range(this), Expr::Range(other)) => this == other,
-            (Expr::Reference(this), Expr::Reference(other)) => this == other,
-            (Expr::Repeat(this), Expr::Repeat(other)) => this == other,
-            (Expr::Return(this), Expr::Return(other)) => this == other,
-            (Expr::Struct(this), Expr::Struct(other)) => this == other,
-            (Expr::Try(this), Expr::Try(other)) => this == other,
-            (Expr::TryBlock(this), Expr::TryBlock(other)) => this == other,
-            (Expr::Tuple(this), Expr::Tuple(other)) => this == other,
-            (Expr::Type(this), Expr::Type(other)) => this == other,
-            (Expr::Unary(this), Expr::Unary(other)) => this == other,
-            (Expr::Unsafe(this), Expr::Unsafe(other)) => this == other,
-            (Expr::Verbatim(this), Expr::Verbatim(other)) => {
-                TokenStreamHelper(this) == TokenStreamHelper(other)
-            }
-            (Expr::While(this), Expr::While(other)) => this == other,
-            (Expr::Yield(this), Expr::Yield(other)) => this == other,
-            _ => false,
-        }
-    }
-}
-
-#[cfg(feature = "extra-traits")]
-impl Hash for Expr {
-    fn hash<H>(&self, hash: &mut H)
-    where
-        H: Hasher,
-    {
-        match self {
-            Expr::Array(expr) => {
-                hash.write_u8(0);
-                expr.hash(hash);
-            }
-            Expr::Assign(expr) => {
-                hash.write_u8(1);
-                expr.hash(hash);
-            }
-            Expr::AssignOp(expr) => {
-                hash.write_u8(2);
-                expr.hash(hash);
-            }
-            Expr::Async(expr) => {
-                hash.write_u8(3);
-                expr.hash(hash);
-            }
-            Expr::Await(expr) => {
-                hash.write_u8(4);
-                expr.hash(hash);
-            }
-            Expr::Binary(expr) => {
-                hash.write_u8(5);
-                expr.hash(hash);
-            }
-            Expr::Block(expr) => {
-                hash.write_u8(6);
-                expr.hash(hash);
-            }
-            Expr::Box(expr) => {
-                hash.write_u8(7);
-                expr.hash(hash);
-            }
-            Expr::Break(expr) => {
-                hash.write_u8(8);
-                expr.hash(hash);
-            }
-            Expr::Call(expr) => {
-                hash.write_u8(9);
-                expr.hash(hash);
-            }
-            Expr::Cast(expr) => {
-                hash.write_u8(10);
-                expr.hash(hash);
-            }
-            Expr::Closure(expr) => {
-                hash.write_u8(11);
-                expr.hash(hash);
-            }
-            Expr::Continue(expr) => {
-                hash.write_u8(12);
-                expr.hash(hash);
-            }
-            Expr::Field(expr) => {
-                hash.write_u8(13);
-                expr.hash(hash);
-            }
-            Expr::ForLoop(expr) => {
-                hash.write_u8(14);
-                expr.hash(hash);
-            }
-            Expr::Group(expr) => {
-                hash.write_u8(15);
-                expr.hash(hash);
-            }
-            Expr::If(expr) => {
-                hash.write_u8(16);
-                expr.hash(hash);
-            }
-            Expr::Index(expr) => {
-                hash.write_u8(17);
-                expr.hash(hash);
-            }
-            Expr::Let(expr) => {
-                hash.write_u8(18);
-                expr.hash(hash);
-            }
-            Expr::Lit(expr) => {
-                hash.write_u8(19);
-                expr.hash(hash);
-            }
-            Expr::Loop(expr) => {
-                hash.write_u8(20);
-                expr.hash(hash);
-            }
-            Expr::Macro(expr) => {
-                hash.write_u8(21);
-                expr.hash(hash);
-            }
-            Expr::Match(expr) => {
-                hash.write_u8(22);
-                expr.hash(hash);
-            }
-            Expr::MethodCall(expr) => {
-                hash.write_u8(23);
-                expr.hash(hash);
-            }
-            Expr::Paren(expr) => {
-                hash.write_u8(24);
-                expr.hash(hash);
-            }
-            Expr::Path(expr) => {
-                hash.write_u8(25);
-                expr.hash(hash);
-            }
-            Expr::Range(expr) => {
-                hash.write_u8(26);
-                expr.hash(hash);
-            }
-            Expr::Reference(expr) => {
-                hash.write_u8(27);
-                expr.hash(hash);
-            }
-            Expr::Repeat(expr) => {
-                hash.write_u8(28);
-                expr.hash(hash);
-            }
-            Expr::Return(expr) => {
-                hash.write_u8(29);
-                expr.hash(hash);
-            }
-            Expr::Struct(expr) => {
-                hash.write_u8(30);
-                expr.hash(hash);
-            }
-            Expr::Try(expr) => {
-                hash.write_u8(31);
-                expr.hash(hash);
-            }
-            Expr::TryBlock(expr) => {
-                hash.write_u8(32);
-                expr.hash(hash);
-            }
-            Expr::Tuple(expr) => {
-                hash.write_u8(33);
-                expr.hash(hash);
-            }
-            Expr::Type(expr) => {
-                hash.write_u8(34);
-                expr.hash(hash);
-            }
-            Expr::Unary(expr) => {
-                hash.write_u8(35);
-                expr.hash(hash);
-            }
-            Expr::Unsafe(expr) => {
-                hash.write_u8(36);
-                expr.hash(hash);
-            }
-            Expr::Verbatim(expr) => {
-                hash.write_u8(37);
-                TokenStreamHelper(expr).hash(hash);
-            }
-            Expr::While(expr) => {
-                hash.write_u8(38);
-                expr.hash(hash);
-            }
-            Expr::Yield(expr) => {
-                hash.write_u8(39);
-                expr.hash(hash);
-            }
-            Expr::__Nonexhaustive => unreachable!(),
-        }
-    }
-}
-
 impl Expr {
     #[cfg(all(feature = "parsing", feature = "full"))]
     pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
         match self {
             Expr::Box(ExprBox { attrs, .. })
             | Expr::Array(ExprArray { attrs, .. })
             | Expr::Call(ExprCall { attrs, .. })
             | Expr::MethodCall(ExprMethodCall { attrs, .. })
@@ -991,107 +768,145 @@ impl Expr {
         }
     }
 }
 
 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"`
+    /// *This type is available only 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),
     }
 }
 
+impl Eq for Member {}
+
+impl PartialEq for Member {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            (Member::Named(this), Member::Named(other)) => this == other,
+            (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
+            _ => false,
+        }
+    }
+}
+
+impl Hash for Member {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        match self {
+            Member::Named(m) => m.hash(state),
+            Member::Unnamed(m) => m.hash(state),
+        }
+    }
+}
+
+#[cfg(feature = "printing")]
+impl IdentFragment for Member {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Member::Named(m) => Display::fmt(m, formatter),
+            Member::Unnamed(m) => Display::fmt(&m.index, formatter),
+        }
+    }
+
+    fn span(&self) -> Option<Span> {
+        match self {
+            Member::Named(m) => Some(m.span()),
+            Member::Unnamed(m) => Some(m.span),
+        }
+    }
+}
+
 ast_struct! {
     /// The index of an unnamed tuple struct field.
     ///
-    /// *This type is available if Syn is built with the `"derive"` or `"full"`
+    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
     /// feature.*
-    pub struct Index #manual_extra_traits {
+    pub struct Index {
         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! {
-    #[derive(Default)]
-    pub struct Reserved {
-        private: (),
+#[cfg(feature = "printing")]
+impl IdentFragment for Index {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.index, formatter)
+    }
+
+    fn span(&self) -> Option<Span> {
+        Some(self.span)
     }
 }
 
 #[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.*
+    /// *This type is available only 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.*
+    /// *This type is available only 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.*
+    /// *This type is available only 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
@@ -1102,17 +917,17 @@ ast_struct! {
         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.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct Label {
         pub name: Lifetime,
         pub colon_token: Token![:],
     }
 }
 
 #[cfg(feature = "full")]
 ast_struct! {
@@ -1129,45 +944,44 @@ ast_struct! {
     ///     }
     ///     // ...
     ///     # _ => {}
     /// }
     /// #   false
     /// # }
     /// ```
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub struct Arm {
         pub attrs: Vec<Attribute>,
         pub pat: Pat,
         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))]
+    /// *This type is available only if Syn is built with the `"full"` feature.*
     pub enum RangeLimits {
         /// Inclusive at the beginning, exclusive at the end.
         HalfOpen(Token![..]),
         /// Inclusive at the beginning and end.
         Closed(Token![..=]),
     }
 }
 
 #[cfg(any(feature = "parsing", feature = "printing"))]
 #[cfg(feature = "full")]
 pub(crate) fn requires_terminator(expr: &Expr) -> bool {
-    // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
+    // see https://github.com/rust-lang/rust/blob/2679c38fc/src/librustc_ast/util/classify.rs#L7-L25
     match *expr {
         Expr::Unsafe(..)
         | Expr::Block(..)
         | Expr::If(..)
         | Expr::Match(..)
         | Expr::While(..)
         | Expr::Loop(..)
         | Expr::ForLoop(..)
@@ -1178,26 +992,27 @@ pub(crate) fn requires_terminator(expr: 
 }
 
 #[cfg(feature = "parsing")]
 pub(crate) mod parsing {
     use super::*;
 
     use crate::parse::{Parse, ParseStream, Result};
     use crate::path;
+    use std::cmp::Ordering;
+
+    crate::custom_keyword!(raw);
 
     // 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
-    #[derive(Copy, Clone)]
     pub struct AllowStruct(bool);
 
-    #[derive(Copy, Clone, PartialEq, PartialOrd)]
     enum Precedence {
         Any,
         Assign,
         Range,
         Or,
         And,
         Compare,
         BitOr,
@@ -1241,19 +1056,131 @@ pub(crate) mod parsing {
     }
 
     impl Parse for Expr {
         fn parse(input: ParseStream) -> Result<Self> {
             ambiguous_expr(input, AllowStruct(true))
         }
     }
 
-    #[cfg(feature = "full")]
-    fn expr_no_struct(input: ParseStream) -> Result<Expr> {
-        ambiguous_expr(input, AllowStruct(false))
+    impl Expr {
+        /// An alternative to the primary `Expr::parse` parser (from the
+        /// [`Parse`] trait) for ambiguous syntactic positions in which a
+        /// trailing brace should not be taken as part of the expression.
+        ///
+        /// Rust grammar has an ambiguity where braces sometimes turn a path
+        /// expression into a struct initialization and sometimes do not. In the
+        /// following code, the expression `S {}` is one expression. Presumably
+        /// there is an empty struct `struct S {}` defined somewhere which it is
+        /// instantiating.
+        ///
+        /// ```
+        /// # struct S;
+        /// # impl std::ops::Deref for S {
+        /// #     type Target = bool;
+        /// #     fn deref(&self) -> &Self::Target {
+        /// #         &true
+        /// #     }
+        /// # }
+        /// let _ = *S {};
+        ///
+        /// // parsed by rustc as: `*(S {})`
+        /// ```
+        ///
+        /// We would want to parse the above using `Expr::parse` after the `=`
+        /// token.
+        ///
+        /// But in the following, `S {}` is *not* a struct init expression.
+        ///
+        /// ```
+        /// # const S: &bool = &true;
+        /// if *S {} {}
+        ///
+        /// // parsed by rustc as:
+        /// //
+        /// //    if (*S) {
+        /// //        /* empty block */
+        /// //    }
+        /// //    {
+        /// //        /* another empty block */
+        /// //    }
+        /// ```
+        ///
+        /// For that reason we would want to parse if-conditions using
+        /// `Expr::parse_without_eager_brace` after the `if` token. Same for
+        /// similar syntactic positions such as the condition expr after a
+        /// `while` token or the expr at the top of a `match`.
+        ///
+        /// The Rust grammar's choices around which way this ambiguity is
+        /// resolved at various syntactic positions is fairly arbitrary. Really
+        /// either parse behavior could work in most positions, and language
+        /// designers just decide each case based on which is more likely to be
+        /// what the programmer had in mind most of the time.
+        ///
+        /// ```
+        /// # struct S;
+        /// # fn doc() -> S {
+        /// if return S {} {}
+        /// # unreachable!()
+        /// # }
+        ///
+        /// // parsed by rustc as:
+        /// //
+        /// //    if (return (S {})) {
+        /// //    }
+        /// //
+        /// // but could equally well have been this other arbitrary choice:
+        /// //
+        /// //    if (return S) {
+        /// //    }
+        /// //    {}
+        /// ```
+        ///
+        /// Note the grammar ambiguity on trailing braces is distinct from
+        /// precedence and is not captured by assigning a precedence level to
+        /// the braced struct init expr in relation to other operators. This can
+        /// be illustrated by `return 0..S {}` vs `match 0..S {}`. The former
+        /// parses as `return (0..(S {}))` implying tighter precedence for
+        /// struct init than `..`, while the latter parses as `match (0..S) {}`
+        /// implying tighter precedence for `..` than struct init, a
+        /// contradiction.
+        #[cfg(feature = "full")]
+        pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
+            ambiguous_expr(input, AllowStruct(false))
+        }
+    }
+
+    impl Copy for AllowStruct {}
+
+    impl Clone for AllowStruct {
+        fn clone(&self) -> Self {
+            *self
+        }
+    }
+
+    impl Copy for Precedence {}
+
+    impl Clone for Precedence {
+        fn clone(&self) -> Self {
+            *self
+        }
+    }
+
+    impl PartialEq for Precedence {
+        fn eq(&self, other: &Self) -> bool {
+            *self as u8 == *other as u8
+        }
+    }
+
+    impl PartialOrd for Precedence {
+        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+            let this = *self as u8;
+            let other = *other as u8;
+            Some(this.cmp(&other))
+        }
     }
 
     #[cfg(feature = "full")]
     fn parse_expr(
         input: ParseStream,
         mut lhs: Expr,
         allow_struct: AllowStruct,
         base: Precedence,
@@ -1425,88 +1352,114 @@ pub(crate) mod parsing {
     }
 
     // Parse an arbitrary expression.
     fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
         let lhs = unary_expr(input, allow_struct)?;
         parse_expr(input, lhs, allow_struct, Precedence::Any)
     }
 
+    #[cfg(feature = "full")]
+    fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
+        let mut attrs = Vec::new();
+        loop {
+            if input.peek(token::Group) {
+                let ahead = input.fork();
+                let group = crate::group::parse_group(&ahead)?;
+                if !group.content.peek(Token![#]) || group.content.peek2(Token![!]) {
+                    break;
+                }
+                let attr = group.content.call(attr::parsing::single_parse_outer)?;
+                if !group.content.is_empty() {
+                    break;
+                }
+                attrs.push(attr);
+            } else if input.peek(Token![#]) {
+                attrs.push(input.call(attr::parsing::single_parse_outer)?);
+            } else {
+                break;
+            }
+        }
+        Ok(attrs)
+    }
+
     // <UnOp> <trailer>
     // & <trailer>
     // &mut <trailer>
     // box <trailer>
     #[cfg(feature = "full")]
     fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
-        // TODO: optimize using advance_to
-        let ahead = input.fork();
-        ahead.call(Attribute::parse_outer)?;
-        if ahead.peek(Token![&])
-            || ahead.peek(Token![box])
-            || ahead.peek(Token![*])
-            || ahead.peek(Token![!])
-            || ahead.peek(Token![-])
-        {
-            let attrs = input.call(Attribute::parse_outer)?;
-            if input.peek(Token![&]) {
+        let begin = input.fork();
+        let attrs = input.call(expr_attrs)?;
+        if input.peek(Token![&]) {
+            let and_token: Token![&] = input.parse()?;
+            let raw: Option<raw> =
+                if input.peek(raw) && (input.peek2(Token![mut]) || input.peek2(Token![const])) {
+                    Some(input.parse()?)
+                } else {
+                    None
+                };
+            let mutability: Option<Token![mut]> = input.parse()?;
+            if raw.is_some() && mutability.is_none() {
+                input.parse::<Token![const]>()?;
+            }
+            let expr = Box::new(unary_expr(input, allow_struct)?);
+            if raw.is_some() {
+                Ok(Expr::Verbatim(verbatim::between(begin, input)))
+            } else {
                 Ok(Expr::Reference(ExprReference {
                     attrs,
-                    and_token: input.parse()?,
+                    and_token,
                     raw: Reserved::default(),
-                    mutability: input.parse()?,
-                    expr: Box::new(unary_expr(input, allow_struct)?),
-                }))
-            } else if input.peek(Token![box]) {
-                Ok(Expr::Box(ExprBox {
-                    attrs,
-                    box_token: input.parse()?,
-                    expr: Box::new(unary_expr(input, allow_struct)?),
-                }))
-            } else {
-                Ok(Expr::Unary(ExprUnary {
-                    attrs,
-                    op: input.parse()?,
-                    expr: Box::new(unary_expr(input, allow_struct)?),
+                    mutability,
+                    expr,
                 }))
             }
+        } else if input.peek(Token![box]) {
+            Ok(Expr::Box(ExprBox {
+                attrs,
+                box_token: input.parse()?,
+                expr: Box::new(unary_expr(input, allow_struct)?),
+            }))
+        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
+            Ok(Expr::Unary(ExprUnary {
+                attrs,
+                op: input.parse()?,
+                expr: Box::new(unary_expr(input, allow_struct)?),
+            }))
         } else {
-            trailer_expr(input, allow_struct)
+            trailer_expr(attrs, input, allow_struct)
         }
     }
 
     #[cfg(not(feature = "full"))]
     fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
-        // TODO: optimize using advance_to
-        let ahead = input.fork();
-        ahead.call(Attribute::parse_outer)?;
-        if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
+        if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
             Ok(Expr::Unary(ExprUnary {
-                attrs: input.call(Attribute::parse_outer)?,
+                attrs: Vec::new(),
                 op: input.parse()?,
                 expr: Box::new(unary_expr(input, allow_struct)?),
             }))
         } else {
             trailer_expr(input, allow_struct)
         }
     }
 
     // <atom> (..<args>) ...
     // <atom> . <ident> (..<args>) ...
     // <atom> . <ident> ...
     // <atom> . <lit> ...
     // <atom> [ <expr> ] ...
     // <atom> ? ...
     #[cfg(feature = "full")]
-    fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
-        if input.peek(token::Group) {
-            return input.call(expr_group).map(Expr::Group);
-        }
-
-        let outer_attrs = input.call(Attribute::parse_outer)?;
-
+    fn trailer_expr(
+        outer_attrs: Vec<Attribute>,
+        input: ParseStream,
+        allow_struct: AllowStruct,
+    ) -> Result<Expr> {
         let atom = atom_expr(input, allow_struct)?;
         let mut e = trailer_helper(input, atom)?;
 
         let inner_attrs = e.replace_attrs(Vec::new());
         let attrs = private::attrs(outer_attrs, inner_attrs);
         e.replace_attrs(attrs);
         Ok(e)
     }
@@ -1518,28 +1471,36 @@ pub(crate) mod parsing {
                 let content;
                 e = Expr::Call(ExprCall {
                     attrs: Vec::new(),
                     func: Box::new(e),
                     paren_token: parenthesized!(content in input),
                     args: content.parse_terminated(Expr::parse)?,
                 });
             } else if input.peek(Token![.]) && !input.peek(Token![..]) {
-                let dot_token: Token![.] = input.parse()?;
+                let mut dot_token: Token![.] = input.parse()?;
 
-                if input.peek(token::Await) {
+                let await_token: Option<token::Await> = input.parse()?;
+                if let Some(await_token) = await_token {
                     e = Expr::Await(ExprAwait {
                         attrs: Vec::new(),
                         base: Box::new(e),
                         dot_token,
-                        await_token: input.parse()?,
+                        await_token,
                     });
                     continue;
                 }
 
+                let float_token: Option<LitFloat> = input.parse()?;
+                if let Some(float_token) = float_token {
+                    if multi_index(&mut e, &mut dot_token, float_token)? {
+                        continue;
+                    }
+                }
+
                 let member: Member = input.parse()?;
                 let turbofish = if member.is_named() && input.peek(Token![::]) {
                     Some(MethodTurbofish {
                         colon2_token: input.parse()?,
                         lt_token: input.parse()?,
                         args: {
                             let mut args = Punctuated::new();
                             loop {
@@ -1615,20 +1576,27 @@ pub(crate) mod parsing {
                 e = Expr::Call(ExprCall {
                     attrs: Vec::new(),
                     func: Box::new(e),
                     paren_token: parenthesized!(content in input),
                     args: content.parse_terminated(Expr::parse)?,
                 });
             } else if input.peek(Token![.]) && !input.peek(Token![..]) && !input.peek2(token::Await)
             {
+                let mut dot_token: Token![.] = input.parse()?;
+                let float_token: Option<LitFloat> = input.parse()?;
+                if let Some(float_token) = float_token {
+                    if multi_index(&mut e, &mut dot_token, float_token)? {
+                        continue;
+                    }
+                }
                 e = Expr::Field(ExprField {
                     attrs: Vec::new(),
                     base: Box::new(e),
-                    dot_token: input.parse()?,
+                    dot_token,
                     member: input.parse()?,
                 });
             } else if input.peek(token::Bracket) {
                 let content;
                 e = Expr::Index(ExprIndex {
                     attrs: Vec::new(),
                     expr: Box::new(e),
                     bracket_token: bracketed!(content in input),
@@ -1641,17 +1609,21 @@ pub(crate) mod parsing {
 
         Ok(e)
     }
 
     // Parse all atomic expressions which don't have to worry about precedence
     // interactions, as they are fully contained.
     #[cfg(feature = "full")]
     fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
-        if input.peek(token::Group) {
+        if input.peek(token::Group)
+            && !input.peek2(Token![::])
+            && !input.peek2(Token![!])
+            && !input.peek2(token::Brace)
+        {
             input.call(expr_group).map(Expr::Group)
         } else if input.peek(Lit) {
             input.parse().map(Expr::Lit)
         } else if input.peek(Token![async])
             && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
         {
             input.call(expr_async).map(Expr::Async)
         } else if input.peek(Token![try]) && input.peek2(token::Brace) {
@@ -1663,17 +1635,16 @@ pub(crate) mod parsing {
         {
             expr_closure(input, allow_struct).map(Expr::Closure)
         } else if input.peek(Ident)
             || input.peek(Token![::])
             || input.peek(Token![<])
             || input.peek(Token![self])
             || input.peek(Token![Self])
             || input.peek(Token![super])
-            || input.peek(Token![extern])
             || input.peek(Token![crate])
         {
             path_or_macro_or_struct(input, allow_struct)
         } else if input.peek(token::Paren) {
             paren_or_tuple(input)
         } else if input.peek(Token![break]) {
             expr_break(input, allow_struct).map(Expr::Break)
         } else if input.peek(Token![continue]) {
@@ -1735,17 +1706,16 @@ pub(crate) mod parsing {
         } else if input.peek(token::Paren) {
             input.call(expr_paren).map(Expr::Paren)
         } else if input.peek(Ident)
             || input.peek(Token![::])
             || input.peek(Token![<])
             || input.peek(Token![self])
             || input.peek(Token![Self])
             || input.peek(Token![super])
-            || input.peek(Token![extern])
             || input.peek(Token![crate])
         {
             input.parse().map(Expr::Path)
         } else {
             Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
         }
     }
 
@@ -1873,17 +1843,17 @@ pub(crate) mod parsing {
             }))
         } else {
             Err(content.error("expected `,` or `;`"))
         }
     }
 
     #[cfg(feature = "full")]
     pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> {
-        let mut attrs = input.call(Attribute::parse_outer)?;
+        let mut attrs = input.call(expr_attrs)?;
         let mut expr = if input.peek(Token![if]) {
             Expr::If(input.parse()?)
         } else if input.peek(Token![while]) {
             Expr::While(input.parse()?)
         } else if input.peek(Token![for]) {
             Expr::ForLoop(input.parse()?)
         } else if input.peek(Token![loop]) {
             Expr::Loop(input.parse()?)
@@ -1900,17 +1870,17 @@ pub(crate) mod parsing {
             let mut expr = unary_expr(input, allow_struct)?;
 
             attrs.extend(expr.replace_attrs(Vec::new()));
             expr.replace_attrs(attrs);
 
             return parse_expr(input, expr, allow_struct, Precedence::Any);
         };
 
-        if input.peek(Token![.]) || input.peek(Token![?]) {
+        if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
             expr = trailer_helper(input, expr)?;
 
             attrs.extend(expr.replace_attrs(Vec::new()));
             expr.replace_attrs(attrs);
 
             let allow_struct = AllowStruct(true);
             return parse_expr(input, expr, allow_struct, Precedence::Any);
         }
@@ -1946,63 +1916,48 @@ pub(crate) mod parsing {
             attrs: Vec::new(),
             paren_token: parenthesized!(content in input),
             expr: content.parse()?,
         })
     }
 
     #[cfg(feature = "full")]
     fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
-        // TODO parse const generics as well
+        if input.peek(Lit) {
+            let lit = input.parse()?;
+            return Ok(GenericMethodArgument::Const(Expr::Lit(lit)));
+        }
+
+        if input.peek(token::Brace) {
+            let block = input.call(expr::parsing::expr_block)?;
+            return Ok(GenericMethodArgument::Const(Expr::Block(block)));
+        }
+
         input.parse().map(GenericMethodArgument::Type)
     }
 
     #[cfg(feature = "full")]
     fn expr_let(input: ParseStream) -> Result<ExprLet> {
         Ok(ExprLet {
             attrs: Vec::new(),
             let_token: input.parse()?,
-            pat: {
-                let leading_vert: Option<Token![|]> = input.parse()?;
-                let pat: Pat = input.parse()?;
-                if leading_vert.is_some()
-                    || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
-                {
-                    let mut cases = Punctuated::new();
-                    cases.push_value(pat);
-                    while input.peek(Token![|])
-                        && !input.peek(Token![||])
-                        && !input.peek(Token![|=])
-                    {
-                        let punct = input.parse()?;
-                        cases.push_punct(punct);
-                        let pat: Pat = input.parse()?;
-                        cases.push_value(pat);
-                    }
-                    Pat::Or(PatOr {
-                        attrs: Vec::new(),
-                        leading_vert,
-                        cases,
-                    })
-                } else {
-                    pat
-                }
-            },
+            pat: pat::parsing::multi_pat_with_leading_vert(input)?,
             eq_token: input.parse()?,
-            expr: Box::new(input.call(expr_no_struct)?),
+            expr: Box::new(input.call(Expr::parse_without_eager_brace)?),
         })
     }
 
     #[cfg(feature = "full")]
     impl Parse for ExprIf {
         fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
             Ok(ExprIf {
-                attrs: Vec::new(),
+                attrs,
                 if_token: input.parse()?,
-                cond: Box::new(input.call(expr_no_struct)?),
+                cond: Box::new(input.call(Expr::parse_without_eager_brace)?),
                 then_branch: input.parse()?,
                 else_branch: {
                     if input.peek(Token![else]) {
                         Some(input.call(else_block)?)
                     } else {
                         None
                     }
                 },
@@ -2028,94 +1983,81 @@ pub(crate) mod parsing {
         };
 
         Ok((else_token, Box::new(else_branch)))
     }
 
     #[cfg(feature = "full")]
     impl Parse for ExprForLoop {
         fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
             let label: Option<Label> = input.parse()?;
             let for_token: Token![for] = input.parse()?;
 
-            let leading_vert: Option<Token![|]> = input.parse()?;
-            let mut pat: Pat = input.parse()?;
-            if leading_vert.is_some() || input.peek(Token![|]) {
-                let mut cases = Punctuated::new();
-                cases.push_value(pat);
-                while input.peek(Token![|]) {
-                    let punct = input.parse()?;
-                    cases.push_punct(punct);
-                    let pat: Pat = input.parse()?;
-                    cases.push_value(pat);
-                }
-                pat = Pat::Or(PatOr {
-                    attrs: Vec::new(),
-                    leading_vert,
-                    cases,
-                });
-            }
+            let pat = pat::parsing::multi_pat_with_leading_vert(input)?;
 
             let in_token: Token![in] = input.parse()?;
-            let expr: Expr = input.call(expr_no_struct)?;
+            let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
 
             let content;
             let brace_token = braced!(content in input);
             let inner_attrs = content.call(Attribute::parse_inner)?;
             let stmts = content.call(Block::parse_within)?;
 
             Ok(ExprForLoop {
-                attrs: inner_attrs,
+                attrs: private::attrs(outer_attrs, inner_attrs),
                 label,
                 for_token,
                 pat,
                 in_token,
                 expr: Box::new(expr),
                 body: Block { brace_token, stmts },
             })
         }
     }
 
     #[cfg(feature = "full")]
     impl Parse for ExprLoop {
         fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
             let label: Option<Label> = input.parse()?;
             let loop_token: Token![loop] = input.parse()?;
 
             let content;
             let brace_token = braced!(content in input);
             let inner_attrs = content.call(Attribute::parse_inner)?;
             let stmts = content.call(Block::parse_within)?;
 
             Ok(ExprLoop {
-                attrs: inner_attrs,
+                attrs: private::attrs(outer_attrs, inner_attrs),
                 label,
                 loop_token,
                 body: Block { brace_token, stmts },
             })
         }
     }
 
     #[cfg(feature = "full")]
     impl Parse for ExprMatch {
         fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
             let match_token: Token![match] = input.parse()?;
-            let expr = expr_no_struct(input)?;
+            let expr = Expr::parse_without_eager_brace(input)?;
 
             let content;
             let brace_token = braced!(content in input);
             let inner_attrs = content.call(Attribute::parse_inner)?;
 
             let mut arms = Vec::new();
             while !content.is_empty() {
                 arms.push(content.call(Arm::parse)?);
             }
 
             Ok(ExprMatch {
-                attrs: inner_attrs,
+                attrs: private::attrs(outer_attrs, inner_attrs),
                 match_token,
                 expr: Box::new(expr),
                 brace_token,
                 arms,
             })
         }
     }
 
@@ -2300,27 +2242,28 @@ pub(crate) mod parsing {
             }
             Ok(pat)
         }
     }
 
     #[cfg(feature = "full")]
     impl Parse for ExprWhile {
         fn parse(input: ParseStream) -> Result<Self> {
+            let outer_attrs = input.call(Attribute::parse_outer)?;
             let label: Option<Label> = input.parse()?;
             let while_token: Token![while] = input.parse()?;
-            let cond = expr_no_struct(input)?;
+            let cond = Expr::parse_without_eager_brace(input)?;
 
             let content;
             let brace_token = braced!(content in input);
             let inner_attrs = content.call(Attribute::parse_inner)?;
             let stmts = content.call(Block::parse_within)?;
 
             Ok(ExprWhile {
-                attrs: inner_attrs,
+                attrs: private::attrs(outer_attrs, inner_attrs),
                 label,
                 while_token,
                 cond: Box::new(cond),
                 body: Block { brace_token, stmts },
             })
         }
     }
 
@@ -2394,16 +2337,17 @@ pub(crate) mod parsing {
                 }
             },
         })
     }
 
     #[cfg(feature = "full")]
     impl Parse for FieldValue {
         fn parse(input: ParseStream) -> Result<Self> {
+            let attrs = input.call(Attribute::parse_outer)?;
             let member: Member = input.parse()?;
             let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
                 let colon_token: Token![:] = input.parse()?;
                 let value: Expr = input.parse()?;
                 (Some(colon_token), value)
             } else if let Member::Named(ident) = &member {
                 let value = Expr::Path(ExprPath {
                     attrs: Vec::new(),
@@ -2411,73 +2355,63 @@ pub(crate) mod parsing {
                     path: Path::from(ident.clone()),
                 });
                 (None, value)
             } else {
                 unreachable!()
             };
 
             Ok(FieldValue {
-                attrs: Vec::new(),
+                attrs,
                 member,
                 colon_token,
                 expr: value,
             })
         }
     }
 
     #[cfg(feature = "full")]
     fn expr_struct_helper(
         input: ParseStream,
         outer_attrs: Vec<Attribute>,
         path: Path,
     ) -> Result<ExprStruct> {
         let content;
         let brace_token = braced!(content in input);
         let inner_attrs = content.call(Attribute::parse_inner)?;
+        let attrs = private::attrs(outer_attrs, inner_attrs);
 
         let mut fields = Punctuated::new();
-        loop {
-            let attrs = content.call(Attribute::parse_outer)?;
-            // TODO: optimize using advance_to
-            if content.fork().parse::<Member>().is_err() {
-                if attrs.is_empty() {
-                    break;
-                } else {
-                    return Err(content.error("expected struct field"));
-                }
+        while !content.is_empty() {
+            if content.peek(Token![..]) {
+                return Ok(ExprStruct {
+                    attrs,
+                    brace_token,
+                    path,
+                    fields,
+                    dot2_token: Some(content.parse()?),
+                    rest: Some(Box::new(content.parse()?)),
+                });
             }
 
-            fields.push(FieldValue {
-                attrs,
-                ..content.parse()?
-            });
-
-            if !content.peek(Token![,]) {
+            fields.push(content.parse()?);
+            if content.is_empty() {
                 break;
             }
             let punct: Token![,] = content.parse()?;
             fields.push_punct(punct);
         }
 
-        let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
-            let dot2_token: Token![..] = content.parse()?;
-            let rest: Expr = content.parse()?;
-            (Some(dot2_token), Some(Box::new(rest)))
-        } else {
-            (None, None)
-        };
-
         Ok(ExprStruct {
-            attrs: private::attrs(outer_attrs, inner_attrs),
+            attrs,
             brace_token,
             path,
             fields,
-            dot2_token,
-            rest,
+            dot2_token: None,
+            rest: None,
         })
     }
 
     #[cfg(feature = "full")]
     fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
         let unsafe_token: Token![unsafe] = input.parse()?;
 
         let content;
@@ -2572,37 +2506,17 @@ pub(crate) mod parsing {
     }
 
     #[cfg(feature = "full")]
     impl Parse for Arm {
         fn parse(input: ParseStream) -> Result<Arm> {
             let requires_comma;
             Ok(Arm {
                 attrs: input.call(Attribute::parse_outer)?,
-                pat: {
-                    let leading_vert: Option<Token![|]> = input.parse()?;
-                    let pat: Pat = input.parse()?;
-                    if leading_vert.is_some() || input.peek(Token![|]) {
-                        let mut cases = Punctuated::new();
-                        cases.push_value(pat);
-                        while input.peek(Token![|]) {
-                            let punct = input.parse()?;
-                            cases.push_punct(punct);
-                            let pat: Pat = input.parse()?;
-                            cases.push_value(pat);
-                        }
-                        Pat::Or(PatOr {
-                            attrs: Vec::new(),
-                            leading_vert,
-                            cases,
-                        })
-                    } else {
-                        pat
-                    }
-                },
+                pat: pat::parsing::multi_pat_with_leading_vert(input)?,
                 guard: {
                     if input.peek(Token![if]) {
                         let if_token: Token![if] = input.parse()?;
                         let guard: Expr = input.parse()?;
                         Some((if_token, Box::new(guard)))
                     } else {
                         None
                     }
@@ -2636,16 +2550,36 @@ pub(crate) mod parsing {
                     span: lit.span(),
                 })
             } else {
                 Err(Error::new(lit.span(), "expected unsuffixed integer"))
             }
         }
     }
 
+    fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
+        let mut float_repr = float.to_string();
+        let trailing_dot = float_repr.ends_with('.');
+        if trailing_dot {
+            float_repr.truncate(float_repr.len() - 1);
+        }
+        for part in float_repr.split('.') {
+            let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
+            let base = mem::replace(e, Expr::__Nonexhaustive);
+            *e = Expr::Field(ExprField {
+                attrs: Vec::new(),
+                base: Box::new(base),
+                dot_token: Token![.](dot_token.span),
+                member: Member::Unnamed(index),
+            });
+            *dot_token = Token![.](float.span());
+        }
+        Ok(!trailing_dot)
+    }
+
     #[cfg(feature = "full")]
     impl Member {
         fn is_named(&self) -> bool {
             match *self {
                 Member::Named(_) => true,
                 Member::Unnamed(_) => false,
             }
         }
--- a/third_party/rust/syn/src/ext.rs
+++ b/third_party/rust/syn/src/ext.rs
@@ -1,27 +1,27 @@
 //! Extension traits to provide parsing methods on foreign types.
 //!
-//! *This module is available if Syn is built with the `"parsing"` feature.*
+//! *This module is available only if Syn is built with the `"parsing"` feature.*
 
 use proc_macro2::Ident;
 
 use crate::parse::{ParseStream, Result};
 
 use crate::buffer::Cursor;
 use crate::parse::Peek;
 use crate::sealed::lookahead;
 use crate::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. It
 /// is implemented only for `proc_macro2::Ident`.
 ///
-/// *This trait is available if Syn is built with the `"parsing"` feature.*
+/// *This trait is available only if Syn is built with the `"parsing"` feature.*
 pub trait IdentExt: Sized + private::Sealed {
     /// Parses any identifier including keywords.
     ///
     /// This is useful when parsing macro input which allows Rust keywords as
     /// identifiers.
     ///
     /// # Example
     ///
@@ -124,12 +124,18 @@ impl lookahead::Sealed for private::Peek
 
 mod private {
     use proc_macro2::Ident;
 
     pub trait Sealed {}
 
     impl Sealed for Ident {}
 
-    #[derive(Copy, Clone)]
     pub struct PeekFn;
     pub struct IdentAny;
+
+    impl Copy for PeekFn {}
+    impl Clone for PeekFn {
+        fn clone(&self) -> Self {
+            *self
+        }
+    }
 }
--- a/third_party/rust/syn/src/file.rs
+++ b/third_party/rust/syn/src/file.rs
@@ -1,14 +1,14 @@
 use super::*;
 
 ast_struct! {
     /// A complete file of Rust source code.
     ///
-    /// *This type is available if Syn is built with the `"full"` feature.*
+    /// *This type is available only 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.
     ///
     /// ```
     /// use std::env;
@@ -32,16 +32,18 @@ ast_struct! {
     ///     };
     ///
     ///     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");
+    ///
+    ///     // Debug impl is available if Syn is built with "extra-traits" feature.
     ///     println!("{:#?}", syntax);
     /// }
     /// ```
     ///
     /// Running with its own source code as input, this program prints output
     /// that begins with:
     ///
     /// ```text
new file mode 100644
--- /dev/null
+++ b/third_party/rust/syn/src/gen/clone.rs
@@ -0,0 +1,2051 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#![allow(clippy::clone_on_copy, clippy::expl_impl_clone_on_copy)]
+use crate::*;
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Abi {
+    fn clone(&self) -> Self {
+        Abi {
+            extern_token: self.extern_token.clone(),
+            name: self.name.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for AngleBracketedGenericArguments {
+    fn clone(&self) -> Self {
+        AngleBracketedGenericArguments {
+            colon2_token: self.colon2_token.clone(),
+            lt_token: self.lt_token.clone(),
+            args: self.args.clone(),
+            gt_token: self.gt_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for Arm {
+    fn clone(&self) -> Self {
+        Arm {
+            attrs: self.attrs.clone(),
+            pat: self.pat.clone(),
+            guard: self.guard.clone(),
+            fat_arrow_token: self.fat_arrow_token.clone(),
+            body: self.body.clone(),
+            comma: self.comma.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Copy for AttrStyle {}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for AttrStyle {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Attribute {
+    fn clone(&self) -> Self {
+        Attribute {
+            pound_token: self.pound_token.clone(),
+            style: self.style.clone(),
+            bracket_token: self.bracket_token.clone(),
+            path: self.path.clone(),
+            tokens: self.tokens.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for BareFnArg {
+    fn clone(&self) -> Self {
+        BareFnArg {
+            attrs: self.attrs.clone(),
+            name: self.name.clone(),
+            ty: self.ty.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Copy for BinOp {}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for BinOp {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Binding {
+    fn clone(&self) -> Self {
+        Binding {
+            ident: self.ident.clone(),
+            eq_token: self.eq_token.clone(),
+            ty: self.ty.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for Block {
+    fn clone(&self) -> Self {
+        Block {
+            brace_token: self.brace_token.clone(),
+            stmts: self.stmts.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for BoundLifetimes {
+    fn clone(&self) -> Self {
+        BoundLifetimes {
+            for_token: self.for_token.clone(),
+            lt_token: self.lt_token.clone(),
+            lifetimes: self.lifetimes.clone(),
+            gt_token: self.gt_token.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ConstParam {
+    fn clone(&self) -> Self {
+        ConstParam {
+            attrs: self.attrs.clone(),
+            const_token: self.const_token.clone(),
+            ident: self.ident.clone(),
+            colon_token: self.colon_token.clone(),
+            ty: self.ty.clone(),
+            eq_token: self.eq_token.clone(),
+            default: self.default.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Constraint {
+    fn clone(&self) -> Self {
+        Constraint {
+            ident: self.ident.clone(),
+            colon_token: self.colon_token.clone(),
+            bounds: self.bounds.clone(),
+        }
+    }
+}
+#[cfg(feature = "derive")]
+impl Clone for Data {
+    fn clone(&self) -> Self {
+        match self {
+            Data::Struct(v0) => Data::Struct(v0.clone()),
+            Data::Enum(v0) => Data::Enum(v0.clone()),
+            Data::Union(v0) => Data::Union(v0.clone()),
+        }
+    }
+}
+#[cfg(feature = "derive")]
+impl Clone for DataEnum {
+    fn clone(&self) -> Self {
+        DataEnum {
+            enum_token: self.enum_token.clone(),
+            brace_token: self.brace_token.clone(),
+            variants: self.variants.clone(),
+        }
+    }
+}
+#[cfg(feature = "derive")]
+impl Clone for DataStruct {
+    fn clone(&self) -> Self {
+        DataStruct {
+            struct_token: self.struct_token.clone(),
+            fields: self.fields.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "derive")]
+impl Clone for DataUnion {
+    fn clone(&self) -> Self {
+        DataUnion {
+            union_token: self.union_token.clone(),
+            fields: self.fields.clone(),
+        }
+    }
+}
+#[cfg(feature = "derive")]
+impl Clone for DeriveInput {
+    fn clone(&self) -> Self {
+        DeriveInput {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            data: self.data.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Expr {
+    fn clone(&self) -> Self {
+        match self {
+            #[cfg(feature = "full")]
+            Expr::Array(v0) => Expr::Array(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Assign(v0) => Expr::Assign(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::AssignOp(v0) => Expr::AssignOp(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Async(v0) => Expr::Async(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Await(v0) => Expr::Await(v0.clone()),
+            Expr::Binary(v0) => Expr::Binary(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Block(v0) => Expr::Block(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Box(v0) => Expr::Box(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Break(v0) => Expr::Break(v0.clone()),
+            Expr::Call(v0) => Expr::Call(v0.clone()),
+            Expr::Cast(v0) => Expr::Cast(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Closure(v0) => Expr::Closure(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Continue(v0) => Expr::Continue(v0.clone()),
+            Expr::Field(v0) => Expr::Field(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::ForLoop(v0) => Expr::ForLoop(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Group(v0) => Expr::Group(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::If(v0) => Expr::If(v0.clone()),
+            Expr::Index(v0) => Expr::Index(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Let(v0) => Expr::Let(v0.clone()),
+            Expr::Lit(v0) => Expr::Lit(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Loop(v0) => Expr::Loop(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Macro(v0) => Expr::Macro(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Match(v0) => Expr::Match(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::MethodCall(v0) => Expr::MethodCall(v0.clone()),
+            Expr::Paren(v0) => Expr::Paren(v0.clone()),
+            Expr::Path(v0) => Expr::Path(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Range(v0) => Expr::Range(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Reference(v0) => Expr::Reference(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Repeat(v0) => Expr::Repeat(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Return(v0) => Expr::Return(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Struct(v0) => Expr::Struct(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Try(v0) => Expr::Try(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::TryBlock(v0) => Expr::TryBlock(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Tuple(v0) => Expr::Tuple(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Type(v0) => Expr::Type(v0.clone()),
+            Expr::Unary(v0) => Expr::Unary(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Unsafe(v0) => Expr::Unsafe(v0.clone()),
+            Expr::Verbatim(v0) => Expr::Verbatim(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::While(v0) => Expr::While(v0.clone()),
+            #[cfg(feature = "full")]
+            Expr::Yield(v0) => Expr::Yield(v0.clone()),
+            _ => unreachable!(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprArray {
+    fn clone(&self) -> Self {
+        ExprArray {
+            attrs: self.attrs.clone(),
+            bracket_token: self.bracket_token.clone(),
+            elems: self.elems.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprAssign {
+    fn clone(&self) -> Self {
+        ExprAssign {
+            attrs: self.attrs.clone(),
+            left: self.left.clone(),
+            eq_token: self.eq_token.clone(),
+            right: self.right.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprAssignOp {
+    fn clone(&self) -> Self {
+        ExprAssignOp {
+            attrs: self.attrs.clone(),
+            left: self.left.clone(),
+            op: self.op.clone(),
+            right: self.right.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprAsync {
+    fn clone(&self) -> Self {
+        ExprAsync {
+            attrs: self.attrs.clone(),
+            async_token: self.async_token.clone(),
+            capture: self.capture.clone(),
+            block: self.block.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprAwait {
+    fn clone(&self) -> Self {
+        ExprAwait {
+            attrs: self.attrs.clone(),
+            base: self.base.clone(),
+            dot_token: self.dot_token.clone(),
+            await_token: self.await_token.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprBinary {
+    fn clone(&self) -> Self {
+        ExprBinary {
+            attrs: self.attrs.clone(),
+            left: self.left.clone(),
+            op: self.op.clone(),
+            right: self.right.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprBlock {
+    fn clone(&self) -> Self {
+        ExprBlock {
+            attrs: self.attrs.clone(),
+            label: self.label.clone(),
+            block: self.block.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprBox {
+    fn clone(&self) -> Self {
+        ExprBox {
+            attrs: self.attrs.clone(),
+            box_token: self.box_token.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprBreak {
+    fn clone(&self) -> Self {
+        ExprBreak {
+            attrs: self.attrs.clone(),
+            break_token: self.break_token.clone(),
+            label: self.label.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprCall {
+    fn clone(&self) -> Self {
+        ExprCall {
+            attrs: self.attrs.clone(),
+            func: self.func.clone(),
+            paren_token: self.paren_token.clone(),
+            args: self.args.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprCast {
+    fn clone(&self) -> Self {
+        ExprCast {
+            attrs: self.attrs.clone(),
+            expr: self.expr.clone(),
+            as_token: self.as_token.clone(),
+            ty: self.ty.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprClosure {
+    fn clone(&self) -> Self {
+        ExprClosure {
+            attrs: self.attrs.clone(),
+            asyncness: self.asyncness.clone(),
+            movability: self.movability.clone(),
+            capture: self.capture.clone(),
+            or1_token: self.or1_token.clone(),
+            inputs: self.inputs.clone(),
+            or2_token: self.or2_token.clone(),
+            output: self.output.clone(),
+            body: self.body.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprContinue {
+    fn clone(&self) -> Self {
+        ExprContinue {
+            attrs: self.attrs.clone(),
+            continue_token: self.continue_token.clone(),
+            label: self.label.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprField {
+    fn clone(&self) -> Self {
+        ExprField {
+            attrs: self.attrs.clone(),
+            base: self.base.clone(),
+            dot_token: self.dot_token.clone(),
+            member: self.member.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprForLoop {
+    fn clone(&self) -> Self {
+        ExprForLoop {
+            attrs: self.attrs.clone(),
+            label: self.label.clone(),
+            for_token: self.for_token.clone(),
+            pat: self.pat.clone(),
+            in_token: self.in_token.clone(),
+            expr: self.expr.clone(),
+            body: self.body.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprGroup {
+    fn clone(&self) -> Self {
+        ExprGroup {
+            attrs: self.attrs.clone(),
+            group_token: self.group_token.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprIf {
+    fn clone(&self) -> Self {
+        ExprIf {
+            attrs: self.attrs.clone(),
+            if_token: self.if_token.clone(),
+            cond: self.cond.clone(),
+            then_branch: self.then_branch.clone(),
+            else_branch: self.else_branch.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprIndex {
+    fn clone(&self) -> Self {
+        ExprIndex {
+            attrs: self.attrs.clone(),
+            expr: self.expr.clone(),
+            bracket_token: self.bracket_token.clone(),
+            index: self.index.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprLet {
+    fn clone(&self) -> Self {
+        ExprLet {
+            attrs: self.attrs.clone(),
+            let_token: self.let_token.clone(),
+            pat: self.pat.clone(),
+            eq_token: self.eq_token.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprLit {
+    fn clone(&self) -> Self {
+        ExprLit {
+            attrs: self.attrs.clone(),
+            lit: self.lit.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprLoop {
+    fn clone(&self) -> Self {
+        ExprLoop {
+            attrs: self.attrs.clone(),
+            label: self.label.clone(),
+            loop_token: self.loop_token.clone(),
+            body: self.body.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprMacro {
+    fn clone(&self) -> Self {
+        ExprMacro {
+            attrs: self.attrs.clone(),
+            mac: self.mac.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprMatch {
+    fn clone(&self) -> Self {
+        ExprMatch {
+            attrs: self.attrs.clone(),
+            match_token: self.match_token.clone(),
+            expr: self.expr.clone(),
+            brace_token: self.brace_token.clone(),
+            arms: self.arms.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprMethodCall {
+    fn clone(&self) -> Self {
+        ExprMethodCall {
+            attrs: self.attrs.clone(),
+            receiver: self.receiver.clone(),
+            dot_token: self.dot_token.clone(),
+            method: self.method.clone(),
+            turbofish: self.turbofish.clone(),
+            paren_token: self.paren_token.clone(),
+            args: self.args.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprParen {
+    fn clone(&self) -> Self {
+        ExprParen {
+            attrs: self.attrs.clone(),
+            paren_token: self.paren_token.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprPath {
+    fn clone(&self) -> Self {
+        ExprPath {
+            attrs: self.attrs.clone(),
+            qself: self.qself.clone(),
+            path: self.path.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprRange {
+    fn clone(&self) -> Self {
+        ExprRange {
+            attrs: self.attrs.clone(),
+            from: self.from.clone(),
+            limits: self.limits.clone(),
+            to: self.to.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprReference {
+    fn clone(&self) -> Self {
+        ExprReference {
+            attrs: self.attrs.clone(),
+            and_token: self.and_token.clone(),
+            raw: self.raw.clone(),
+            mutability: self.mutability.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprRepeat {
+    fn clone(&self) -> Self {
+        ExprRepeat {
+            attrs: self.attrs.clone(),
+            bracket_token: self.bracket_token.clone(),
+            expr: self.expr.clone(),
+            semi_token: self.semi_token.clone(),
+            len: self.len.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprReturn {
+    fn clone(&self) -> Self {
+        ExprReturn {
+            attrs: self.attrs.clone(),
+            return_token: self.return_token.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprStruct {
+    fn clone(&self) -> Self {
+        ExprStruct {
+            attrs: self.attrs.clone(),
+            path: self.path.clone(),
+            brace_token: self.brace_token.clone(),
+            fields: self.fields.clone(),
+            dot2_token: self.dot2_token.clone(),
+            rest: self.rest.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprTry {
+    fn clone(&self) -> Self {
+        ExprTry {
+            attrs: self.attrs.clone(),
+            expr: self.expr.clone(),
+            question_token: self.question_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprTryBlock {
+    fn clone(&self) -> Self {
+        ExprTryBlock {
+            attrs: self.attrs.clone(),
+            try_token: self.try_token.clone(),
+            block: self.block.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprTuple {
+    fn clone(&self) -> Self {
+        ExprTuple {
+            attrs: self.attrs.clone(),
+            paren_token: self.paren_token.clone(),
+            elems: self.elems.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprType {
+    fn clone(&self) -> Self {
+        ExprType {
+            attrs: self.attrs.clone(),
+            expr: self.expr.clone(),
+            colon_token: self.colon_token.clone(),
+            ty: self.ty.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for ExprUnary {
+    fn clone(&self) -> Self {
+        ExprUnary {
+            attrs: self.attrs.clone(),
+            op: self.op.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprUnsafe {
+    fn clone(&self) -> Self {
+        ExprUnsafe {
+            attrs: self.attrs.clone(),
+            unsafe_token: self.unsafe_token.clone(),
+            block: self.block.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprWhile {
+    fn clone(&self) -> Self {
+        ExprWhile {
+            attrs: self.attrs.clone(),
+            label: self.label.clone(),
+            while_token: self.while_token.clone(),
+            cond: self.cond.clone(),
+            body: self.body.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ExprYield {
+    fn clone(&self) -> Self {
+        ExprYield {
+            attrs: self.attrs.clone(),
+            yield_token: self.yield_token.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Field {
+    fn clone(&self) -> Self {
+        Field {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            ident: self.ident.clone(),
+            colon_token: self.colon_token.clone(),
+            ty: self.ty.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for FieldPat {
+    fn clone(&self) -> Self {
+        FieldPat {
+            attrs: self.attrs.clone(),
+            member: self.member.clone(),
+            colon_token: self.colon_token.clone(),
+            pat: self.pat.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for FieldValue {
+    fn clone(&self) -> Self {
+        FieldValue {
+            attrs: self.attrs.clone(),
+            member: self.member.clone(),
+            colon_token: self.colon_token.clone(),
+            expr: self.expr.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Fields {
+    fn clone(&self) -> Self {
+        match self {
+            Fields::Named(v0) => Fields::Named(v0.clone()),
+            Fields::Unnamed(v0) => Fields::Unnamed(v0.clone()),
+            Fields::Unit => Fields::Unit,
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for FieldsNamed {
+    fn clone(&self) -> Self {
+        FieldsNamed {
+            brace_token: self.brace_token.clone(),
+            named: self.named.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for FieldsUnnamed {
+    fn clone(&self) -> Self {
+        FieldsUnnamed {
+            paren_token: self.paren_token.clone(),
+            unnamed: self.unnamed.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for File {
+    fn clone(&self) -> Self {
+        File {
+            shebang: self.shebang.clone(),
+            attrs: self.attrs.clone(),
+            items: self.items.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for FnArg {
+    fn clone(&self) -> Self {
+        match self {
+            FnArg::Receiver(v0) => FnArg::Receiver(v0.clone()),
+            FnArg::Typed(v0) => FnArg::Typed(v0.clone()),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ForeignItem {
+    fn clone(&self) -> Self {
+        match self {
+            ForeignItem::Fn(v0) => ForeignItem::Fn(v0.clone()),
+            ForeignItem::Static(v0) => ForeignItem::Static(v0.clone()),
+            ForeignItem::Type(v0) => ForeignItem::Type(v0.clone()),
+            ForeignItem::Macro(v0) => ForeignItem::Macro(v0.clone()),
+            ForeignItem::Verbatim(v0) => ForeignItem::Verbatim(v0.clone()),
+            _ => unreachable!(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ForeignItemFn {
+    fn clone(&self) -> Self {
+        ForeignItemFn {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            sig: self.sig.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ForeignItemMacro {
+    fn clone(&self) -> Self {
+        ForeignItemMacro {
+            attrs: self.attrs.clone(),
+            mac: self.mac.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ForeignItemStatic {
+    fn clone(&self) -> Self {
+        ForeignItemStatic {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            static_token: self.static_token.clone(),
+            mutability: self.mutability.clone(),
+            ident: self.ident.clone(),
+            colon_token: self.colon_token.clone(),
+            ty: self.ty.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ForeignItemType {
+    fn clone(&self) -> Self {
+        ForeignItemType {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            type_token: self.type_token.clone(),
+            ident: self.ident.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for GenericArgument {
+    fn clone(&self) -> Self {
+        match self {
+            GenericArgument::Lifetime(v0) => GenericArgument::Lifetime(v0.clone()),
+            GenericArgument::Type(v0) => GenericArgument::Type(v0.clone()),
+            GenericArgument::Binding(v0) => GenericArgument::Binding(v0.clone()),
+            GenericArgument::Constraint(v0) => GenericArgument::Constraint(v0.clone()),
+            GenericArgument::Const(v0) => GenericArgument::Const(v0.clone()),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for GenericMethodArgument {
+    fn clone(&self) -> Self {
+        match self {
+            GenericMethodArgument::Type(v0) => GenericMethodArgument::Type(v0.clone()),
+            GenericMethodArgument::Const(v0) => GenericMethodArgument::Const(v0.clone()),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for GenericParam {
+    fn clone(&self) -> Self {
+        match self {
+            GenericParam::Type(v0) => GenericParam::Type(v0.clone()),
+            GenericParam::Lifetime(v0) => GenericParam::Lifetime(v0.clone()),
+            GenericParam::Const(v0) => GenericParam::Const(v0.clone()),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Generics {
+    fn clone(&self) -> Self {
+        Generics {
+            lt_token: self.lt_token.clone(),
+            params: self.params.clone(),
+            gt_token: self.gt_token.clone(),
+            where_clause: self.where_clause.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ImplItem {
+    fn clone(&self) -> Self {
+        match self {
+            ImplItem::Const(v0) => ImplItem::Const(v0.clone()),
+            ImplItem::Method(v0) => ImplItem::Method(v0.clone()),
+            ImplItem::Type(v0) => ImplItem::Type(v0.clone()),
+            ImplItem::Macro(v0) => ImplItem::Macro(v0.clone()),
+            ImplItem::Verbatim(v0) => ImplItem::Verbatim(v0.clone()),
+            _ => unreachable!(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ImplItemConst {
+    fn clone(&self) -> Self {
+        ImplItemConst {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            defaultness: self.defaultness.clone(),
+            const_token: self.const_token.clone(),
+            ident: self.ident.clone(),
+            colon_token: self.colon_token.clone(),
+            ty: self.ty.clone(),
+            eq_token: self.eq_token.clone(),
+            expr: self.expr.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ImplItemMacro {
+    fn clone(&self) -> Self {
+        ImplItemMacro {
+            attrs: self.attrs.clone(),
+            mac: self.mac.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ImplItemMethod {
+    fn clone(&self) -> Self {
+        ImplItemMethod {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            defaultness: self.defaultness.clone(),
+            sig: self.sig.clone(),
+            block: self.block.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ImplItemType {
+    fn clone(&self) -> Self {
+        ImplItemType {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            defaultness: self.defaultness.clone(),
+            type_token: self.type_token.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            eq_token: self.eq_token.clone(),
+            ty: self.ty.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Index {
+    fn clone(&self) -> Self {
+        Index {
+            index: self.index.clone(),
+            span: self.span.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for Item {
+    fn clone(&self) -> Self {
+        match self {
+            Item::Const(v0) => Item::Const(v0.clone()),
+            Item::Enum(v0) => Item::Enum(v0.clone()),
+            Item::ExternCrate(v0) => Item::ExternCrate(v0.clone()),
+            Item::Fn(v0) => Item::Fn(v0.clone()),
+            Item::ForeignMod(v0) => Item::ForeignMod(v0.clone()),
+            Item::Impl(v0) => Item::Impl(v0.clone()),
+            Item::Macro(v0) => Item::Macro(v0.clone()),
+            Item::Macro2(v0) => Item::Macro2(v0.clone()),
+            Item::Mod(v0) => Item::Mod(v0.clone()),
+            Item::Static(v0) => Item::Static(v0.clone()),
+            Item::Struct(v0) => Item::Struct(v0.clone()),
+            Item::Trait(v0) => Item::Trait(v0.clone()),
+            Item::TraitAlias(v0) => Item::TraitAlias(v0.clone()),
+            Item::Type(v0) => Item::Type(v0.clone()),
+            Item::Union(v0) => Item::Union(v0.clone()),
+            Item::Use(v0) => Item::Use(v0.clone()),
+            Item::Verbatim(v0) => Item::Verbatim(v0.clone()),
+            _ => unreachable!(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemConst {
+    fn clone(&self) -> Self {
+        ItemConst {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            const_token: self.const_token.clone(),
+            ident: self.ident.clone(),
+            colon_token: self.colon_token.clone(),
+            ty: self.ty.clone(),
+            eq_token: self.eq_token.clone(),
+            expr: self.expr.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemEnum {
+    fn clone(&self) -> Self {
+        ItemEnum {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            enum_token: self.enum_token.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            brace_token: self.brace_token.clone(),
+            variants: self.variants.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemExternCrate {
+    fn clone(&self) -> Self {
+        ItemExternCrate {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            extern_token: self.extern_token.clone(),
+            crate_token: self.crate_token.clone(),
+            ident: self.ident.clone(),
+            rename: self.rename.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemFn {
+    fn clone(&self) -> Self {
+        ItemFn {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            sig: self.sig.clone(),
+            block: self.block.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemForeignMod {
+    fn clone(&self) -> Self {
+        ItemForeignMod {
+            attrs: self.attrs.clone(),
+            abi: self.abi.clone(),
+            brace_token: self.brace_token.clone(),
+            items: self.items.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemImpl {
+    fn clone(&self) -> Self {
+        ItemImpl {
+            attrs: self.attrs.clone(),
+            defaultness: self.defaultness.clone(),
+            unsafety: self.unsafety.clone(),
+            impl_token: self.impl_token.clone(),
+            generics: self.generics.clone(),
+            trait_: self.trait_.clone(),
+            self_ty: self.self_ty.clone(),
+            brace_token: self.brace_token.clone(),
+            items: self.items.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemMacro {
+    fn clone(&self) -> Self {
+        ItemMacro {
+            attrs: self.attrs.clone(),
+            ident: self.ident.clone(),
+            mac: self.mac.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemMacro2 {
+    fn clone(&self) -> Self {
+        ItemMacro2 {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            macro_token: self.macro_token.clone(),
+            ident: self.ident.clone(),
+            rules: self.rules.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemMod {
+    fn clone(&self) -> Self {
+        ItemMod {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            mod_token: self.mod_token.clone(),
+            ident: self.ident.clone(),
+            content: self.content.clone(),
+            semi: self.semi.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemStatic {
+    fn clone(&self) -> Self {
+        ItemStatic {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            static_token: self.static_token.clone(),
+            mutability: self.mutability.clone(),
+            ident: self.ident.clone(),
+            colon_token: self.colon_token.clone(),
+            ty: self.ty.clone(),
+            eq_token: self.eq_token.clone(),
+            expr: self.expr.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemStruct {
+    fn clone(&self) -> Self {
+        ItemStruct {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            struct_token: self.struct_token.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            fields: self.fields.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemTrait {
+    fn clone(&self) -> Self {
+        ItemTrait {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            unsafety: self.unsafety.clone(),
+            auto_token: self.auto_token.clone(),
+            trait_token: self.trait_token.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            colon_token: self.colon_token.clone(),
+            supertraits: self.supertraits.clone(),
+            brace_token: self.brace_token.clone(),
+            items: self.items.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemTraitAlias {
+    fn clone(&self) -> Self {
+        ItemTraitAlias {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            trait_token: self.trait_token.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            eq_token: self.eq_token.clone(),
+            bounds: self.bounds.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemType {
+    fn clone(&self) -> Self {
+        ItemType {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            type_token: self.type_token.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            eq_token: self.eq_token.clone(),
+            ty: self.ty.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemUnion {
+    fn clone(&self) -> Self {
+        ItemUnion {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            union_token: self.union_token.clone(),
+            ident: self.ident.clone(),
+            generics: self.generics.clone(),
+            fields: self.fields.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for ItemUse {
+    fn clone(&self) -> Self {
+        ItemUse {
+            attrs: self.attrs.clone(),
+            vis: self.vis.clone(),
+            use_token: self.use_token.clone(),
+            leading_colon: self.leading_colon.clone(),
+            tree: self.tree.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for Label {
+    fn clone(&self) -> Self {
+        Label {
+            name: self.name.clone(),
+            colon_token: self.colon_token.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for LifetimeDef {
+    fn clone(&self) -> Self {
+        LifetimeDef {
+            attrs: self.attrs.clone(),
+            lifetime: self.lifetime.clone(),
+            colon_token: self.colon_token.clone(),
+            bounds: self.bounds.clone(),
+        }
+    }
+}
+impl Clone for Lit {
+    fn clone(&self) -> Self {
+        match self {
+            Lit::Str(v0) => Lit::Str(v0.clone()),
+            Lit::ByteStr(v0) => Lit::ByteStr(v0.clone()),
+            Lit::Byte(v0) => Lit::Byte(v0.clone()),
+            Lit::Char(v0) => Lit::Char(v0.clone()),
+            Lit::Int(v0) => Lit::Int(v0.clone()),
+            Lit::Float(v0) => Lit::Float(v0.clone()),
+            Lit::Bool(v0) => Lit::Bool(v0.clone()),
+            Lit::Verbatim(v0) => Lit::Verbatim(v0.clone()),
+        }
+    }
+}
+impl Clone for LitBool {
+    fn clone(&self) -> Self {
+        LitBool {
+            value: self.value.clone(),
+            span: self.span.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for Local {
+    fn clone(&self) -> Self {
+        Local {
+            attrs: self.attrs.clone(),
+            let_token: self.let_token.clone(),
+            pat: self.pat.clone(),
+            init: self.init.clone(),
+            semi_token: self.semi_token.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Macro {
+    fn clone(&self) -> Self {
+        Macro {
+            path: self.path.clone(),
+            bang_token: self.bang_token.clone(),
+            delimiter: self.delimiter.clone(),
+            tokens: self.tokens.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for MacroDelimiter {
+    fn clone(&self) -> Self {
+        match self {
+            MacroDelimiter::Paren(v0) => MacroDelimiter::Paren(v0.clone()),
+            MacroDelimiter::Brace(v0) => MacroDelimiter::Brace(v0.clone()),
+            MacroDelimiter::Bracket(v0) => MacroDelimiter::Bracket(v0.clone()),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Member {
+    fn clone(&self) -> Self {
+        match self {
+            Member::Named(v0) => Member::Named(v0.clone()),
+            Member::Unnamed(v0) => Member::Unnamed(v0.clone()),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for Meta {
+    fn clone(&self) -> Self {
+        match self {
+            Meta::Path(v0) => Meta::Path(v0.clone()),
+            Meta::List(v0) => Meta::List(v0.clone()),
+            Meta::NameValue(v0) => Meta::NameValue(v0.clone()),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for MetaList {
+    fn clone(&self) -> Self {
+        MetaList {
+            path: self.path.clone(),
+            paren_token: self.paren_token.clone(),
+            nested: self.nested.clone(),
+        }
+    }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl Clone for MetaNameValue {
+    fn clone(&self) -> Self {
+        MetaNameValue {
+            path: self.path.clone(),
+            eq_token: self.eq_token.clone(),
+            lit: self.lit.clone(),
+        }
+    }
+}
+#[cfg(feature = "full")]
+impl Clone for MethodTurbofish {
+    fn clone(&self) -> Self {
+        MethodTurbofish {
+            colon2_token: self.colon2_token.clone(),
+            lt_token: sel