up to 78.5.0 auto/th/thunderbird-78.5.0-1
authorJan Palus <atler@pld-linux.org>
Wed, 18 Nov 2020 19:47:12 +0000 (20:47 +0100)
committerJan Palus <atler@pld-linux.org>
Wed, 18 Nov 2020 19:47:12 +0000 (20:47 +0100)
rust-1.47.patch [deleted file]
thunderbird.spec

diff --git a/rust-1.47.patch b/rust-1.47.patch
deleted file mode 100644 (file)
index 65441a1..0000000
+++ /dev/null
@@ -1,35276 +0,0 @@
-
-# HG changeset patch
-# User Emilio Cobos Álvarez <emilio@crisal.io>
-# Date 1599584448 0
-# Node ID 85c38ea4d34969797eb5d24265cd90cc6841e6ae
-# Parent  5aa243a2fe9d77578dd95ce3ab3a2aa6c1e92604
-Bug 1663715 - Update syn and proc-macro2 so that Firefox can build on Rust nightly again. r=froydnj, a=RyanVM
-
-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
-
-diff --git a/Cargo.lock b/Cargo.lock
---- a/Cargo.lock
-+++ b/Cargo.lock
-@@ -3712,19 +3712,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"
-@@ -4642,19 +4642,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"
-diff --git a/third_party/rust/proc-macro2/.cargo-checksum.json b/third_party/rust/proc-macro2/.cargo-checksum.json
---- 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
-diff --git a/third_party/rust/proc-macro2/Cargo.toml b/third_party/rust/proc-macro2/Cargo.toml
---- 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"
-diff --git a/third_party/rust/proc-macro2/README.md b/third_party/rust/proc-macro2/README.md
---- 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
-diff --git a/third_party/rust/proc-macro2/build.rs b/third_party/rust/proc-macro2/build.rs
---- 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 {
-diff --git a/third_party/rust/proc-macro2/src/detection.rs b/third_party/rust/proc-macro2/src/detection.rs
-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");
-+    }
-+}
-diff --git a/third_party/rust/proc-macro2/src/fallback.rs b/third_party/rust/proc-macro2/src/fallback.rs
---- 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))
--    )
--));
-diff --git a/third_party/rust/proc-macro2/src/lib.rs b/third_party/rust/proc-macro2/src/lib.rs
---- 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 {
-diff --git a/third_party/rust/proc-macro2/src/parse.rs b/third_party/rust/proc-macro2/src/parse.rs
-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)
-+}
-diff --git a/third_party/rust/proc-macro2/src/strnom.rs b/third_party/rust/proc-macro2/src/strnom.rs
-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)
--    };
--}
-diff --git a/third_party/rust/proc-macro2/src/wrapper.rs b/third_party/rust/proc-macro2/src/wrapper.rs
---- 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),
-         }
-     }
- }
-diff --git a/third_party/rust/proc-macro2/tests/comments.rs b/third_party/rust/proc-macro2/tests/comments.rs
-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();
-+}
-diff --git a/third_party/rust/proc-macro2/tests/test.rs b/third_party/rust/proc-macro2/tests/test.rs
---- 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);
-+            }
-+        }
-+    }
-+}
-diff --git a/third_party/rust/proc-macro2/tests/test_fmt.rs b/third_party/rust/proc-macro2/tests/test_fmt.rs
-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());
-+}
-diff --git a/third_party/rust/syn/.cargo-checksum.json b/third_party/rust/syn/.cargo-checksum.json
---- 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
-diff --git a/third_party/rust/syn/Cargo.toml b/third_party/rust/syn/Cargo.toml
---- 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"
-diff --git a/third_party/rust/syn/README.md b/third_party/rust/syn/README.md
---- 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.
-diff --git a/third_party/rust/syn/benches/file.rs b/third_party/rust/syn/benches/file.rs
---- 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;
-diff --git a/third_party/rust/syn/benches/rust.rs b/third_party/rust/syn/benches/rust.rs
---- 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(),
-         );
-diff --git a/third_party/rust/syn/build.rs b/third_party/rust/syn/build.rs
---- 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 })
- }
-diff --git a/third_party/rust/syn/src/attr.rs b/third_party/rust/syn/src/attr.rs
---- 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 {
-diff --git a/third_party/rust/syn/src/buffer.rs b/third_party/rust/syn/src/buffer.rs
---- 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() {
-diff --git a/third_party/rust/syn/src/custom_keyword.rs b/third_party/rust/syn/src/custom_keyword.rs
---- 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 {
-diff --git a/third_party/rust/syn/src/custom_punctuation.rs b/third_party/rust/syn/src/custom_punctuation.rs
---- 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)*)
--    };
--}
-diff --git a/third_party/rust/syn/src/data.rs b/third_party/rust/syn/src/data.rs
---- 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;
-diff --git a/third_party/rust/syn/src/derive.rs b/third_party/rust/syn/src/derive.rs
---- 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")]
-diff --git a/third_party/rust/syn/src/discouraged.rs b/third_party/rust/syn/src/discouraged.rs
---- 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()) })
-     }
- }
-diff --git a/third_party/rust/syn/src/error.rs b/third_party/rust/syn/src/error.rs
---- 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);
-+        }
-+    }
-+}
-diff --git a/third_party/rust/syn/src/expr.rs b/third_party/rust/syn/src/expr.rs
---- 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,
-             }
-         }
-diff --git a/third_party/rust/syn/src/ext.rs b/third_party/rust/syn/src/ext.rs
---- 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
-+        }
-+    }
- }
-diff --git a/third_party/rust/syn/src/file.rs b/third_party/rust/syn/src/file.rs
---- 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
-diff --git a/third_party/rust/syn/src/gen/clone.rs b/third_party/rust/syn/src/gen/clone.rs
-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 {