Snap for 10453563 from 8e4d2330aa4e28e0a5bf78fc3f75d615832d46a7 to mainline-uwb-release

Change-Id: I28aa5b529c5d4a29b95b4202a10feeae271e5d9a
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index a0fb259..88ac651 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "278057d0d2e59c7de95d79d42e4934783d013e83"
+    "sha1": "550af67f9e0be89897902031f153fb3d40360017"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b7f0028..5e67515 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,8 +5,11 @@
   pull_request:
   schedule: [cron: "40 1 * * *"]
 
+permissions:
+  contents: read
+
 env:
-  RUSTFLAGS: '-Dwarnings'
+  RUSTFLAGS: -Dwarnings
 
 jobs:
   test:
@@ -15,19 +18,22 @@
     strategy:
       fail-fast: false
       matrix:
-        rust: [stable, beta, 1.36.0]
+        rust: [stable, beta, 1.56.0]
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/rust-toolchain@master
         with:
           toolchain: ${{matrix.rust}}
+          components: rust-src
       - run: cargo test
 
   nightly:
     name: Rust nightly
     runs-on: ubuntu-latest
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/rust-toolchain@nightly
         with:
           components: rust-src
@@ -38,25 +44,43 @@
   msrv:
     name: Rust 1.31.0
     runs-on: ubuntu-latest
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/rust-toolchain@1.31.0
+        with:
+          components: rust-src
       - run: cargo check
 
   clippy:
     name: Clippy
     runs-on: ubuntu-latest
     if: github.event_name != 'pull_request'
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
-      - uses: dtolnay/rust-toolchain@clippy
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@nightly
+        with:
+          components: clippy, rust-src
       - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic
 
+  miri:
+    name: Miri
+    runs-on: ubuntu-latest
+    timeout-minutes: 45
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dtolnay/rust-toolchain@miri
+      - run: cargo miri test
+        env:
+          MIRIFLAGS: -Zmiri-strict-provenance
+
   outdated:
     name: Outdated
     runs-on: ubuntu-latest
     if: github.event_name != 'pull_request'
+    timeout-minutes: 45
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
       - uses: dtolnay/install@cargo-outdated
-      - run: cargo outdated --exit-code 1
+      - run: cargo outdated --workspace --exit-code 1
diff --git a/Android.bp b/Android.bp
index 2ce1823..4709e22 100644
--- a/Android.bp
+++ b/Android.bp
@@ -41,7 +41,7 @@
     name: "libquote",
     crate_name: "quote",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.0.15",
+    cargo_pkg_version: "1.0.23",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
@@ -52,4 +52,6 @@
         "libproc_macro2",
     ],
     compile_multilib: "first",
+    product_available: true,
+    vendor_available: true,
 }
diff --git a/Cargo.toml b/Cargo.toml
index c06ec0c..4d6b326 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,26 +13,35 @@
 edition = "2018"
 rust-version = "1.31"
 name = "quote"
-version = "1.0.15"
+version = "1.0.23"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 autobenches = false
 description = "Quasi-quoting macro quote!(...)"
 documentation = "https://docs.rs/quote/"
 readme = "README.md"
-keywords = ["syn"]
+keywords = [
+    "macros",
+    "syn",
+]
 categories = ["development-tools::procedural-macro-helpers"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/dtolnay/quote"
+
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
+
+[lib]
+doc-scrape-examples = false
+
 [dependencies.proc-macro2]
-version = "1.0.36"
+version = "1.0.40"
 default-features = false
+
 [dev-dependencies.rustversion]
 version = "1.0"
 
 [dev-dependencies.trybuild]
-version = "1.0.52"
+version = "1.0.66"
 features = ["diff"]
 
 [features]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 9dd4c77..f99b48f 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,24 +1,23 @@
 [package]
 name = "quote"
-version = "1.0.15" # don't forget to update html_root_url, version in readme for breaking changes
+version = "1.0.23" # don't forget to update html_root_url, version in readme for breaking changes
 authors = ["David Tolnay <dtolnay@gmail.com>"]
-license = "MIT OR Apache-2.0"
-description = "Quasi-quoting macro quote!(...)"
-repository = "https://github.com/dtolnay/quote"
-documentation = "https://docs.rs/quote/"
-keywords = ["syn"]
-categories = ["development-tools::procedural-macro-helpers"]
-readme = "README.md"
-edition = "2018"
 autobenches = false
+categories = ["development-tools::procedural-macro-helpers"]
+description = "Quasi-quoting macro quote!(...)"
+documentation = "https://docs.rs/quote/"
+edition = "2018"
+keywords = ["macros", "syn"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/quote"
 rust-version = "1.31"
 
 [dependencies]
-proc-macro2 = { version = "1.0.36", default-features = false }
+proc-macro2 = { version = "1.0.40", default-features = false }
 
 [dev-dependencies]
 rustversion = "1.0"
-trybuild = { version = "1.0.52", features = ["diff"] }
+trybuild = { version = "1.0.66", features = ["diff"] }
 
 [features]
 default = ["proc-macro"]
@@ -26,6 +25,9 @@
 # libproc_macro in the rustc compiler.
 proc-macro = ["proc-macro2/proc-macro"]
 
+[lib]
+doc-scrape-examples = false
+
 [workspace]
 members = ["benches"]
 
diff --git a/LICENSE-MIT b/LICENSE-MIT
index 40b8817..31aa793 100644
--- a/LICENSE-MIT
+++ b/LICENSE-MIT
@@ -1,5 +1,3 @@
-Copyright (c) 2016 The Rust Project Developers
-
 Permission is hereby granted, free of charge, to any
 person obtaining a copy of this software and associated
 documentation files (the "Software"), to deal in the
diff --git a/METADATA b/METADATA
index f788fb6..3297eb7 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/quote
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "quote"
 description: "Quasi-quoting macro quote!(...)"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/quote/quote-1.0.15.crate"
+    value: "https://static.crates.io/crates/quote/quote-1.0.23.crate"
   }
-  version: "1.0.15"
+  version: "1.0.23"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 3
-    day: 1
+    year: 2023
+    month: 2
+    day: 6
   }
 }
diff --git a/README.md b/README.md
index 57b2a62..74e99ce 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,8 @@
 
 [<img alt="github" src="https://img.shields.io/badge/github-dtolnay/quote-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/quote)
 [<img alt="crates.io" src="https://img.shields.io/crates/v/quote.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/quote)
-[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-quote-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/quote)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/quote/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/quote/actions?query=branch%3Amaster)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-quote-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/quote)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/quote/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/quote/actions?query=branch%3Amaster)
 
 This crate provides the [`quote!`] macro for turning Rust syntax tree data
 structures into tokens of source code.
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 76a8253..7c46892 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -11,6 +11,9 @@
       "path": "external/rust/crates/argh"
     },
     {
+      "path": "external/rust/crates/async-stream"
+    },
+    {
       "path": "external/rust/crates/base64"
     },
     {
@@ -20,12 +23,30 @@
       "path": "external/rust/crates/bytes"
     },
     {
+      "path": "external/rust/crates/coset"
+    },
+    {
       "path": "external/rust/crates/either"
     },
     {
+      "path": "external/rust/crates/futures-channel"
+    },
+    {
+      "path": "external/rust/crates/futures-executor"
+    },
+    {
+      "path": "external/rust/crates/futures-test"
+    },
+    {
       "path": "external/rust/crates/futures-util"
     },
     {
+      "path": "external/rust/crates/hashbrown"
+    },
+    {
+      "path": "external/rust/crates/hashlink"
+    },
+    {
       "path": "external/rust/crates/jni"
     },
     {
@@ -72,160 +93,75 @@
     },
     {
       "path": "external/rust/crates/url"
-    }
-  ],
-  "presubmit": [
-    {
-      "name": "ZipFuseTest"
     },
     {
-      "name": "apkdmverity.test"
+      "path": "external/rust/crates/virtio-drivers"
     },
     {
-      "name": "authfs_device_test_src_lib"
+      "path": "external/rust/crates/zerocopy"
     },
     {
-      "name": "diced_open_dice_cbor_test"
+      "path": "external/rust/crates/zeroize"
     },
     {
-      "name": "diced_sample_inputs_test"
+      "path": "external/uwb/src"
     },
     {
-      "name": "diced_test"
+      "path": "packages/modules/DnsResolver"
     },
     {
-      "name": "diced_utils_test"
+      "path": "packages/modules/Virtualization/apkdmverity"
     },
     {
-      "name": "diced_vendor_test"
+      "path": "packages/modules/Virtualization/authfs"
     },
     {
-      "name": "doh_unit_test"
+      "path": "packages/modules/Virtualization/avmd"
     },
     {
-      "name": "keystore2_crypto_test_rust"
+      "path": "packages/modules/Virtualization/encryptedstore"
     },
     {
-      "name": "keystore2_km_compat_test"
+      "path": "packages/modules/Virtualization/libs/apexutil"
     },
     {
-      "name": "keystore2_selinux_concurrency_test"
+      "path": "packages/modules/Virtualization/libs/apkverify"
     },
     {
-      "name": "keystore2_selinux_test"
+      "path": "packages/modules/Virtualization/libs/devicemapper"
     },
     {
-      "name": "keystore2_test"
+      "path": "packages/modules/Virtualization/microdroid_manager"
     },
     {
-      "name": "keystore2_test_utils_test"
+      "path": "packages/modules/Virtualization/virtualizationmanager"
     },
     {
-      "name": "keystore2_vintf_test"
+      "path": "packages/modules/Virtualization/vm"
     },
     {
-      "name": "legacykeystore_test"
+      "path": "packages/modules/Virtualization/zipfuse"
     },
     {
-      "name": "libapkverify.integration_test"
+      "path": "system/keymint/derive"
     },
     {
-      "name": "libapkverify.test"
+      "path": "system/keymint/hal"
     },
     {
-      "name": "libcert_request_validator_tests"
+      "path": "system/security/diced"
     },
     {
-      "name": "libidsig.test"
+      "path": "system/security/keystore2"
     },
     {
-      "name": "librustutils_test"
+      "path": "system/security/keystore2/legacykeystore"
     },
     {
-      "name": "microdroid_manager_test"
+      "path": "system/security/keystore2/selinux"
     },
     {
-      "name": "rustBinderTest"
-    },
-    {
-      "name": "virtualizationservice_device_test"
-    }
-  ],
-  "presubmit-rust": [
-    {
-      "name": "ZipFuseTest"
-    },
-    {
-      "name": "apkdmverity.test"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "diced_open_dice_cbor_test"
-    },
-    {
-      "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_test"
-    },
-    {
-      "name": "diced_utils_test"
-    },
-    {
-      "name": "diced_vendor_test"
-    },
-    {
-      "name": "doh_unit_test"
-    },
-    {
-      "name": "keystore2_crypto_test_rust"
-    },
-    {
-      "name": "keystore2_km_compat_test"
-    },
-    {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_selinux_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "keystore2_test_utils_test"
-    },
-    {
-      "name": "keystore2_vintf_test"
-    },
-    {
-      "name": "legacykeystore_test"
-    },
-    {
-      "name": "libapkverify.integration_test"
-    },
-    {
-      "name": "libapkverify.test"
-    },
-    {
-      "name": "libcert_request_validator_tests"
-    },
-    {
-      "name": "libidsig.test"
-    },
-    {
-      "name": "librustutils_test"
-    },
-    {
-      "name": "microdroid_manager_test"
-    },
-    {
-      "name": "rustBinderTest"
-    },
-    {
-      "name": "virtualizationservice_device_test"
+      "path": "system/security/keystore2/src/crypto"
     }
   ]
 }
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..a7e6b2c
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,38 @@
+use std::env;
+use std::process::{self, Command};
+use std::str;
+
+fn main() {
+    println!("cargo:rerun-if-changed=build.rs");
+
+    let version = match rustc_version() {
+        Some(version) => version,
+        None => return,
+    };
+
+    if version.minor < 31 {
+        eprintln!("Minimum supported rustc version is 1.31");
+        process::exit(1);
+    }
+
+    if version.minor < 53 {
+        // https://github.com/rust-lang/rust/issues/43081
+        println!("cargo:rustc-cfg=needs_invalid_span_workaround");
+    }
+}
+
+struct RustcVersion {
+    minor: u32,
+}
+
+fn rustc_version() -> Option<RustcVersion> {
+    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 minor = pieces.next()?.parse().ok()?;
+    Some(RustcVersion { minor })
+}
diff --git a/src/ext.rs b/src/ext.rs
index 9e9b4a5..92c2315 100644
--- a/src/ext.rs
+++ b/src/ext.rs
@@ -1,7 +1,5 @@
 use super::ToTokens;
-
-use std::iter;
-
+use core::iter;
 use proc_macro2::{TokenStream, TokenTree};
 
 /// TokenStream extension trait with methods for appending tokens.
diff --git a/src/format.rs b/src/format.rs
index 5e44b01..3cddbd2 100644
--- a/src/format.rs
+++ b/src/format.rs
@@ -111,14 +111,14 @@
 macro_rules! format_ident {
     ($fmt:expr) => {
         $crate::format_ident_impl!([
-            ::std::option::Option::None,
+            $crate::__private::Option::None,
             $fmt
         ])
     };
 
     ($fmt:expr, $($rest:tt)*) => {
         $crate::format_ident_impl!([
-            ::std::option::Option::None,
+            $crate::__private::Option::None,
             $fmt
         ] $($rest)*)
     };
@@ -129,7 +129,10 @@
 macro_rules! format_ident_impl {
     // Final state
     ([$span:expr, $($fmt:tt)*]) => {
-        $crate::__private::mk_ident(&format!($($fmt)*), $span)
+        $crate::__private::mk_ident(
+            &$crate::__private::format!($($fmt)*),
+            $span,
+        )
     };
 
     // Span argument
@@ -138,7 +141,7 @@
     };
     ([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {
         $crate::format_ident_impl!([
-            ::std::option::Option::Some::<$crate::__private::Span>($span),
+            $crate::__private::Option::Some::<$crate::__private::Span>($span),
             $($fmt)*
         ] $($rest)*)
     };
diff --git a/src/ident_fragment.rs b/src/ident_fragment.rs
index 67e2e33..cf74024 100644
--- a/src/ident_fragment.rs
+++ b/src/ident_fragment.rs
@@ -1,6 +1,6 @@
+use core::fmt;
 use proc_macro2::{Ident, Span};
 use std::borrow::Cow;
-use std::fmt;
 
 /// Specialized formatting trait used by `format_ident!`.
 ///
diff --git a/src/lib.rs b/src/lib.rs
index 02f6532..adc14c5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,7 @@
 //!
 //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
 //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
-//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
 //!
 //! <br>
 //!
@@ -81,7 +81,7 @@
 //! ```
 
 // Quote types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/quote/1.0.15")]
+#![doc(html_root_url = "https://docs.rs/quote/1.0.23")]
 #![allow(
     clippy::doc_markdown,
     clippy::missing_errors_doc,
@@ -389,14 +389,6 @@
 /// }
 /// ```
 ///
-/// Macro calls in a doc attribute are not valid syntax:
-///
-/// ```compile_fail
-/// quote! {
-///     #[doc = concat!("try to interpolate: ", stringify!(#ident))]
-/// }
-/// ```
-///
 /// Instead the best way to build doc comments that involve variables is by
 /// formatting the doc string literal outside of quote.
 ///
@@ -476,14 +468,45 @@
 /// #     }
 /// # }
 /// ```
+#[cfg(doc)]
+#[macro_export]
+macro_rules! quote {
+    ($($tt:tt)*) => {
+        ...
+    };
+}
+
+#[cfg(not(doc))]
 #[macro_export]
 macro_rules! quote {
     () => {
         $crate::__private::TokenStream::new()
     };
+
+    // Special case rule for a single tt, for performance.
+    ($tt:tt) => {{
+        let mut _s = $crate::__private::TokenStream::new();
+        $crate::quote_token!{$tt _s}
+        _s
+    }};
+
+    // Special case rules for two tts, for performance.
+    (# $var:ident) => {{
+        let mut _s = $crate::__private::TokenStream::new();
+        $crate::ToTokens::to_tokens(&$var, &mut _s);
+        _s
+    }};
+    ($tt1:tt $tt2:tt) => {{
+        let mut _s = $crate::__private::TokenStream::new();
+        $crate::quote_token!{$tt1 _s}
+        $crate::quote_token!{$tt2 _s}
+        _s
+    }};
+
+    // Rule for any other number of tokens.
     ($($tt:tt)*) => {{
         let mut _s = $crate::__private::TokenStream::new();
-        $crate::quote_each_token!(_s $($tt)*);
+        $crate::quote_each_token!{_s $($tt)*}
         _s
     }};
 }
@@ -584,16 +607,50 @@
 /// In this example it is important for the where-clause to be spanned with the
 /// line/column information of the user's input type so that error messages are
 /// placed appropriately by the compiler.
+#[cfg(doc)]
+#[macro_export]
+macro_rules! quote_spanned {
+    ($span:expr=> $($tt:tt)*) => {
+        ...
+    };
+}
+
+#[cfg(not(doc))]
 #[macro_export]
 macro_rules! quote_spanned {
     ($span:expr=>) => {{
         let _: $crate::__private::Span = $span;
         $crate::__private::TokenStream::new()
     }};
+
+    // Special case rule for a single tt, for performance.
+    ($span:expr=> $tt:tt) => {{
+        let mut _s = $crate::__private::TokenStream::new();
+        let _span: $crate::__private::Span = $span;
+        $crate::quote_token_spanned!{$tt _s _span}
+        _s
+    }};
+
+    // Special case rules for two tts, for performance.
+    ($span:expr=> # $var:ident) => {{
+        let mut _s = $crate::__private::TokenStream::new();
+        let _: $crate::__private::Span = $span;
+        $crate::ToTokens::to_tokens(&$var, &mut _s);
+        _s
+    }};
+    ($span:expr=> $tt1:tt $tt2:tt) => {{
+        let mut _s = $crate::__private::TokenStream::new();
+        let _span: $crate::__private::Span = $span;
+        $crate::quote_token_spanned!{$tt1 _s _span}
+        $crate::quote_token_spanned!{$tt2 _s _span}
+        _s
+    }};
+
+    // Rule for any other number of tokens.
     ($span:expr=> $($tt:tt)*) => {{
         let mut _s = $crate::__private::TokenStream::new();
         let _span: $crate::__private::Span = $span;
-        $crate::quote_each_token_spanned!(_s _span $($tt)*);
+        $crate::quote_each_token_spanned!{_s _span $($tt)*}
         _s
     }};
 }
@@ -608,10 +665,10 @@
 #[doc(hidden)]
 macro_rules! pounded_var_names {
     ($call:ident! $extra:tt $($tts:tt)*) => {
-        $crate::pounded_var_names_with_context!($call! $extra
+        $crate::pounded_var_names_with_context!{$call! $extra
             (@ $($tts)*)
             ($($tts)* @)
-        )
+        }
     };
 }
 
@@ -620,7 +677,7 @@
 macro_rules! pounded_var_names_with_context {
     ($call:ident! $extra:tt ($($b1:tt)*) ($($curr:tt)*)) => {
         $(
-            $crate::pounded_var_with_context!($call! $extra $b1 $curr);
+            $crate::pounded_var_with_context!{$call! $extra $b1 $curr}
         )*
     };
 }
@@ -629,15 +686,15 @@
 #[doc(hidden)]
 macro_rules! pounded_var_with_context {
     ($call:ident! $extra:tt $b1:tt ( $($inner:tt)* )) => {
-        $crate::pounded_var_names!($call! $extra $($inner)*);
+        $crate::pounded_var_names!{$call! $extra $($inner)*}
     };
 
     ($call:ident! $extra:tt $b1:tt [ $($inner:tt)* ]) => {
-        $crate::pounded_var_names!($call! $extra $($inner)*);
+        $crate::pounded_var_names!{$call! $extra $($inner)*}
     };
 
     ($call:ident! $extra:tt $b1:tt { $($inner:tt)* }) => {
-        $crate::pounded_var_names!($call! $extra $($inner)*);
+        $crate::pounded_var_names!{$call! $extra $($inner)*}
     };
 
     ($call:ident!($($extra:tt)*) # $var:ident) => {
@@ -669,11 +726,79 @@
     };
 }
 
+// The obvious way to write this macro is as a tt muncher. This implementation
+// does something more complex for two reasons.
+//
+//   - With a tt muncher it's easy to hit Rust's built-in recursion_limit, which
+//     this implementation avoids because it isn't tail recursive.
+//
+//   - Compile times for a tt muncher are quadratic relative to the length of
+//     the input. This implementation is linear, so it will be faster
+//     (potentially much faster) for big inputs. However, the constant factors
+//     of this implementation are higher than that of a tt muncher, so it is
+//     somewhat slower than a tt muncher if there are many invocations with
+//     short inputs.
+//
+// An invocation like this:
+//
+//     quote_each_token!(_s a b c d e f g h i j);
+//
+// expands to this:
+//
+//     quote_tokens_with_context!(_s
+//         (@  @  @  @   @   @   a   b   c   d   e   f   g  h  i  j)
+//         (@  @  @  @   @   a   b   c   d   e   f   g   h  i  j  @)
+//         (@  @  @  @   a   b   c   d   e   f   g   h   i  j  @  @)
+//         (@  @  @ (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) @  @  @)
+//         (@  @  a  b   c   d   e   f   g   h   i   j   @  @  @  @)
+//         (@  a  b  c   d   e   f   g   h   i   j   @   @  @  @  @)
+//         (a  b  c  d   e   f   g   h   i   j   @   @   @  @  @  @)
+//     );
+//
+// which gets transposed and expanded to this:
+//
+//     quote_token_with_context!(_s @ @ @  @  @ @ a);
+//     quote_token_with_context!(_s @ @ @  @  @ a b);
+//     quote_token_with_context!(_s @ @ @  @  a b c);
+//     quote_token_with_context!(_s @ @ @ (a) b c d);
+//     quote_token_with_context!(_s @ @ a (b) c d e);
+//     quote_token_with_context!(_s @ a b (c) d e f);
+//     quote_token_with_context!(_s a b c (d) e f g);
+//     quote_token_with_context!(_s b c d (e) f g h);
+//     quote_token_with_context!(_s c d e (f) g h i);
+//     quote_token_with_context!(_s d e f (g) h i j);
+//     quote_token_with_context!(_s e f g (h) i j @);
+//     quote_token_with_context!(_s f g h (i) j @ @);
+//     quote_token_with_context!(_s g h i (j) @ @ @);
+//     quote_token_with_context!(_s h i j  @  @ @ @);
+//     quote_token_with_context!(_s i j @  @  @ @ @);
+//     quote_token_with_context!(_s j @ @  @  @ @ @);
+//
+// Without having used muncher-style recursion, we get one invocation of
+// quote_token_with_context for each original tt, with three tts of context on
+// either side. This is enough for the longest possible interpolation form (a
+// repetition with separator, as in `# (#var) , *`) to be fully represented with
+// the first or last tt in the middle.
+//
+// The middle tt (surrounded by parentheses) is the tt being processed.
+//
+//   - When it is a `#`, quote_token_with_context can do an interpolation. The
+//     interpolation kind will depend on the three subsequent tts.
+//
+//   - When it is within a later part of an interpolation, it can be ignored
+//     because the interpolation has already been done.
+//
+//   - When it is not part of an interpolation it can be pushed as a single
+//     token into the output.
+//
+//   - When the middle token is an unparenthesized `@`, that call is one of the
+//     first 3 or last 3 calls of quote_token_with_context and does not
+//     correspond to one of the original input tokens, so turns into nothing.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_each_token {
     ($tokens:ident $($tts:tt)*) => {
-        $crate::quote_tokens_with_context!($tokens
+        $crate::quote_tokens_with_context!{$tokens
             (@ @ @ @ @ @ $($tts)*)
             (@ @ @ @ @ $($tts)* @)
             (@ @ @ @ $($tts)* @ @)
@@ -681,15 +806,16 @@
             (@ @ $($tts)* @ @ @ @)
             (@ $($tts)* @ @ @ @ @)
             ($($tts)* @ @ @ @ @ @)
-        );
+        }
     };
 }
 
+// See the explanation on quote_each_token.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_each_token_spanned {
     ($tokens:ident $span:ident $($tts:tt)*) => {
-        $crate::quote_tokens_with_context_spanned!($tokens $span
+        $crate::quote_tokens_with_context_spanned!{$tokens $span
             (@ @ @ @ @ @ $($tts)*)
             (@ @ @ @ @ $($tts)* @)
             (@ @ @ @ $($tts)* @ @)
@@ -697,10 +823,11 @@
             (@ @ $($tts)* @ @ @ @)
             (@ $($tts)* @ @ @ @ @)
             ($($tts)* @ @ @ @ @ @)
-        );
+        }
     };
 }
 
+// See the explanation on quote_each_token.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_tokens_with_context {
@@ -710,11 +837,12 @@
         ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*)
     ) => {
         $(
-            $crate::quote_token_with_context!($tokens $b3 $b2 $b1 $curr $a1 $a2 $a3);
+            $crate::quote_token_with_context!{$tokens $b3 $b2 $b1 $curr $a1 $a2 $a3}
         )*
     };
 }
 
+// See the explanation on quote_each_token.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_tokens_with_context_spanned {
@@ -724,20 +852,24 @@
         ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*)
     ) => {
         $(
-            $crate::quote_token_with_context_spanned!($tokens $span $b3 $b2 $b1 $curr $a1 $a2 $a3);
+            $crate::quote_token_with_context_spanned!{$tokens $span $b3 $b2 $b1 $curr $a1 $a2 $a3}
         )*
     };
 }
 
+// See the explanation on quote_each_token.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_token_with_context {
+    // Unparenthesized `@` indicates this call does not correspond to one of the
+    // original input tokens. Ignore it.
     ($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};
 
+    // A repetition with no separator.
     ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
         use $crate::__private::ext::*;
         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
-        $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*);
+        $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
         let _: $crate::__private::HasIterator = has_iter;
         // This is `while true` instead of `loop` because if there are no
         // iterators used inside of this repetition then the body would not
@@ -745,55 +877,60 @@
         // warnings on anything below the loop. We use has_iter to detect and
         // fail to compile when there are no iterators, so here we just work
         // around the unneeded extra warning.
-        //
-        // FIXME: temporariliy working around Clippy regression.
-        // https://github.com/rust-lang/rust-clippy/issues/7768
-        loop {
-            $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*);
-            $crate::quote_each_token!($tokens $($inner)*);
-            if false {
-                break;
-            }
+        while true {
+            $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
+            $crate::quote_each_token!{$tokens $($inner)*}
         }
     }};
+    // ... and one step later.
     ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {};
+    // ... and one step later.
     ($tokens:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {};
 
+    // A repetition with separator.
     ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{
         use $crate::__private::ext::*;
         let mut _i = 0usize;
         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
-        $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*);
+        $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
         let _: $crate::__private::HasIterator = has_iter;
-        loop {
-            $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*);
+        while true {
+            $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
             if _i > 0 {
-                $crate::quote_token!($tokens $sep);
+                $crate::quote_token!{$sep $tokens}
             }
             _i += 1;
-            $crate::quote_each_token!($tokens $($inner)*);
-            if false {
-                break;
-            }
+            $crate::quote_each_token!{$tokens $($inner)*}
         }
     }};
+    // ... and one step later.
     ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {};
+    // ... and one step later.
     ($tokens:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {};
+    // (A special case for `#(var)**`, where the first `*` is treated as the
+    // repetition symbol and the second `*` is treated as an ordinary token.)
     ($tokens:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => {
         // https://github.com/dtolnay/quote/issues/130
-        $crate::quote_token!($tokens *);
+        $crate::quote_token!{* $tokens}
     };
+    // ... and one step later.
     ($tokens:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {};
 
+    // A non-repetition interpolation.
     ($tokens:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => {
         $crate::ToTokens::to_tokens(&$var, &mut $tokens);
     };
+    // ... and one step later.
     ($tokens:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
+
+    // An ordinary token, not part of any interpolation.
     ($tokens:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {
-        $crate::quote_token!($tokens $curr);
+        $crate::quote_token!{$curr $tokens}
     };
 }
 
+// See the explanation on quote_each_token, and on the individual rules of
+// quote_token_with_context.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_token_with_context_spanned {
@@ -802,23 +939,11 @@
     ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
         use $crate::__private::ext::*;
         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
-        $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*);
+        $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
         let _: $crate::__private::HasIterator = has_iter;
-        // This is `while true` instead of `loop` because if there are no
-        // iterators used inside of this repetition then the body would not
-        // contain any `break`, so the compiler would emit unreachable code
-        // warnings on anything below the loop. We use has_iter to detect and
-        // fail to compile when there are no iterators, so here we just work
-        // around the unneeded extra warning.
-        //
-        // FIXME: temporariliy working around Clippy regression.
-        // https://github.com/rust-lang/rust-clippy/issues/7768
-        loop {
-            $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*);
-            $crate::quote_each_token_spanned!($tokens $span $($inner)*);
-            if false {
-                break;
-            }
+        while true {
+            $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
+            $crate::quote_each_token_spanned!{$tokens $span $($inner)*}
         }
     }};
     ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {};
@@ -828,25 +953,22 @@
         use $crate::__private::ext::*;
         let mut _i = 0usize;
         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
-        $crate::pounded_var_names!(quote_bind_into_iter!(has_iter) () $($inner)*);
+        $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
         let _: $crate::__private::HasIterator = has_iter;
-        loop {
-            $crate::pounded_var_names!(quote_bind_next_or_break!() () $($inner)*);
+        while true {
+            $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
             if _i > 0 {
-                $crate::quote_token_spanned!($tokens $span $sep);
+                $crate::quote_token_spanned!{$sep $tokens $span}
             }
             _i += 1;
-            $crate::quote_each_token_spanned!($tokens $span $($inner)*);
-            if false {
-                break;
-            }
+            $crate::quote_each_token_spanned!{$tokens $span $($inner)*}
         }
     }};
     ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {};
     ($tokens:ident $span:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {};
     ($tokens:ident $span:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => {
         // https://github.com/dtolnay/quote/issues/130
-        $crate::quote_token_spanned!($tokens $span *);
+        $crate::quote_token_spanned!{* $tokens $span}
     };
     ($tokens:ident $span:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {};
 
@@ -854,15 +976,31 @@
         $crate::ToTokens::to_tokens(&$var, &mut $tokens);
     };
     ($tokens:ident $span:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
+
     ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {
-        $crate::quote_token_spanned!($tokens $span $curr);
+        $crate::quote_token_spanned!{$curr $tokens $span}
     };
 }
 
+// These rules are ordered by approximate token frequency, at least for the
+// first 10 or so, to improve compile times. Having `ident` first is by far the
+// most important because it's typically 2-3x more common than the next most
+// common token.
+//
+// Separately, we put the token being matched in the very front so that failing
+// rules may fail to match as quickly as possible.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_token {
-    ($tokens:ident ( $($inner:tt)* )) => {
+    ($ident:ident $tokens:ident) => {
+        $crate::__private::push_ident(&mut $tokens, stringify!($ident));
+    };
+
+    (:: $tokens:ident) => {
+        $crate::__private::push_colon2(&mut $tokens);
+    };
+
+    (( $($inner:tt)* ) $tokens:ident) => {
         $crate::__private::push_group(
             &mut $tokens,
             $crate::__private::Delimiter::Parenthesis,
@@ -870,7 +1008,7 @@
         );
     };
 
-    ($tokens:ident [ $($inner:tt)* ]) => {
+    ([ $($inner:tt)* ] $tokens:ident) => {
         $crate::__private::push_group(
             &mut $tokens,
             $crate::__private::Delimiter::Bracket,
@@ -878,7 +1016,7 @@
         );
     };
 
-    ($tokens:ident { $($inner:tt)* }) => {
+    ({ $($inner:tt)* } $tokens:ident) => {
         $crate::__private::push_group(
             &mut $tokens,
             $crate::__private::Delimiter::Brace,
@@ -886,203 +1024,204 @@
         );
     };
 
-    ($tokens:ident +) => {
-        $crate::__private::push_add(&mut $tokens);
-    };
-
-    ($tokens:ident +=) => {
-        $crate::__private::push_add_eq(&mut $tokens);
-    };
-
-    ($tokens:ident &) => {
-        $crate::__private::push_and(&mut $tokens);
-    };
-
-    ($tokens:ident &&) => {
-        $crate::__private::push_and_and(&mut $tokens);
-    };
-
-    ($tokens:ident &=) => {
-        $crate::__private::push_and_eq(&mut $tokens);
-    };
-
-    ($tokens:ident @) => {
-        $crate::__private::push_at(&mut $tokens);
-    };
-
-    ($tokens:ident !) => {
-        $crate::__private::push_bang(&mut $tokens);
-    };
-
-    ($tokens:ident ^) => {
-        $crate::__private::push_caret(&mut $tokens);
-    };
-
-    ($tokens:ident ^=) => {
-        $crate::__private::push_caret_eq(&mut $tokens);
-    };
-
-    ($tokens:ident :) => {
-        $crate::__private::push_colon(&mut $tokens);
-    };
-
-    ($tokens:ident ::) => {
-        $crate::__private::push_colon2(&mut $tokens);
-    };
-
-    ($tokens:ident ,) => {
-        $crate::__private::push_comma(&mut $tokens);
-    };
-
-    ($tokens:ident /) => {
-        $crate::__private::push_div(&mut $tokens);
-    };
-
-    ($tokens:ident /=) => {
-        $crate::__private::push_div_eq(&mut $tokens);
-    };
-
-    ($tokens:ident .) => {
-        $crate::__private::push_dot(&mut $tokens);
-    };
-
-    ($tokens:ident ..) => {
-        $crate::__private::push_dot2(&mut $tokens);
-    };
-
-    ($tokens:ident ...) => {
-        $crate::__private::push_dot3(&mut $tokens);
-    };
-
-    ($tokens:ident ..=) => {
-        $crate::__private::push_dot_dot_eq(&mut $tokens);
-    };
-
-    ($tokens:ident =) => {
-        $crate::__private::push_eq(&mut $tokens);
-    };
-
-    ($tokens:ident ==) => {
-        $crate::__private::push_eq_eq(&mut $tokens);
-    };
-
-    ($tokens:ident >=) => {
-        $crate::__private::push_ge(&mut $tokens);
-    };
-
-    ($tokens:ident >) => {
-        $crate::__private::push_gt(&mut $tokens);
-    };
-
-    ($tokens:ident <=) => {
-        $crate::__private::push_le(&mut $tokens);
-    };
-
-    ($tokens:ident <) => {
-        $crate::__private::push_lt(&mut $tokens);
-    };
-
-    ($tokens:ident *=) => {
-        $crate::__private::push_mul_eq(&mut $tokens);
-    };
-
-    ($tokens:ident !=) => {
-        $crate::__private::push_ne(&mut $tokens);
-    };
-
-    ($tokens:ident |) => {
-        $crate::__private::push_or(&mut $tokens);
-    };
-
-    ($tokens:ident |=) => {
-        $crate::__private::push_or_eq(&mut $tokens);
-    };
-
-    ($tokens:ident ||) => {
-        $crate::__private::push_or_or(&mut $tokens);
-    };
-
-    ($tokens:ident #) => {
+    (# $tokens:ident) => {
         $crate::__private::push_pound(&mut $tokens);
     };
 
-    ($tokens:ident ?) => {
-        $crate::__private::push_question(&mut $tokens);
+    (, $tokens:ident) => {
+        $crate::__private::push_comma(&mut $tokens);
     };
 
-    ($tokens:ident ->) => {
-        $crate::__private::push_rarrow(&mut $tokens);
+    (. $tokens:ident) => {
+        $crate::__private::push_dot(&mut $tokens);
     };
 
-    ($tokens:ident <-) => {
-        $crate::__private::push_larrow(&mut $tokens);
-    };
-
-    ($tokens:ident %) => {
-        $crate::__private::push_rem(&mut $tokens);
-    };
-
-    ($tokens:ident %=) => {
-        $crate::__private::push_rem_eq(&mut $tokens);
-    };
-
-    ($tokens:ident =>) => {
-        $crate::__private::push_fat_arrow(&mut $tokens);
-    };
-
-    ($tokens:ident ;) => {
+    (; $tokens:ident) => {
         $crate::__private::push_semi(&mut $tokens);
     };
 
-    ($tokens:ident <<) => {
+    (: $tokens:ident) => {
+        $crate::__private::push_colon(&mut $tokens);
+    };
+
+    (+ $tokens:ident) => {
+        $crate::__private::push_add(&mut $tokens);
+    };
+
+    (+= $tokens:ident) => {
+        $crate::__private::push_add_eq(&mut $tokens);
+    };
+
+    (& $tokens:ident) => {
+        $crate::__private::push_and(&mut $tokens);
+    };
+
+    (&& $tokens:ident) => {
+        $crate::__private::push_and_and(&mut $tokens);
+    };
+
+    (&= $tokens:ident) => {
+        $crate::__private::push_and_eq(&mut $tokens);
+    };
+
+    (@ $tokens:ident) => {
+        $crate::__private::push_at(&mut $tokens);
+    };
+
+    (! $tokens:ident) => {
+        $crate::__private::push_bang(&mut $tokens);
+    };
+
+    (^ $tokens:ident) => {
+        $crate::__private::push_caret(&mut $tokens);
+    };
+
+    (^= $tokens:ident) => {
+        $crate::__private::push_caret_eq(&mut $tokens);
+    };
+
+    (/ $tokens:ident) => {
+        $crate::__private::push_div(&mut $tokens);
+    };
+
+    (/= $tokens:ident) => {
+        $crate::__private::push_div_eq(&mut $tokens);
+    };
+
+    (.. $tokens:ident) => {
+        $crate::__private::push_dot2(&mut $tokens);
+    };
+
+    (... $tokens:ident) => {
+        $crate::__private::push_dot3(&mut $tokens);
+    };
+
+    (..= $tokens:ident) => {
+        $crate::__private::push_dot_dot_eq(&mut $tokens);
+    };
+
+    (= $tokens:ident) => {
+        $crate::__private::push_eq(&mut $tokens);
+    };
+
+    (== $tokens:ident) => {
+        $crate::__private::push_eq_eq(&mut $tokens);
+    };
+
+    (>= $tokens:ident) => {
+        $crate::__private::push_ge(&mut $tokens);
+    };
+
+    (> $tokens:ident) => {
+        $crate::__private::push_gt(&mut $tokens);
+    };
+
+    (<= $tokens:ident) => {
+        $crate::__private::push_le(&mut $tokens);
+    };
+
+    (< $tokens:ident) => {
+        $crate::__private::push_lt(&mut $tokens);
+    };
+
+    (*= $tokens:ident) => {
+        $crate::__private::push_mul_eq(&mut $tokens);
+    };
+
+    (!= $tokens:ident) => {
+        $crate::__private::push_ne(&mut $tokens);
+    };
+
+    (| $tokens:ident) => {
+        $crate::__private::push_or(&mut $tokens);
+    };
+
+    (|= $tokens:ident) => {
+        $crate::__private::push_or_eq(&mut $tokens);
+    };
+
+    (|| $tokens:ident) => {
+        $crate::__private::push_or_or(&mut $tokens);
+    };
+
+    (? $tokens:ident) => {
+        $crate::__private::push_question(&mut $tokens);
+    };
+
+    (-> $tokens:ident) => {
+        $crate::__private::push_rarrow(&mut $tokens);
+    };
+
+    (<- $tokens:ident) => {
+        $crate::__private::push_larrow(&mut $tokens);
+    };
+
+    (% $tokens:ident) => {
+        $crate::__private::push_rem(&mut $tokens);
+    };
+
+    (%= $tokens:ident) => {
+        $crate::__private::push_rem_eq(&mut $tokens);
+    };
+
+    (=> $tokens:ident) => {
+        $crate::__private::push_fat_arrow(&mut $tokens);
+    };
+
+    (<< $tokens:ident) => {
         $crate::__private::push_shl(&mut $tokens);
     };
 
-    ($tokens:ident <<=) => {
+    (<<= $tokens:ident) => {
         $crate::__private::push_shl_eq(&mut $tokens);
     };
 
-    ($tokens:ident >>) => {
+    (>> $tokens:ident) => {
         $crate::__private::push_shr(&mut $tokens);
     };
 
-    ($tokens:ident >>=) => {
+    (>>= $tokens:ident) => {
         $crate::__private::push_shr_eq(&mut $tokens);
     };
 
-    ($tokens:ident *) => {
+    (* $tokens:ident) => {
         $crate::__private::push_star(&mut $tokens);
     };
 
-    ($tokens:ident -) => {
+    (- $tokens:ident) => {
         $crate::__private::push_sub(&mut $tokens);
     };
 
-    ($tokens:ident -=) => {
+    (-= $tokens:ident) => {
         $crate::__private::push_sub_eq(&mut $tokens);
     };
 
-    ($tokens:ident $ident:ident) => {
-        $crate::__private::push_ident(&mut $tokens, stringify!($ident));
-    };
-
-    ($tokens:ident $lifetime:lifetime) => {
+    ($lifetime:lifetime $tokens:ident) => {
         $crate::__private::push_lifetime(&mut $tokens, stringify!($lifetime));
     };
 
-    ($tokens:ident _) => {
+    (_ $tokens:ident) => {
         $crate::__private::push_underscore(&mut $tokens);
     };
 
-    ($tokens:ident $other:tt) => {
+    ($other:tt $tokens:ident) => {
         $crate::__private::parse(&mut $tokens, stringify!($other));
     };
 }
 
+// See the comment above `quote_token!` about the rule ordering.
 #[macro_export]
 #[doc(hidden)]
 macro_rules! quote_token_spanned {
-    ($tokens:ident $span:ident ( $($inner:tt)* )) => {
+    ($ident:ident $tokens:ident $span:ident) => {
+        $crate::__private::push_ident_spanned(&mut $tokens, $span, stringify!($ident));
+    };
+
+    (:: $tokens:ident $span:ident) => {
+        $crate::__private::push_colon2_spanned(&mut $tokens, $span);
+    };
+
+    (( $($inner:tt)* ) $tokens:ident $span:ident) => {
         $crate::__private::push_group_spanned(
             &mut $tokens,
             $span,
@@ -1091,7 +1230,7 @@
         );
     };
 
-    ($tokens:ident $span:ident [ $($inner:tt)* ]) => {
+    ([ $($inner:tt)* ] $tokens:ident $span:ident) => {
         $crate::__private::push_group_spanned(
             &mut $tokens,
             $span,
@@ -1100,7 +1239,7 @@
         );
     };
 
-    ($tokens:ident $span:ident { $($inner:tt)* }) => {
+    ({ $($inner:tt)* } $tokens:ident $span:ident) => {
         $crate::__private::push_group_spanned(
             &mut $tokens,
             $span,
@@ -1109,195 +1248,187 @@
         );
     };
 
-    ($tokens:ident $span:ident +) => {
-        $crate::__private::push_add_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident +=) => {
-        $crate::__private::push_add_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident &) => {
-        $crate::__private::push_and_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident &&) => {
-        $crate::__private::push_and_and_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident &=) => {
-        $crate::__private::push_and_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident @) => {
-        $crate::__private::push_at_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident !) => {
-        $crate::__private::push_bang_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ^) => {
-        $crate::__private::push_caret_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ^=) => {
-        $crate::__private::push_caret_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident :) => {
-        $crate::__private::push_colon_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ::) => {
-        $crate::__private::push_colon2_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ,) => {
-        $crate::__private::push_comma_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident /) => {
-        $crate::__private::push_div_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident /=) => {
-        $crate::__private::push_div_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident .) => {
-        $crate::__private::push_dot_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ..) => {
-        $crate::__private::push_dot2_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ...) => {
-        $crate::__private::push_dot3_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ..=) => {
-        $crate::__private::push_dot_dot_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident =) => {
-        $crate::__private::push_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ==) => {
-        $crate::__private::push_eq_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident >=) => {
-        $crate::__private::push_ge_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident >) => {
-        $crate::__private::push_gt_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident <=) => {
-        $crate::__private::push_le_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident <) => {
-        $crate::__private::push_lt_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident *=) => {
-        $crate::__private::push_mul_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident !=) => {
-        $crate::__private::push_ne_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident |) => {
-        $crate::__private::push_or_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident |=) => {
-        $crate::__private::push_or_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ||) => {
-        $crate::__private::push_or_or_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident #) => {
+    (# $tokens:ident $span:ident) => {
         $crate::__private::push_pound_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident ?) => {
-        $crate::__private::push_question_spanned(&mut $tokens, $span);
+    (, $tokens:ident $span:ident) => {
+        $crate::__private::push_comma_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident ->) => {
-        $crate::__private::push_rarrow_spanned(&mut $tokens, $span);
+    (. $tokens:ident $span:ident) => {
+        $crate::__private::push_dot_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident <-) => {
-        $crate::__private::push_larrow_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident %) => {
-        $crate::__private::push_rem_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident %=) => {
-        $crate::__private::push_rem_eq_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident =>) => {
-        $crate::__private::push_fat_arrow_spanned(&mut $tokens, $span);
-    };
-
-    ($tokens:ident $span:ident ;) => {
+    (; $tokens:ident $span:ident) => {
         $crate::__private::push_semi_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident <<) => {
+    (: $tokens:ident $span:ident) => {
+        $crate::__private::push_colon_spanned(&mut $tokens, $span);
+    };
+
+    (+ $tokens:ident $span:ident) => {
+        $crate::__private::push_add_spanned(&mut $tokens, $span);
+    };
+
+    (+= $tokens:ident $span:ident) => {
+        $crate::__private::push_add_eq_spanned(&mut $tokens, $span);
+    };
+
+    (& $tokens:ident $span:ident) => {
+        $crate::__private::push_and_spanned(&mut $tokens, $span);
+    };
+
+    (&& $tokens:ident $span:ident) => {
+        $crate::__private::push_and_and_spanned(&mut $tokens, $span);
+    };
+
+    (&= $tokens:ident $span:ident) => {
+        $crate::__private::push_and_eq_spanned(&mut $tokens, $span);
+    };
+
+    (@ $tokens:ident $span:ident) => {
+        $crate::__private::push_at_spanned(&mut $tokens, $span);
+    };
+
+    (! $tokens:ident $span:ident) => {
+        $crate::__private::push_bang_spanned(&mut $tokens, $span);
+    };
+
+    (^ $tokens:ident $span:ident) => {
+        $crate::__private::push_caret_spanned(&mut $tokens, $span);
+    };
+
+    (^= $tokens:ident $span:ident) => {
+        $crate::__private::push_caret_eq_spanned(&mut $tokens, $span);
+    };
+
+    (/ $tokens:ident $span:ident) => {
+        $crate::__private::push_div_spanned(&mut $tokens, $span);
+    };
+
+    (/= $tokens:ident $span:ident) => {
+        $crate::__private::push_div_eq_spanned(&mut $tokens, $span);
+    };
+
+    (.. $tokens:ident $span:ident) => {
+        $crate::__private::push_dot2_spanned(&mut $tokens, $span);
+    };
+
+    (... $tokens:ident $span:ident) => {
+        $crate::__private::push_dot3_spanned(&mut $tokens, $span);
+    };
+
+    (..= $tokens:ident $span:ident) => {
+        $crate::__private::push_dot_dot_eq_spanned(&mut $tokens, $span);
+    };
+
+    (= $tokens:ident $span:ident) => {
+        $crate::__private::push_eq_spanned(&mut $tokens, $span);
+    };
+
+    (== $tokens:ident $span:ident) => {
+        $crate::__private::push_eq_eq_spanned(&mut $tokens, $span);
+    };
+
+    (>= $tokens:ident $span:ident) => {
+        $crate::__private::push_ge_spanned(&mut $tokens, $span);
+    };
+
+    (> $tokens:ident $span:ident) => {
+        $crate::__private::push_gt_spanned(&mut $tokens, $span);
+    };
+
+    (<= $tokens:ident $span:ident) => {
+        $crate::__private::push_le_spanned(&mut $tokens, $span);
+    };
+
+    (< $tokens:ident $span:ident) => {
+        $crate::__private::push_lt_spanned(&mut $tokens, $span);
+    };
+
+    (*= $tokens:ident $span:ident) => {
+        $crate::__private::push_mul_eq_spanned(&mut $tokens, $span);
+    };
+
+    (!= $tokens:ident $span:ident) => {
+        $crate::__private::push_ne_spanned(&mut $tokens, $span);
+    };
+
+    (| $tokens:ident $span:ident) => {
+        $crate::__private::push_or_spanned(&mut $tokens, $span);
+    };
+
+    (|= $tokens:ident $span:ident) => {
+        $crate::__private::push_or_eq_spanned(&mut $tokens, $span);
+    };
+
+    (|| $tokens:ident $span:ident) => {
+        $crate::__private::push_or_or_spanned(&mut $tokens, $span);
+    };
+
+    (? $tokens:ident $span:ident) => {
+        $crate::__private::push_question_spanned(&mut $tokens, $span);
+    };
+
+    (-> $tokens:ident $span:ident) => {
+        $crate::__private::push_rarrow_spanned(&mut $tokens, $span);
+    };
+
+    (<- $tokens:ident $span:ident) => {
+        $crate::__private::push_larrow_spanned(&mut $tokens, $span);
+    };
+
+    (% $tokens:ident $span:ident) => {
+        $crate::__private::push_rem_spanned(&mut $tokens, $span);
+    };
+
+    (%= $tokens:ident $span:ident) => {
+        $crate::__private::push_rem_eq_spanned(&mut $tokens, $span);
+    };
+
+    (=> $tokens:ident $span:ident) => {
+        $crate::__private::push_fat_arrow_spanned(&mut $tokens, $span);
+    };
+
+    (<< $tokens:ident $span:ident) => {
         $crate::__private::push_shl_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident <<=) => {
+    (<<= $tokens:ident $span:ident) => {
         $crate::__private::push_shl_eq_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident >>) => {
+    (>> $tokens:ident $span:ident) => {
         $crate::__private::push_shr_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident >>=) => {
+    (>>= $tokens:ident $span:ident) => {
         $crate::__private::push_shr_eq_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident *) => {
+    (* $tokens:ident $span:ident) => {
         $crate::__private::push_star_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident -) => {
+    (- $tokens:ident $span:ident) => {
         $crate::__private::push_sub_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident -=) => {
+    (-= $tokens:ident $span:ident) => {
         $crate::__private::push_sub_eq_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident $ident:ident) => {
-        $crate::__private::push_ident_spanned(&mut $tokens, $span, stringify!($ident));
-    };
-
-    ($tokens:ident $span:ident $lifetime:lifetime) => {
+    ($lifetime:lifetime $tokens:ident $span:ident) => {
         $crate::__private::push_lifetime_spanned(&mut $tokens, $span, stringify!($lifetime));
     };
 
-    ($tokens:ident $span:ident _) => {
+    (_ $tokens:ident $span:ident) => {
         $crate::__private::push_underscore_spanned(&mut $tokens, $span);
     };
 
-    ($tokens:ident $span:ident $other:tt) => {
+    ($other:tt $tokens:ident $span:ident) => {
         $crate::__private::parse_spanned(&mut $tokens, $span, stringify!($other));
     };
 }
diff --git a/src/runtime.rs b/src/runtime.rs
index 52955cb..f3cdded 100644
--- a/src/runtime.rs
+++ b/src/runtime.rs
@@ -1,9 +1,11 @@
 use crate::{IdentFragment, ToTokens, TokenStreamExt};
-use std::fmt;
-use std::iter;
-use std::ops::BitOr;
+use core::fmt;
+use core::iter;
+use core::ops::BitOr;
 
+pub use core::option::Option;
 pub use proc_macro2::*;
+pub use std::format;
 
 pub struct HasIterator; // True
 pub struct ThereIsNoIteratorInRepetition; // False
@@ -46,8 +48,8 @@
     use super::RepInterp;
     use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
     use crate::ToTokens;
+    use core::slice;
     use std::collections::btree_set::{self, BTreeSet};
-    use std::slice;
 
     /// Extension trait providing the `quote_into_iter` method on iterators.
     pub trait RepIteratorExt: Iterator + Sized {
@@ -205,27 +207,12 @@
 }
 
 pub fn push_ident(tokens: &mut TokenStream, s: &str) {
-    // Optimization over `mk_ident`, as `s` is guaranteed to be a valid ident.
-    //
-    // FIXME: When `Ident::new_raw` becomes stable, this method should be
-    // updated to call it when available.
-    if s.starts_with("r#") {
-        parse(tokens, s);
-    } else {
-        tokens.append(Ident::new(s, Span::call_site()));
-    }
+    let span = Span::call_site();
+    push_ident_spanned(tokens, span, s);
 }
 
 pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
-    // Optimization over `mk_ident`, as `s` is guaranteed to be a valid ident.
-    //
-    // FIXME: When `Ident::new_raw` becomes stable, this method should be
-    // updated to call it when available.
-    if s.starts_with("r#") {
-        parse_spanned(tokens, span, s);
-    } else {
-        tokens.append(Ident::new(s, span));
-    }
+    tokens.append(ident_maybe_raw(s, span));
 }
 
 pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
@@ -392,36 +379,17 @@
 
 // Helper method for constructing identifiers from the `format_ident!` macro,
 // handling `r#` prefixes.
-//
-// Directly parsing the input string may produce a valid identifier,
-// although the input string was invalid, due to ignored characters such as
-// whitespace and comments. Instead, we always create a non-raw identifier
-// to validate that the string is OK, and only parse again if needed.
 pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
     let span = span.unwrap_or_else(Span::call_site);
+    ident_maybe_raw(id, span)
+}
 
-    let is_raw = id.starts_with("r#");
-    let unraw = Ident::new(if is_raw { &id[2..] } else { id }, span);
-    if !is_raw {
-        return unraw;
+fn ident_maybe_raw(id: &str, span: Span) -> Ident {
+    if id.starts_with("r#") {
+        Ident::new_raw(&id[2..], span)
+    } else {
+        Ident::new(id, span)
     }
-
-    // At this point, the identifier is raw, and the unraw-ed version of it was
-    // successfully converted into an identifier. Try to produce a valid raw
-    // identifier by running the `TokenStream` parser, and unwrapping the first
-    // token as an `Ident`.
-    //
-    // FIXME: When `Ident::new_raw` becomes stable, this method should be
-    // updated to call it when available.
-    if let Ok(ts) = id.parse::<TokenStream>() {
-        let mut iter = ts.into_iter();
-        if let (Some(TokenTree::Ident(mut id)), None) = (iter.next(), iter.next()) {
-            id.set_span(span);
-            return id;
-        }
-    }
-
-    panic!("not allowed as a raw identifier: `{}`", id);
 }
 
 // Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
diff --git a/src/spanned.rs b/src/spanned.rs
index 55168bd..f64c8f5 100644
--- a/src/spanned.rs
+++ b/src/spanned.rs
@@ -18,10 +18,11 @@
 }
 
 fn join_spans(tokens: TokenStream) -> Span {
+    #[cfg(not(needs_invalid_span_workaround))]
+    let mut iter = tokens.into_iter().map(|tt| tt.span());
+
+    #[cfg(needs_invalid_span_workaround)]
     let mut iter = tokens.into_iter().filter_map(|tt| {
-        // FIXME: This shouldn't be required, since optimally spans should
-        // never be invalid. This filter_map can probably be removed when
-        // https://github.com/rust-lang/rust/issues/43081 is resolved.
         let span = tt.span();
         let debug = format!("{:?}", span);
         if debug.ends_with("bytes(0..0)") {
diff --git a/src/to_tokens.rs b/src/to_tokens.rs
index dbb8dfc..5748721 100644
--- a/src/to_tokens.rs
+++ b/src/to_tokens.rs
@@ -1,10 +1,8 @@
 use super::TokenStreamExt;
-
-use std::borrow::Cow;
-use std::iter;
-use std::rc::Rc;
-
+use core::iter;
 use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
+use std::borrow::Cow;
+use std::rc::Rc;
 
 /// Types that can be interpolated inside a `quote!` invocation.
 ///
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
index f9aea23..7974a62 100644
--- a/tests/compiletest.rs
+++ b/tests/compiletest.rs
@@ -1,4 +1,5 @@
 #[rustversion::attr(not(nightly), ignore)]
+#[cfg_attr(miri, ignore)]
 #[test]
 fn ui() {
     let t = trybuild::TestCases::new();
diff --git a/tests/test.rs b/tests/test.rs
index 11f8a31..52ec7bc 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,6 +1,5 @@
 #![allow(
-    clippy::blacklisted_name,
-    clippy::let_underscore_drop,
+    clippy::disallowed_names,
     clippy::shadow_unrelated,
     clippy::unseparated_literal_suffix,
     clippy::used_underscore_binding
@@ -180,7 +179,8 @@
         #ii8 #ii16 #ii32 #ii64 #ii128 #iisize
         #uu8 #uu16 #uu32 #uu64 #uu128 #uusize
     };
-    let expected = "1 1i32 1u256 - 1i8 - 1i16 - 1i32 - 1i64 - 1i128 - 1isize 1u8 1u16 1u32 1u64 1u128 1usize";
+    let expected =
+        "1 1i32 1u256 - 1i8 - 1i16 - 1i32 - 1i64 - 1i128 - 1isize 1u8 1u16 1u32 1u64 1u128 1usize";
     assert_eq!(expected, tokens.to_string());
 }
 
@@ -200,7 +200,7 @@
 
 #[test]
 fn test_char() {
-    let zero = '\0';
+    let zero = '\u{1}';
     let pound = '#';
     let quote = '"';
     let apost = '\'';
@@ -210,23 +210,23 @@
     let tokens = quote! {
         #zero #pound #quote #apost #newline #heart
     };
-    let expected = "'\\u{0}' '#' '\"' '\\'' '\\n' '\u{2764}'";
+    let expected = "'\\u{1}' '#' '\"' '\\'' '\\n' '\u{2764}'";
     assert_eq!(expected, tokens.to_string());
 }
 
 #[test]
 fn test_str() {
-    let s = "\0 a 'b \" c";
+    let s = "\u{1} a 'b \" c";
     let tokens = quote!(#s);
-    let expected = "\"\\u{0} a 'b \\\" c\"";
+    let expected = "\"\\u{1} a 'b \\\" c\"";
     assert_eq!(expected, tokens.to_string());
 }
 
 #[test]
 fn test_string() {
-    let s = "\0 a 'b \" c".to_string();
+    let s = "\u{1} a 'b \" c".to_string();
     let tokens = quote!(#s);
-    let expected = "\"\\u{0} a 'b \\\" c\"";
+    let expected = "\"\\u{1} a 'b \\\" c\"";
     assert_eq!(expected, tokens.to_string());
 }
 
diff --git a/tests/ui/does-not-have-iter-interpolated-dup.stderr b/tests/ui/does-not-have-iter-interpolated-dup.stderr
index bcd631d..8087879 100644
--- a/tests/ui/does-not-have-iter-interpolated-dup.stderr
+++ b/tests/ui/does-not-have-iter-interpolated-dup.stderr
@@ -7,4 +7,4 @@
   |     expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
   |     expected due to this
   |
-  = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/does-not-have-iter-interpolated.stderr b/tests/ui/does-not-have-iter-interpolated.stderr
index 799837b..2dcf206 100644
--- a/tests/ui/does-not-have-iter-interpolated.stderr
+++ b/tests/ui/does-not-have-iter-interpolated.stderr
@@ -7,4 +7,4 @@
   |     expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
   |     expected due to this
   |
-  = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/does-not-have-iter-separated.stderr b/tests/ui/does-not-have-iter-separated.stderr
index aa2e693..87a19fe 100644
--- a/tests/ui/does-not-have-iter-separated.stderr
+++ b/tests/ui/does-not-have-iter-separated.stderr
@@ -7,4 +7,4 @@
   |     expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
   |     expected due to this
   |
-  = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/does-not-have-iter.stderr b/tests/ui/does-not-have-iter.stderr
index c2692fe..32aa62d 100644
--- a/tests/ui/does-not-have-iter.stderr
+++ b/tests/ui/does-not-have-iter.stderr
@@ -7,4 +7,4 @@
   |     expected struct `HasIterator`, found struct `ThereIsNoIteratorInRepetition`
   |     expected due to this
   |
-  = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/not-quotable.rs b/tests/ui/not-quotable.rs
index f991c18..220542d 100644
--- a/tests/ui/not-quotable.rs
+++ b/tests/ui/not-quotable.rs
@@ -3,5 +3,5 @@
 
 fn main() {
     let ip = Ipv4Addr::LOCALHOST;
-    let _ = quote! { #ip };
+    _ = quote! { #ip };
 }
diff --git a/tests/ui/not-quotable.stderr b/tests/ui/not-quotable.stderr
index 5dd13bf..c323d99 100644
--- a/tests/ui/not-quotable.stderr
+++ b/tests/ui/not-quotable.stderr
@@ -1,7 +1,20 @@
 error[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied
- --> tests/ui/not-quotable.rs:6:13
+ --> tests/ui/not-quotable.rs:6:9
   |
-6 |     let _ = quote! { #ip };
-  |             ^^^^^^^^^^^^^^ the trait `ToTokens` is not implemented for `Ipv4Addr`
+6 |     _ = quote! { #ip };
+  |         ^^^^^^^^^^^^^^
+  |         |
+  |         the trait `ToTokens` is not implemented for `Ipv4Addr`
+  |         required by a bound introduced by this call
   |
-  = note: this error originates in the macro `$crate::quote_token_with_context` (in Nightly builds, run with -Z macro-backtrace for more info)
+  = help: the following other types implement trait `ToTokens`:
+            &'a T
+            &'a mut T
+            Box<T>
+            Cow<'a, T>
+            Option<T>
+            Rc<T>
+            RepInterp<T>
+            String
+          and 23 others
+  = note: this error originates in the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/not-repeatable.rs b/tests/ui/not-repeatable.rs
index a8f0fe7..c1debf5 100644
--- a/tests/ui/not-repeatable.rs
+++ b/tests/ui/not-repeatable.rs
@@ -4,5 +4,5 @@
 
 fn main() {
     let ip = Ipv4Addr;
-    let _ = quote! { #(#ip)* };
+    _ = quote! { #(#ip)* };
 }
diff --git a/tests/ui/not-repeatable.stderr b/tests/ui/not-repeatable.stderr
index cd5a1e4..264a89f 100644
--- a/tests/ui/not-repeatable.stderr
+++ b/tests/ui/not-repeatable.stderr
@@ -1,47 +1,35 @@
 error[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied
-    --> tests/ui/not-repeatable.rs:7:13
-     |
-3    | struct Ipv4Addr;
-     | ----------------
-     | |
-     | method `quote_into_iter` not found for this
-     | doesn't satisfy `Ipv4Addr: Iterator`
-     | doesn't satisfy `Ipv4Addr: ToTokens`
-     | doesn't satisfy `Ipv4Addr: quote::__private::ext::RepIteratorExt`
-     | doesn't satisfy `Ipv4Addr: quote::__private::ext::RepToTokensExt`
+ --> tests/ui/not-repeatable.rs:7:9
+  |
+3 | struct Ipv4Addr;
+  | ---------------
+  | |
+  | method `quote_into_iter` not found for this struct
+  | doesn't satisfy `Ipv4Addr: Iterator`
+  | doesn't satisfy `Ipv4Addr: ToTokens`
+  | doesn't satisfy `Ipv4Addr: ext::RepIteratorExt`
+  | doesn't satisfy `Ipv4Addr: ext::RepToTokensExt`
 ...
-7    |     let _ = quote! { #(#ip)* };
-     |             ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds
-     |
-     = note: the following trait bounds were not satisfied:
-             `Ipv4Addr: Iterator`
-             which is required by `Ipv4Addr: quote::__private::ext::RepIteratorExt`
-             `&Ipv4Addr: Iterator`
-             which is required by `&Ipv4Addr: quote::__private::ext::RepIteratorExt`
-             `Ipv4Addr: ToTokens`
-             which is required by `Ipv4Addr: quote::__private::ext::RepToTokensExt`
-             `&mut Ipv4Addr: Iterator`
-             which is required by `&mut Ipv4Addr: quote::__private::ext::RepIteratorExt`
-note: the following traits must be implemented
-    --> $RUST/core/src/iter/traits/iterator.rs
-     |
-     | /  pub trait Iterator {
-     | |      /// The type of the elements being iterated over.
-     | |      #[stable(feature = "rust1", since = "1.0.0")]
-     | |      type Item;
-...    |
-     | |      }
-     | |  }
-     | |__^
-     |
-    ::: src/to_tokens.rs
-     |
-     |  / pub trait ToTokens {
-     |  |     /// Write `self` to the given `TokenStream`.
-     |  |     ///
-     |  |     /// The token append methods provided by the [`TokenStreamExt`] extension
-...     |
-     |  |     }
-     |  | }
-     |  |_^
-     = note: this error originates in the macro `$crate::quote_bind_into_iter` (in Nightly builds, run with -Z macro-backtrace for more info)
+7 |     _ = quote! { #(#ip)* };
+  |         ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds
+  |
+  = note: the following trait bounds were not satisfied:
+          `Ipv4Addr: Iterator`
+          which is required by `Ipv4Addr: ext::RepIteratorExt`
+          `&Ipv4Addr: Iterator`
+          which is required by `&Ipv4Addr: ext::RepIteratorExt`
+          `Ipv4Addr: ToTokens`
+          which is required by `Ipv4Addr: ext::RepToTokensExt`
+          `&mut Ipv4Addr: Iterator`
+          which is required by `&mut Ipv4Addr: ext::RepIteratorExt`
+note: the traits `ToTokens` and `Iterator` must be implemented
+ --> src/to_tokens.rs
+  |
+  | pub trait ToTokens {
+  | ^^^^^^^^^^^^^^^^^^
+  |
+ ::: $RUST/core/src/iter/traits/iterator.rs
+  |
+  | pub trait Iterator {
+  | ^^^^^^^^^^^^^^^^^^
+  = note: this error originates in the macro `$crate::quote_bind_into_iter` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)