diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:00:19 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 05:00:19 +0000 |
commit | 4c795e2dfa1793dcc24e9963a800b6f4f84b0da7 (patch) | |
tree | 207634b084b5affe542b82e8e7ef309ecba81fcf | |
parent | cd698d20322edc35e7438a67699a98e6d1588cfc (diff) | |
parent | 8e4d2330aa4e28e0a5bf78fc3f75d615832d46a7 (diff) | |
download | quote-android14-mainline-extservices-release.tar.gz |
Snap for 10453563 from 8e4d2330aa4e28e0a5bf78fc3f75d615832d46a7 to mainline-extservices-releaseaml_ext_341716000aml_ext_341620040aml_ext_341518010aml_ext_341414010aml_ext_341317010aml_ext_341131030aml_ext_341027030android14-mainline-extservices-release
Change-Id: I1f1b7a31e522fc768d786447bdf54462ae3c04b7
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | .github/workflows/ci.yml | 42 | ||||
-rw-r--r-- | Android.bp | 4 | ||||
-rw-r--r-- | Cargo.toml | 17 | ||||
-rw-r--r-- | Cargo.toml.orig | 20 | ||||
-rw-r--r-- | LICENSE-MIT | 2 | ||||
-rw-r--r-- | METADATA | 14 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | TEST_MAPPING | 152 | ||||
-rw-r--r-- | build.rs | 38 | ||||
-rw-r--r-- | src/ext.rs | 4 | ||||
-rw-r--r-- | src/format.rs | 11 | ||||
-rw-r--r-- | src/ident_fragment.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 559 | ||||
-rw-r--r-- | src/runtime.rs | 64 | ||||
-rw-r--r-- | src/spanned.rs | 7 | ||||
-rw-r--r-- | src/to_tokens.rs | 6 | ||||
-rw-r--r-- | tests/compiletest.rs | 1 | ||||
-rw-r--r-- | tests/test.rs | 18 | ||||
-rw-r--r-- | tests/ui/does-not-have-iter-interpolated-dup.stderr | 2 | ||||
-rw-r--r-- | tests/ui/does-not-have-iter-interpolated.stderr | 2 | ||||
-rw-r--r-- | tests/ui/does-not-have-iter-separated.stderr | 2 | ||||
-rw-r--r-- | tests/ui/does-not-have-iter.stderr | 2 | ||||
-rw-r--r-- | tests/ui/not-quotable.rs | 2 | ||||
-rw-r--r-- | tests/ui/not-quotable.stderr | 21 | ||||
-rw-r--r-- | tests/ui/not-repeatable.rs | 2 | ||||
-rw-r--r-- | tests/ui/not-repeatable.stderr | 78 |
27 files changed, 596 insertions, 482 deletions
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 @@ on: pull_request: schedule: [cron: "40 1 * * *"] +permissions: + contents: read + env: - RUSTFLAGS: '-Dwarnings' + RUSTFLAGS: -Dwarnings jobs: test: @@ -15,19 +18,22 @@ jobs: 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 @@ jobs: 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 @@ -41,7 +41,7 @@ rust_library_host { 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 @@ rust_library_host { "libproc_macro2", ], compile_multilib: "first", + product_available: true, + vendor_available: true, } @@ -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" +autobenches = false +categories = ["development-tools::procedural-macro-helpers"] 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 +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 @@ default = ["proc-macro"] # 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 @@ -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 @@ third_party { } 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 } } @@ -3,8 +3,8 @@ Rust Quasi-Quoting [<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" - }, - { - "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" - } - ], - "presubmit-rust": [ - { - "name": "ZipFuseTest" - }, - { - "name": "apkdmverity.test" }, { - "name": "authfs_device_test_src_lib" + "path": "external/rust/crates/virtio-drivers" }, { - "name": "diced_open_dice_cbor_test" + "path": "external/rust/crates/zerocopy" }, { - "name": "diced_sample_inputs_test" + "path": "external/rust/crates/zeroize" }, { - "name": "diced_test" + "path": "external/uwb/src" }, { - "name": "diced_utils_test" + "path": "packages/modules/DnsResolver" }, { - "name": "diced_vendor_test" + "path": "packages/modules/Virtualization/apkdmverity" }, { - "name": "doh_unit_test" + "path": "packages/modules/Virtualization/authfs" }, { - "name": "keystore2_crypto_test_rust" + "path": "packages/modules/Virtualization/avmd" }, { - "name": "keystore2_km_compat_test" + "path": "packages/modules/Virtualization/encryptedstore" }, { - "name": "keystore2_selinux_concurrency_test" + "path": "packages/modules/Virtualization/libs/apexutil" }, { - "name": "keystore2_selinux_test" + "path": "packages/modules/Virtualization/libs/apkverify" }, { - "name": "keystore2_test" + "path": "packages/modules/Virtualization/libs/devicemapper" }, { - "name": "keystore2_test_utils_test" + "path": "packages/modules/Virtualization/microdroid_manager" }, { - "name": "keystore2_vintf_test" + "path": "packages/modules/Virtualization/virtualizationmanager" }, { - "name": "legacykeystore_test" + "path": "packages/modules/Virtualization/vm" }, { - "name": "libapkverify.integration_test" + "path": "packages/modules/Virtualization/zipfuse" }, { - "name": "libapkverify.test" + "path": "system/keymint/derive" }, { - "name": "libcert_request_validator_tests" + "path": "system/keymint/hal" }, { - "name": "libidsig.test" + "path": "system/security/diced" }, { - "name": "librustutils_test" + "path": "system/security/keystore2" }, { - "name": "microdroid_manager_test" + "path": "system/security/keystore2/legacykeystore" }, { - "name": "rustBinderTest" + "path": "system/security/keystore2/selinux" }, { - "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 }) +} @@ -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 { 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 @@ macro_rules! format_ident_impl { }; ([$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!`. /// @@ -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 @@ pub mod spanned; /// } /// ``` /// -/// 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 @@ pub mod spanned; /// # } /// # } /// ``` +#[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 @@ macro_rules! quote { /// 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 @@ macro_rules! quote_spanned { #[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 { 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 @@ macro_rules! pounded_var_names_with_context { #[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 @@ macro_rules! quote_bind_next_or_break { }; } +// 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 @@ macro_rules! quote_each_token { (@ @ $($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 @@ macro_rules! quote_each_token_spanned { (@ @ $($tts)* @ @ @ @) (@ $($tts)* @ @ @ @ @) ($($tts)* @ @ @ @ @ @) - ); + } }; } +// See the explanation on quote_each_token. #[macro_export] #[doc(hidden)] macro_rules! quote_tokens_with_context { @@ -710,11 +837,12 @@ macro_rules! quote_tokens_with_context { ($($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 @@ macro_rules! quote_tokens_with_context_spanned { ($($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 @@ macro_rules! quote_token_with_context { // 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 @@ macro_rules! quote_token_with_context_spanned { ($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 @@ macro_rules! quote_token_with_context_spanned { 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 @@ macro_rules! quote_token_with_context_spanned { $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 @@ macro_rules! quote_token { ); }; - ($tokens:ident [ $($inner:tt)* ]) => { + ([ $($inner:tt)* ] $tokens:ident) => { $crate::__private::push_group( &mut $tokens, $crate::__private::Delimiter::Bracket, @@ -878,7 +1016,7 @@ macro_rules! quote_token { ); }; - ($tokens:ident { $($inner:tt)* }) => { + ({ $($inner:tt)* } $tokens:ident) => { $crate::__private::push_group( &mut $tokens, $crate::__private::Delimiter::Brace, @@ -886,203 +1024,204 @@ macro_rules! quote_token { ); }; - ($tokens:ident +) => { + (# $tokens:ident) => { + $crate::__private::push_pound(&mut $tokens); + }; + + (, $tokens:ident) => { + $crate::__private::push_comma(&mut $tokens); + }; + + (. $tokens:ident) => { + $crate::__private::push_dot(&mut $tokens); + }; + + (; $tokens:ident) => { + $crate::__private::push_semi(&mut $tokens); + }; + + (: $tokens:ident) => { + $crate::__private::push_colon(&mut $tokens); + }; + + (+ $tokens:ident) => { $crate::__private::push_add(&mut $tokens); }; - ($tokens:ident +=) => { + (+= $tokens:ident) => { $crate::__private::push_add_eq(&mut $tokens); }; - ($tokens:ident &) => { + (& $tokens:ident) => { $crate::__private::push_and(&mut $tokens); }; - ($tokens:ident &&) => { + (&& $tokens:ident) => { $crate::__private::push_and_and(&mut $tokens); }; - ($tokens:ident &=) => { + (&= $tokens:ident) => { $crate::__private::push_and_eq(&mut $tokens); }; - ($tokens:ident @) => { + (@ $tokens:ident) => { $crate::__private::push_at(&mut $tokens); }; - ($tokens:ident !) => { + (! $tokens:ident) => { $crate::__private::push_bang(&mut $tokens); }; - ($tokens:ident ^) => { + (^ $tokens:ident) => { $crate::__private::push_caret(&mut $tokens); }; - ($tokens:ident ^=) => { + (^= $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 /) => { + (/ $tokens:ident) => { $crate::__private::push_div(&mut $tokens); }; - ($tokens:ident /=) => { + (/= $tokens:ident) => { $crate::__private::push_div_eq(&mut $tokens); }; - ($tokens:ident .) => { - $crate::__private::push_dot(&mut $tokens); - }; - - ($tokens:ident ..) => { + (.. $tokens:ident) => { $crate::__private::push_dot2(&mut $tokens); }; - ($tokens:ident ...) => { + (... $tokens:ident) => { $crate::__private::push_dot3(&mut $tokens); }; - ($tokens:ident ..=) => { + (..= $tokens:ident) => { $crate::__private::push_dot_dot_eq(&mut $tokens); }; - ($tokens:ident =) => { + (= $tokens:ident) => { $crate::__private::push_eq(&mut $tokens); }; - ($tokens:ident ==) => { + (== $tokens:ident) => { $crate::__private::push_eq_eq(&mut $tokens); }; - ($tokens:ident >=) => { + (>= $tokens:ident) => { $crate::__private::push_ge(&mut $tokens); }; - ($tokens:ident >) => { + (> $tokens:ident) => { $crate::__private::push_gt(&mut $tokens); }; - ($tokens:ident <=) => { + (<= $tokens:ident) => { $crate::__private::push_le(&mut $tokens); }; - ($tokens:ident <) => { + (< $tokens:ident) => { $crate::__private::push_lt(&mut $tokens); }; - ($tokens:ident *=) => { + (*= $tokens:ident) => { $crate::__private::push_mul_eq(&mut $tokens); }; - ($tokens:ident !=) => { + (!= $tokens:ident) => { $crate::__private::push_ne(&mut $tokens); }; - ($tokens:ident |) => { + (| $tokens:ident) => { $crate::__private::push_or(&mut $tokens); }; - ($tokens:ident |=) => { + (|= $tokens:ident) => { $crate::__private::push_or_eq(&mut $tokens); }; - ($tokens:ident ||) => { + (|| $tokens:ident) => { $crate::__private::push_or_or(&mut $tokens); }; - ($tokens:ident #) => { - $crate::__private::push_pound(&mut $tokens); - }; - - ($tokens:ident ?) => { + (? $tokens:ident) => { $crate::__private::push_question(&mut $tokens); }; - ($tokens:ident ->) => { + (-> $tokens:ident) => { $crate::__private::push_rarrow(&mut $tokens); }; - ($tokens:ident <-) => { + (<- $tokens:ident) => { $crate::__private::push_larrow(&mut $tokens); }; - ($tokens:ident %) => { + (% $tokens:ident) => { $crate::__private::push_rem(&mut $tokens); }; - ($tokens:ident %=) => { + (%= $tokens:ident) => { $crate::__private::push_rem_eq(&mut $tokens); }; - ($tokens:ident =>) => { + (=> $tokens:ident) => { $crate::__private::push_fat_arrow(&mut $tokens); }; - ($tokens:ident ;) => { - $crate::__private::push_semi(&mut $tokens); - }; - - ($tokens:ident <<) => { + (<< $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 @@ macro_rules! quote_token_spanned { ); }; - ($tokens:ident $span:ident [ $($inner:tt)* ]) => { + ([ $($inner:tt)* ] $tokens:ident $span:ident) => { $crate::__private::push_group_spanned( &mut $tokens, $span, @@ -1100,7 +1239,7 @@ macro_rules! quote_token_spanned { ); }; - ($tokens:ident $span:ident { $($inner:tt)* }) => { + ({ $($inner:tt)* } $tokens:ident $span:ident) => { $crate::__private::push_group_spanned( &mut $tokens, $span, @@ -1109,195 +1248,187 @@ macro_rules! quote_token_spanned { ); }; - ($tokens:ident $span:ident +) => { + (# $tokens:ident $span:ident) => { + $crate::__private::push_pound_spanned(&mut $tokens, $span); + }; + + (, $tokens:ident $span:ident) => { + $crate::__private::push_comma_spanned(&mut $tokens, $span); + }; + + (. $tokens:ident $span:ident) => { + $crate::__private::push_dot_spanned(&mut $tokens, $span); + }; + + (; $tokens:ident $span:ident) => { + $crate::__private::push_semi_spanned(&mut $tokens, $span); + }; + + (: $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 +=) => { + (+= $tokens:ident $span:ident) => { $crate::__private::push_add_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident &) => { + (& $tokens:ident $span:ident) => { $crate::__private::push_and_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident &&) => { + (&& $tokens:ident $span:ident) => { $crate::__private::push_and_and_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident &=) => { + (&= $tokens:ident $span:ident) => { $crate::__private::push_and_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident @) => { + (@ $tokens:ident $span:ident) => { $crate::__private::push_at_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident !) => { + (! $tokens:ident $span:ident) => { $crate::__private::push_bang_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ^) => { + (^ $tokens:ident $span:ident) => { $crate::__private::push_caret_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ^=) => { + (^= $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 /) => { + (/ $tokens:ident $span:ident) => { $crate::__private::push_div_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident /=) => { + (/= $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 ..) => { + (.. $tokens:ident $span:ident) => { $crate::__private::push_dot2_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ...) => { + (... $tokens:ident $span:ident) => { $crate::__private::push_dot3_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ..=) => { + (..= $tokens:ident $span:ident) => { $crate::__private::push_dot_dot_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident =) => { + (= $tokens:ident $span:ident) => { $crate::__private::push_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ==) => { + (== $tokens:ident $span:ident) => { $crate::__private::push_eq_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident >=) => { + (>= $tokens:ident $span:ident) => { $crate::__private::push_ge_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident >) => { + (> $tokens:ident $span:ident) => { $crate::__private::push_gt_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident <=) => { + (<= $tokens:ident $span:ident) => { $crate::__private::push_le_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident <) => { + (< $tokens:ident $span:ident) => { $crate::__private::push_lt_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident *=) => { + (*= $tokens:ident $span:ident) => { $crate::__private::push_mul_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident !=) => { + (!= $tokens:ident $span:ident) => { $crate::__private::push_ne_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident |) => { + (| $tokens:ident $span:ident) => { $crate::__private::push_or_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident |=) => { + (|= $tokens:ident $span:ident) => { $crate::__private::push_or_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ||) => { + (|| $tokens:ident $span:ident) => { $crate::__private::push_or_or_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident #) => { - $crate::__private::push_pound_spanned(&mut $tokens, $span); - }; - - ($tokens:ident $span:ident ?) => { + (? $tokens:ident $span:ident) => { $crate::__private::push_question_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ->) => { + (-> $tokens:ident $span:ident) => { $crate::__private::push_rarrow_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident <-) => { + (<- $tokens:ident $span:ident) => { $crate::__private::push_larrow_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident %) => { + (% $tokens:ident $span:ident) => { $crate::__private::push_rem_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident %=) => { + (%= $tokens:ident $span:ident) => { $crate::__private::push_rem_eq_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident =>) => { + (=> $tokens:ident $span:ident) => { $crate::__private::push_fat_arrow_spanned(&mut $tokens, $span); }; - ($tokens:ident $span:ident ;) => { - $crate::__private::push_semi_spanned(&mut $tokens, $span); - }; - - ($tokens:ident $span:ident <<) => { + (<< $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 @@ pub mod ext { 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 @@ fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree { } 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 @@ pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) { // 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; - } - - // 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; - } +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) } - - 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 @@ impl<T: ?Sized + ToTokens> Spanned for T { } 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,11 +1,9 @@ use super::TokenStreamExt; - +use core::iter; +use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree}; use std::borrow::Cow; -use std::iter; use std::rc::Rc; -use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree}; - /// Types that can be interpolated inside a `quote!` invocation. /// /// [`quote!`]: macro.quote.html 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 @@ fn test_integer() { #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 @@ fn test_floating() { #[test] fn test_char() { - let zero = '\0'; + let zero = '\u{1}'; let pound = '#'; let quote = '"'; let apost = '\''; @@ -210,23 +210,23 @@ fn test_char() { 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 @@ error[E0308]: mismatched types | 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 @@ error[E0308]: mismatched types | 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 @@ error[E0308]: mismatched types | 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 @@ error[E0308]: mismatched types | 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 @@ use std::net::Ipv4Addr; 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 @@ struct Ipv4Addr; 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) |