xref: /linux/rust/quote/lib.rs (revision 784faa8eca8270671e0ed6d9d21f04bbb80fc5f7)
1*ddfa1b27SMiguel Ojeda // SPDX-License-Identifier: Apache-2.0 OR MIT
2*ddfa1b27SMiguel Ojeda 
3a4851eeeSMiguel Ojeda //! [![github]](https://github.com/dtolnay/quote) [![crates-io]](https://crates.io/crates/quote) [![docs-rs]](https://docs.rs/quote)
4a4851eeeSMiguel Ojeda //!
5a4851eeeSMiguel Ojeda //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
6a4851eeeSMiguel Ojeda //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
7a4851eeeSMiguel Ojeda //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
8a4851eeeSMiguel Ojeda //!
9a4851eeeSMiguel Ojeda //! <br>
10a4851eeeSMiguel Ojeda //!
11a4851eeeSMiguel Ojeda //! This crate provides the [`quote!`] macro for turning Rust syntax tree data
12a4851eeeSMiguel Ojeda //! structures into tokens of source code.
13a4851eeeSMiguel Ojeda //!
14a4851eeeSMiguel Ojeda //! Procedural macros in Rust receive a stream of tokens as input, execute
15a4851eeeSMiguel Ojeda //! arbitrary Rust code to determine how to manipulate those tokens, and produce
16a4851eeeSMiguel Ojeda //! a stream of tokens to hand back to the compiler to compile into the caller's
17a4851eeeSMiguel Ojeda //! crate. Quasi-quoting is a solution to one piece of that &mdash; producing
18a4851eeeSMiguel Ojeda //! tokens to return to the compiler.
19a4851eeeSMiguel Ojeda //!
20a4851eeeSMiguel Ojeda //! The idea of quasi-quoting is that we write *code* that we treat as *data*.
21a4851eeeSMiguel Ojeda //! Within the `quote!` macro, we can write what looks like code to our text
22a4851eeeSMiguel Ojeda //! editor or IDE. We get all the benefits of the editor's brace matching,
23a4851eeeSMiguel Ojeda //! syntax highlighting, indentation, and maybe autocompletion. But rather than
24a4851eeeSMiguel Ojeda //! compiling that as code into the current crate, we can treat it as data, pass
25a4851eeeSMiguel Ojeda //! it around, mutate it, and eventually hand it back to the compiler as tokens
26a4851eeeSMiguel Ojeda //! to compile into the macro caller's crate.
27a4851eeeSMiguel Ojeda //!
28a4851eeeSMiguel Ojeda //! This crate is motivated by the procedural macro use case, but is a
29a4851eeeSMiguel Ojeda //! general-purpose Rust quasi-quoting library and is not specific to procedural
30a4851eeeSMiguel Ojeda //! macros.
31a4851eeeSMiguel Ojeda //!
32a4851eeeSMiguel Ojeda //! ```toml
33a4851eeeSMiguel Ojeda //! [dependencies]
34a4851eeeSMiguel Ojeda //! quote = "1.0"
35a4851eeeSMiguel Ojeda //! ```
36a4851eeeSMiguel Ojeda //!
37a4851eeeSMiguel Ojeda //! <br>
38a4851eeeSMiguel Ojeda //!
39a4851eeeSMiguel Ojeda //! # Example
40a4851eeeSMiguel Ojeda //!
41a4851eeeSMiguel Ojeda //! The following quasi-quoted block of code is something you might find in [a]
42a4851eeeSMiguel Ojeda //! procedural macro having to do with data structure serialization. The `#var`
43a4851eeeSMiguel Ojeda //! syntax performs interpolation of runtime variables into the quoted tokens.
44a4851eeeSMiguel Ojeda //! Check out the documentation of the [`quote!`] macro for more detail about
45a4851eeeSMiguel Ojeda //! the syntax. See also the [`quote_spanned!`] macro which is important for
46a4851eeeSMiguel Ojeda //! implementing hygienic procedural macros.
47a4851eeeSMiguel Ojeda //!
48a4851eeeSMiguel Ojeda //! [a]: https://serde.rs/
49a4851eeeSMiguel Ojeda //!
50a4851eeeSMiguel Ojeda //! ```
51a4851eeeSMiguel Ojeda //! # use quote::quote;
52a4851eeeSMiguel Ojeda //! #
53a4851eeeSMiguel Ojeda //! # let generics = "";
54a4851eeeSMiguel Ojeda //! # let where_clause = "";
55a4851eeeSMiguel Ojeda //! # let field_ty = "";
56a4851eeeSMiguel Ojeda //! # let item_ty = "";
57a4851eeeSMiguel Ojeda //! # let path = "";
58a4851eeeSMiguel Ojeda //! # let value = "";
59a4851eeeSMiguel Ojeda //! #
60a4851eeeSMiguel Ojeda //! let tokens = quote! {
61a4851eeeSMiguel Ojeda //!     struct SerializeWith #generics #where_clause {
62a4851eeeSMiguel Ojeda //!         value: &'a #field_ty,
63a4851eeeSMiguel Ojeda //!         phantom: core::marker::PhantomData<#item_ty>,
64a4851eeeSMiguel Ojeda //!     }
65a4851eeeSMiguel Ojeda //!
66a4851eeeSMiguel Ojeda //!     impl #generics serde::Serialize for SerializeWith #generics #where_clause {
67a4851eeeSMiguel Ojeda //!         fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68a4851eeeSMiguel Ojeda //!         where
69a4851eeeSMiguel Ojeda //!             S: serde::Serializer,
70a4851eeeSMiguel Ojeda //!         {
71a4851eeeSMiguel Ojeda //!             #path(self.value, serializer)
72a4851eeeSMiguel Ojeda //!         }
73a4851eeeSMiguel Ojeda //!     }
74a4851eeeSMiguel Ojeda //!
75a4851eeeSMiguel Ojeda //!     SerializeWith {
76a4851eeeSMiguel Ojeda //!         value: #value,
77a4851eeeSMiguel Ojeda //!         phantom: core::marker::PhantomData::<#item_ty>,
78a4851eeeSMiguel Ojeda //!     }
79a4851eeeSMiguel Ojeda //! };
80a4851eeeSMiguel Ojeda //! ```
81a4851eeeSMiguel Ojeda //!
82a4851eeeSMiguel Ojeda //! <br>
83a4851eeeSMiguel Ojeda //!
84a4851eeeSMiguel Ojeda //! # Non-macro code generators
85a4851eeeSMiguel Ojeda //!
86a4851eeeSMiguel Ojeda //! When using `quote` in a build.rs or main.rs and writing the output out to a
87a4851eeeSMiguel Ojeda //! file, consider having the code generator pass the tokens through
88a4851eeeSMiguel Ojeda //! [prettyplease] before writing. This way if an error occurs in the generated
89a4851eeeSMiguel Ojeda //! code it is convenient for a human to read and debug.
90a4851eeeSMiguel Ojeda //!
91a4851eeeSMiguel Ojeda //! [prettyplease]: https://github.com/dtolnay/prettyplease
92a4851eeeSMiguel Ojeda 
93a4851eeeSMiguel Ojeda // Quote types in rustdoc of other crates get linked to here.
94a4851eeeSMiguel Ojeda #![doc(html_root_url = "https://docs.rs/quote/1.0.40")]
95a4851eeeSMiguel Ojeda #![allow(
96a4851eeeSMiguel Ojeda     clippy::doc_markdown,
97a4851eeeSMiguel Ojeda     clippy::elidable_lifetime_names,
98a4851eeeSMiguel Ojeda     clippy::missing_errors_doc,
99a4851eeeSMiguel Ojeda     clippy::missing_panics_doc,
100a4851eeeSMiguel Ojeda     clippy::module_name_repetitions,
101a4851eeeSMiguel Ojeda     clippy::needless_lifetimes,
102a4851eeeSMiguel Ojeda     // false positive https://github.com/rust-lang/rust-clippy/issues/6983
103a4851eeeSMiguel Ojeda     clippy::wrong_self_convention,
104a4851eeeSMiguel Ojeda )]
105a4851eeeSMiguel Ojeda 
106a4851eeeSMiguel Ojeda extern crate alloc;
107a4851eeeSMiguel Ojeda 
108a4851eeeSMiguel Ojeda #[cfg(feature = "proc-macro")]
109a4851eeeSMiguel Ojeda extern crate proc_macro;
110a4851eeeSMiguel Ojeda 
111a4851eeeSMiguel Ojeda mod ext;
112a4851eeeSMiguel Ojeda mod format;
113a4851eeeSMiguel Ojeda mod ident_fragment;
114a4851eeeSMiguel Ojeda mod to_tokens;
115a4851eeeSMiguel Ojeda 
116a4851eeeSMiguel Ojeda // Not public API.
117a4851eeeSMiguel Ojeda #[doc(hidden)]
118a4851eeeSMiguel Ojeda #[path = "runtime.rs"]
119a4851eeeSMiguel Ojeda pub mod __private;
120a4851eeeSMiguel Ojeda 
121a4851eeeSMiguel Ojeda pub use crate::ext::TokenStreamExt;
122a4851eeeSMiguel Ojeda pub use crate::ident_fragment::IdentFragment;
123a4851eeeSMiguel Ojeda pub use crate::to_tokens::ToTokens;
124a4851eeeSMiguel Ojeda 
125a4851eeeSMiguel Ojeda // Not public API.
126a4851eeeSMiguel Ojeda #[doc(hidden)]
127a4851eeeSMiguel Ojeda pub mod spanned;
128a4851eeeSMiguel Ojeda 
129a4851eeeSMiguel Ojeda macro_rules! __quote {
130a4851eeeSMiguel Ojeda     ($quote:item) => {
131a4851eeeSMiguel Ojeda         /// The whole point.
132a4851eeeSMiguel Ojeda         ///
133a4851eeeSMiguel Ojeda         /// Performs variable interpolation against the input and produces it as
134a4851eeeSMiguel Ojeda         /// [`proc_macro2::TokenStream`].
135a4851eeeSMiguel Ojeda         ///
136a4851eeeSMiguel Ojeda         /// Note: for returning tokens to the compiler in a procedural macro, use
137a4851eeeSMiguel Ojeda         /// `.into()` on the result to convert to [`proc_macro::TokenStream`].
138a4851eeeSMiguel Ojeda         ///
139a4851eeeSMiguel Ojeda         /// <br>
140a4851eeeSMiguel Ojeda         ///
141a4851eeeSMiguel Ojeda         /// # Interpolation
142a4851eeeSMiguel Ojeda         ///
143a4851eeeSMiguel Ojeda         /// Variable interpolation is done with `#var` (similar to `$var` in
144a4851eeeSMiguel Ojeda         /// `macro_rules!` macros). This grabs the `var` variable that is currently in
145a4851eeeSMiguel Ojeda         /// scope and inserts it in that location in the output tokens. Any type
146a4851eeeSMiguel Ojeda         /// implementing the [`ToTokens`] trait can be interpolated. This includes most
147a4851eeeSMiguel Ojeda         /// Rust primitive types as well as most of the syntax tree types from the [Syn]
148a4851eeeSMiguel Ojeda         /// crate.
149a4851eeeSMiguel Ojeda         ///
150a4851eeeSMiguel Ojeda         /// [Syn]: https://github.com/dtolnay/syn
151a4851eeeSMiguel Ojeda         ///
152a4851eeeSMiguel Ojeda         /// Repetition is done using `#(...)*` or `#(...),*` again similar to
153a4851eeeSMiguel Ojeda         /// `macro_rules!`. This iterates through the elements of any variable
154a4851eeeSMiguel Ojeda         /// interpolated within the repetition and inserts a copy of the repetition body
155a4851eeeSMiguel Ojeda         /// for each one. The variables in an interpolation may be a `Vec`, slice,
156a4851eeeSMiguel Ojeda         /// `BTreeSet`, or any `Iterator`.
157a4851eeeSMiguel Ojeda         ///
158a4851eeeSMiguel Ojeda         /// - `#(#var)*` — no separators
159a4851eeeSMiguel Ojeda         /// - `#(#var),*` — the character before the asterisk is used as a separator
160a4851eeeSMiguel Ojeda         /// - `#( struct #var; )*` — the repetition can contain other tokens
161a4851eeeSMiguel Ojeda         /// - `#( #k => println!("{}", #v), )*` — even multiple interpolations
162a4851eeeSMiguel Ojeda         ///
163a4851eeeSMiguel Ojeda         /// <br>
164a4851eeeSMiguel Ojeda         ///
165a4851eeeSMiguel Ojeda         /// # Hygiene
166a4851eeeSMiguel Ojeda         ///
167a4851eeeSMiguel Ojeda         /// Any interpolated tokens preserve the `Span` information provided by their
168a4851eeeSMiguel Ojeda         /// `ToTokens` implementation. Tokens that originate within the `quote!`
169a4851eeeSMiguel Ojeda         /// invocation are spanned with [`Span::call_site()`].
170a4851eeeSMiguel Ojeda         ///
171a4851eeeSMiguel Ojeda         /// [`Span::call_site()`]: proc_macro2::Span::call_site
172a4851eeeSMiguel Ojeda         ///
173a4851eeeSMiguel Ojeda         /// A different span can be provided through the [`quote_spanned!`] macro.
174a4851eeeSMiguel Ojeda         ///
175a4851eeeSMiguel Ojeda         /// <br>
176a4851eeeSMiguel Ojeda         ///
177a4851eeeSMiguel Ojeda         /// # Return type
178a4851eeeSMiguel Ojeda         ///
179a4851eeeSMiguel Ojeda         /// The macro evaluates to an expression of type `proc_macro2::TokenStream`.
180a4851eeeSMiguel Ojeda         /// Meanwhile Rust procedural macros are expected to return the type
181a4851eeeSMiguel Ojeda         /// `proc_macro::TokenStream`.
182a4851eeeSMiguel Ojeda         ///
183a4851eeeSMiguel Ojeda         /// The difference between the two types is that `proc_macro` types are entirely
184a4851eeeSMiguel Ojeda         /// specific to procedural macros and cannot ever exist in code outside of a
185a4851eeeSMiguel Ojeda         /// procedural macro, while `proc_macro2` types may exist anywhere including
186a4851eeeSMiguel Ojeda         /// tests and non-macro code like main.rs and build.rs. This is why even the
187a4851eeeSMiguel Ojeda         /// procedural macro ecosystem is largely built around `proc_macro2`, because
188a4851eeeSMiguel Ojeda         /// that ensures the libraries are unit testable and accessible in non-macro
189a4851eeeSMiguel Ojeda         /// contexts.
190a4851eeeSMiguel Ojeda         ///
191a4851eeeSMiguel Ojeda         /// There is a [`From`]-conversion in both directions so returning the output of
192a4851eeeSMiguel Ojeda         /// `quote!` from a procedural macro usually looks like `tokens.into()` or
193a4851eeeSMiguel Ojeda         /// `proc_macro::TokenStream::from(tokens)`.
194a4851eeeSMiguel Ojeda         ///
195a4851eeeSMiguel Ojeda         /// <br>
196a4851eeeSMiguel Ojeda         ///
197a4851eeeSMiguel Ojeda         /// # Examples
198a4851eeeSMiguel Ojeda         ///
199a4851eeeSMiguel Ojeda         /// ### Procedural macro
200a4851eeeSMiguel Ojeda         ///
201a4851eeeSMiguel Ojeda         /// The structure of a basic procedural macro is as follows. Refer to the [Syn]
202a4851eeeSMiguel Ojeda         /// crate for further useful guidance on using `quote!` as part of a procedural
203a4851eeeSMiguel Ojeda         /// macro.
204a4851eeeSMiguel Ojeda         ///
205a4851eeeSMiguel Ojeda         /// [Syn]: https://github.com/dtolnay/syn
206a4851eeeSMiguel Ojeda         ///
207a4851eeeSMiguel Ojeda         /// ```
208a4851eeeSMiguel Ojeda         /// # #[cfg(any())]
209a4851eeeSMiguel Ojeda         /// extern crate proc_macro;
210a4851eeeSMiguel Ojeda         /// # extern crate proc_macro2;
211a4851eeeSMiguel Ojeda         ///
212a4851eeeSMiguel Ojeda         /// # #[cfg(any())]
213a4851eeeSMiguel Ojeda         /// use proc_macro::TokenStream;
214a4851eeeSMiguel Ojeda         /// # use proc_macro2::TokenStream;
215a4851eeeSMiguel Ojeda         /// use quote::quote;
216a4851eeeSMiguel Ojeda         ///
217a4851eeeSMiguel Ojeda         /// # const IGNORE_TOKENS: &'static str = stringify! {
218a4851eeeSMiguel Ojeda         /// #[proc_macro_derive(HeapSize)]
219a4851eeeSMiguel Ojeda         /// # };
220a4851eeeSMiguel Ojeda         /// pub fn derive_heap_size(input: TokenStream) -> TokenStream {
221a4851eeeSMiguel Ojeda         ///     // Parse the input and figure out what implementation to generate...
222a4851eeeSMiguel Ojeda         ///     # const IGNORE_TOKENS: &'static str = stringify! {
223a4851eeeSMiguel Ojeda         ///     let name = /* ... */;
224a4851eeeSMiguel Ojeda         ///     let expr = /* ... */;
225a4851eeeSMiguel Ojeda         ///     # };
226a4851eeeSMiguel Ojeda         ///     #
227a4851eeeSMiguel Ojeda         ///     # let name = 0;
228a4851eeeSMiguel Ojeda         ///     # let expr = 0;
229a4851eeeSMiguel Ojeda         ///
230a4851eeeSMiguel Ojeda         ///     let expanded = quote! {
231a4851eeeSMiguel Ojeda         ///         // The generated impl.
232a4851eeeSMiguel Ojeda         ///         impl heapsize::HeapSize for #name {
233a4851eeeSMiguel Ojeda         ///             fn heap_size_of_children(&self) -> usize {
234a4851eeeSMiguel Ojeda         ///                 #expr
235a4851eeeSMiguel Ojeda         ///             }
236a4851eeeSMiguel Ojeda         ///         }
237a4851eeeSMiguel Ojeda         ///     };
238a4851eeeSMiguel Ojeda         ///
239a4851eeeSMiguel Ojeda         ///     // Hand the output tokens back to the compiler.
240a4851eeeSMiguel Ojeda         ///     TokenStream::from(expanded)
241a4851eeeSMiguel Ojeda         /// }
242a4851eeeSMiguel Ojeda         /// ```
243a4851eeeSMiguel Ojeda         ///
244a4851eeeSMiguel Ojeda         /// <p><br></p>
245a4851eeeSMiguel Ojeda         ///
246a4851eeeSMiguel Ojeda         /// ### Combining quoted fragments
247a4851eeeSMiguel Ojeda         ///
248a4851eeeSMiguel Ojeda         /// Usually you don't end up constructing an entire final `TokenStream` in one
249a4851eeeSMiguel Ojeda         /// piece. Different parts may come from different helper functions. The tokens
250a4851eeeSMiguel Ojeda         /// produced by `quote!` themselves implement `ToTokens` and so can be
251a4851eeeSMiguel Ojeda         /// interpolated into later `quote!` invocations to build up a final result.
252a4851eeeSMiguel Ojeda         ///
253a4851eeeSMiguel Ojeda         /// ```
254a4851eeeSMiguel Ojeda         /// # use quote::quote;
255a4851eeeSMiguel Ojeda         /// #
256a4851eeeSMiguel Ojeda         /// let type_definition = quote! {...};
257a4851eeeSMiguel Ojeda         /// let methods = quote! {...};
258a4851eeeSMiguel Ojeda         ///
259a4851eeeSMiguel Ojeda         /// let tokens = quote! {
260a4851eeeSMiguel Ojeda         ///     #type_definition
261a4851eeeSMiguel Ojeda         ///     #methods
262a4851eeeSMiguel Ojeda         /// };
263a4851eeeSMiguel Ojeda         /// ```
264a4851eeeSMiguel Ojeda         ///
265a4851eeeSMiguel Ojeda         /// <p><br></p>
266a4851eeeSMiguel Ojeda         ///
267a4851eeeSMiguel Ojeda         /// ### Constructing identifiers
268a4851eeeSMiguel Ojeda         ///
269a4851eeeSMiguel Ojeda         /// Suppose we have an identifier `ident` which came from somewhere in a macro
270a4851eeeSMiguel Ojeda         /// input and we need to modify it in some way for the macro output. Let's
271a4851eeeSMiguel Ojeda         /// consider prepending the identifier with an underscore.
272a4851eeeSMiguel Ojeda         ///
273a4851eeeSMiguel Ojeda         /// Simply interpolating the identifier next to an underscore will not have the
274a4851eeeSMiguel Ojeda         /// behavior of concatenating them. The underscore and the identifier will
275a4851eeeSMiguel Ojeda         /// continue to be two separate tokens as if you had written `_ x`.
276a4851eeeSMiguel Ojeda         ///
277a4851eeeSMiguel Ojeda         /// ```
278a4851eeeSMiguel Ojeda         /// # use proc_macro2::{self as syn, Span};
279a4851eeeSMiguel Ojeda         /// # use quote::quote;
280a4851eeeSMiguel Ojeda         /// #
281a4851eeeSMiguel Ojeda         /// # let ident = syn::Ident::new("i", Span::call_site());
282a4851eeeSMiguel Ojeda         /// #
283a4851eeeSMiguel Ojeda         /// // incorrect
284a4851eeeSMiguel Ojeda         /// quote! {
285a4851eeeSMiguel Ojeda         ///     let mut _#ident = 0;
286a4851eeeSMiguel Ojeda         /// }
287a4851eeeSMiguel Ojeda         /// # ;
288a4851eeeSMiguel Ojeda         /// ```
289a4851eeeSMiguel Ojeda         ///
290a4851eeeSMiguel Ojeda         /// The solution is to build a new identifier token with the correct value. As
291a4851eeeSMiguel Ojeda         /// this is such a common case, the [`format_ident!`] macro provides a
292a4851eeeSMiguel Ojeda         /// convenient utility for doing so correctly.
293a4851eeeSMiguel Ojeda         ///
294a4851eeeSMiguel Ojeda         /// ```
295a4851eeeSMiguel Ojeda         /// # use proc_macro2::{Ident, Span};
296a4851eeeSMiguel Ojeda         /// # use quote::{format_ident, quote};
297a4851eeeSMiguel Ojeda         /// #
298a4851eeeSMiguel Ojeda         /// # let ident = Ident::new("i", Span::call_site());
299a4851eeeSMiguel Ojeda         /// #
300a4851eeeSMiguel Ojeda         /// let varname = format_ident!("_{}", ident);
301a4851eeeSMiguel Ojeda         /// quote! {
302a4851eeeSMiguel Ojeda         ///     let mut #varname = 0;
303a4851eeeSMiguel Ojeda         /// }
304a4851eeeSMiguel Ojeda         /// # ;
305a4851eeeSMiguel Ojeda         /// ```
306a4851eeeSMiguel Ojeda         ///
307a4851eeeSMiguel Ojeda         /// Alternatively, the APIs provided by Syn and proc-macro2 can be used to
308a4851eeeSMiguel Ojeda         /// directly build the identifier. This is roughly equivalent to the above, but
309a4851eeeSMiguel Ojeda         /// will not handle `ident` being a raw identifier.
310a4851eeeSMiguel Ojeda         ///
311a4851eeeSMiguel Ojeda         /// ```
312a4851eeeSMiguel Ojeda         /// # use proc_macro2::{self as syn, Span};
313a4851eeeSMiguel Ojeda         /// # use quote::quote;
314a4851eeeSMiguel Ojeda         /// #
315a4851eeeSMiguel Ojeda         /// # let ident = syn::Ident::new("i", Span::call_site());
316a4851eeeSMiguel Ojeda         /// #
317a4851eeeSMiguel Ojeda         /// let concatenated = format!("_{}", ident);
318a4851eeeSMiguel Ojeda         /// let varname = syn::Ident::new(&concatenated, ident.span());
319a4851eeeSMiguel Ojeda         /// quote! {
320a4851eeeSMiguel Ojeda         ///     let mut #varname = 0;
321a4851eeeSMiguel Ojeda         /// }
322a4851eeeSMiguel Ojeda         /// # ;
323a4851eeeSMiguel Ojeda         /// ```
324a4851eeeSMiguel Ojeda         ///
325a4851eeeSMiguel Ojeda         /// <p><br></p>
326a4851eeeSMiguel Ojeda         ///
327a4851eeeSMiguel Ojeda         /// ### Making method calls
328a4851eeeSMiguel Ojeda         ///
329a4851eeeSMiguel Ojeda         /// Let's say our macro requires some type specified in the macro input to have
330a4851eeeSMiguel Ojeda         /// a constructor called `new`. We have the type in a variable called
331a4851eeeSMiguel Ojeda         /// `field_type` of type `syn::Type` and want to invoke the constructor.
332a4851eeeSMiguel Ojeda         ///
333a4851eeeSMiguel Ojeda         /// ```
334a4851eeeSMiguel Ojeda         /// # use quote::quote;
335a4851eeeSMiguel Ojeda         /// #
336a4851eeeSMiguel Ojeda         /// # let field_type = quote!(...);
337a4851eeeSMiguel Ojeda         /// #
338a4851eeeSMiguel Ojeda         /// // incorrect
339a4851eeeSMiguel Ojeda         /// quote! {
340a4851eeeSMiguel Ojeda         ///     let value = #field_type::new();
341a4851eeeSMiguel Ojeda         /// }
342a4851eeeSMiguel Ojeda         /// # ;
343a4851eeeSMiguel Ojeda         /// ```
344a4851eeeSMiguel Ojeda         ///
345a4851eeeSMiguel Ojeda         /// This works only sometimes. If `field_type` is `String`, the expanded code
346a4851eeeSMiguel Ojeda         /// contains `String::new()` which is fine. But if `field_type` is something
347a4851eeeSMiguel Ojeda         /// like `Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid
348a4851eeeSMiguel Ojeda         /// syntax. Ordinarily in handwritten Rust we would write `Vec::<i32>::new()`
349a4851eeeSMiguel Ojeda         /// but for macros often the following is more convenient.
350a4851eeeSMiguel Ojeda         ///
351a4851eeeSMiguel Ojeda         /// ```
352a4851eeeSMiguel Ojeda         /// # use quote::quote;
353a4851eeeSMiguel Ojeda         /// #
354a4851eeeSMiguel Ojeda         /// # let field_type = quote!(...);
355a4851eeeSMiguel Ojeda         /// #
356a4851eeeSMiguel Ojeda         /// quote! {
357a4851eeeSMiguel Ojeda         ///     let value = <#field_type>::new();
358a4851eeeSMiguel Ojeda         /// }
359a4851eeeSMiguel Ojeda         /// # ;
360a4851eeeSMiguel Ojeda         /// ```
361a4851eeeSMiguel Ojeda         ///
362a4851eeeSMiguel Ojeda         /// This expands to `<Vec<i32>>::new()` which behaves correctly.
363a4851eeeSMiguel Ojeda         ///
364a4851eeeSMiguel Ojeda         /// A similar pattern is appropriate for trait methods.
365a4851eeeSMiguel Ojeda         ///
366a4851eeeSMiguel Ojeda         /// ```
367a4851eeeSMiguel Ojeda         /// # use quote::quote;
368a4851eeeSMiguel Ojeda         /// #
369a4851eeeSMiguel Ojeda         /// # let field_type = quote!(...);
370a4851eeeSMiguel Ojeda         /// #
371a4851eeeSMiguel Ojeda         /// quote! {
372a4851eeeSMiguel Ojeda         ///     let value = <#field_type as core::default::Default>::default();
373a4851eeeSMiguel Ojeda         /// }
374a4851eeeSMiguel Ojeda         /// # ;
375a4851eeeSMiguel Ojeda         /// ```
376a4851eeeSMiguel Ojeda         ///
377a4851eeeSMiguel Ojeda         /// <p><br></p>
378a4851eeeSMiguel Ojeda         ///
379a4851eeeSMiguel Ojeda         /// ### Interpolating text inside of doc comments
380a4851eeeSMiguel Ojeda         ///
381a4851eeeSMiguel Ojeda         /// Neither doc comments nor string literals get interpolation behavior in
382a4851eeeSMiguel Ojeda         /// quote:
383a4851eeeSMiguel Ojeda         ///
384a4851eeeSMiguel Ojeda         /// ```compile_fail
385a4851eeeSMiguel Ojeda         /// quote! {
386a4851eeeSMiguel Ojeda         ///     /// try to interpolate: #ident
387a4851eeeSMiguel Ojeda         ///     ///
388a4851eeeSMiguel Ojeda         ///     /// ...
389a4851eeeSMiguel Ojeda         /// }
390a4851eeeSMiguel Ojeda         /// ```
391a4851eeeSMiguel Ojeda         ///
392a4851eeeSMiguel Ojeda         /// ```compile_fail
393a4851eeeSMiguel Ojeda         /// quote! {
394a4851eeeSMiguel Ojeda         ///     #[doc = "try to interpolate: #ident"]
395a4851eeeSMiguel Ojeda         /// }
396a4851eeeSMiguel Ojeda         /// ```
397a4851eeeSMiguel Ojeda         ///
398a4851eeeSMiguel Ojeda         /// Instead the best way to build doc comments that involve variables is by
399a4851eeeSMiguel Ojeda         /// formatting the doc string literal outside of quote.
400a4851eeeSMiguel Ojeda         ///
401a4851eeeSMiguel Ojeda         /// ```rust
402a4851eeeSMiguel Ojeda         /// # use proc_macro2::{Ident, Span};
403a4851eeeSMiguel Ojeda         /// # use quote::quote;
404a4851eeeSMiguel Ojeda         /// #
405a4851eeeSMiguel Ojeda         /// # const IGNORE: &str = stringify! {
406a4851eeeSMiguel Ojeda         /// let msg = format!(...);
407a4851eeeSMiguel Ojeda         /// # };
408a4851eeeSMiguel Ojeda         /// #
409a4851eeeSMiguel Ojeda         /// # let ident = Ident::new("var", Span::call_site());
410a4851eeeSMiguel Ojeda         /// # let msg = format!("try to interpolate: {}", ident);
411a4851eeeSMiguel Ojeda         /// quote! {
412a4851eeeSMiguel Ojeda         ///     #[doc = #msg]
413a4851eeeSMiguel Ojeda         ///     ///
414a4851eeeSMiguel Ojeda         ///     /// ...
415a4851eeeSMiguel Ojeda         /// }
416a4851eeeSMiguel Ojeda         /// # ;
417a4851eeeSMiguel Ojeda         /// ```
418a4851eeeSMiguel Ojeda         ///
419a4851eeeSMiguel Ojeda         /// <p><br></p>
420a4851eeeSMiguel Ojeda         ///
421a4851eeeSMiguel Ojeda         /// ### Indexing into a tuple struct
422a4851eeeSMiguel Ojeda         ///
423a4851eeeSMiguel Ojeda         /// When interpolating indices of a tuple or tuple struct, we need them not to
424a4851eeeSMiguel Ojeda         /// appears suffixed as integer literals by interpolating them as [`syn::Index`]
425a4851eeeSMiguel Ojeda         /// instead.
426a4851eeeSMiguel Ojeda         ///
427a4851eeeSMiguel Ojeda         /// [`syn::Index`]: https://docs.rs/syn/2.0/syn/struct.Index.html
428a4851eeeSMiguel Ojeda         ///
429a4851eeeSMiguel Ojeda         /// ```compile_fail
430a4851eeeSMiguel Ojeda         /// let i = 0usize..self.fields.len();
431a4851eeeSMiguel Ojeda         ///
432a4851eeeSMiguel Ojeda         /// // expands to 0 + self.0usize.heap_size() + self.1usize.heap_size() + ...
433a4851eeeSMiguel Ojeda         /// // which is not valid syntax
434a4851eeeSMiguel Ojeda         /// quote! {
435a4851eeeSMiguel Ojeda         ///     0 #( + self.#i.heap_size() )*
436a4851eeeSMiguel Ojeda         /// }
437a4851eeeSMiguel Ojeda         /// ```
438a4851eeeSMiguel Ojeda         ///
439a4851eeeSMiguel Ojeda         /// ```
440a4851eeeSMiguel Ojeda         /// # use proc_macro2::{Ident, TokenStream};
441a4851eeeSMiguel Ojeda         /// # use quote::quote;
442a4851eeeSMiguel Ojeda         /// #
443a4851eeeSMiguel Ojeda         /// # mod syn {
444a4851eeeSMiguel Ojeda         /// #     use proc_macro2::{Literal, TokenStream};
445a4851eeeSMiguel Ojeda         /// #     use quote::{ToTokens, TokenStreamExt};
446a4851eeeSMiguel Ojeda         /// #
447a4851eeeSMiguel Ojeda         /// #     pub struct Index(usize);
448a4851eeeSMiguel Ojeda         /// #
449a4851eeeSMiguel Ojeda         /// #     impl From<usize> for Index {
450a4851eeeSMiguel Ojeda         /// #         fn from(i: usize) -> Self {
451a4851eeeSMiguel Ojeda         /// #             Index(i)
452a4851eeeSMiguel Ojeda         /// #         }
453a4851eeeSMiguel Ojeda         /// #     }
454a4851eeeSMiguel Ojeda         /// #
455a4851eeeSMiguel Ojeda         /// #     impl ToTokens for Index {
456a4851eeeSMiguel Ojeda         /// #         fn to_tokens(&self, tokens: &mut TokenStream) {
457a4851eeeSMiguel Ojeda         /// #             tokens.append(Literal::usize_unsuffixed(self.0));
458a4851eeeSMiguel Ojeda         /// #         }
459a4851eeeSMiguel Ojeda         /// #     }
460a4851eeeSMiguel Ojeda         /// # }
461a4851eeeSMiguel Ojeda         /// #
462a4851eeeSMiguel Ojeda         /// # struct Struct {
463a4851eeeSMiguel Ojeda         /// #     fields: Vec<Ident>,
464a4851eeeSMiguel Ojeda         /// # }
465a4851eeeSMiguel Ojeda         /// #
466a4851eeeSMiguel Ojeda         /// # impl Struct {
467a4851eeeSMiguel Ojeda         /// #     fn example(&self) -> TokenStream {
468a4851eeeSMiguel Ojeda         /// let i = (0..self.fields.len()).map(syn::Index::from);
469a4851eeeSMiguel Ojeda         ///
470a4851eeeSMiguel Ojeda         /// // expands to 0 + self.0.heap_size() + self.1.heap_size() + ...
471a4851eeeSMiguel Ojeda         /// quote! {
472a4851eeeSMiguel Ojeda         ///     0 #( + self.#i.heap_size() )*
473a4851eeeSMiguel Ojeda         /// }
474a4851eeeSMiguel Ojeda         /// #     }
475a4851eeeSMiguel Ojeda         /// # }
476a4851eeeSMiguel Ojeda         /// ```
477a4851eeeSMiguel Ojeda         $quote
478a4851eeeSMiguel Ojeda     };
479a4851eeeSMiguel Ojeda }
480a4851eeeSMiguel Ojeda 
481a4851eeeSMiguel Ojeda #[cfg(doc)]
482a4851eeeSMiguel Ojeda __quote![
483a4851eeeSMiguel Ojeda     #[macro_export]
484a4851eeeSMiguel Ojeda     macro_rules! quote {
485a4851eeeSMiguel Ojeda         ($($tt:tt)*) => {
486a4851eeeSMiguel Ojeda             ...
487a4851eeeSMiguel Ojeda         };
488a4851eeeSMiguel Ojeda     }
489a4851eeeSMiguel Ojeda ];
490a4851eeeSMiguel Ojeda 
491a4851eeeSMiguel Ojeda #[cfg(not(doc))]
492a4851eeeSMiguel Ojeda __quote![
493a4851eeeSMiguel Ojeda     #[macro_export]
494a4851eeeSMiguel Ojeda     macro_rules! quote {
495a4851eeeSMiguel Ojeda         () => {
496a4851eeeSMiguel Ojeda             $crate::__private::TokenStream::new()
497a4851eeeSMiguel Ojeda         };
498a4851eeeSMiguel Ojeda 
499a4851eeeSMiguel Ojeda         // Special case rule for a single tt, for performance.
500a4851eeeSMiguel Ojeda         ($tt:tt) => {{
501a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
502a4851eeeSMiguel Ojeda             $crate::quote_token!{$tt _s}
503a4851eeeSMiguel Ojeda             _s
504a4851eeeSMiguel Ojeda         }};
505a4851eeeSMiguel Ojeda 
506a4851eeeSMiguel Ojeda         // Special case rules for two tts, for performance.
507a4851eeeSMiguel Ojeda         (# $var:ident) => {{
508a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
509a4851eeeSMiguel Ojeda             $crate::ToTokens::to_tokens(&$var, &mut _s);
510a4851eeeSMiguel Ojeda             _s
511a4851eeeSMiguel Ojeda         }};
512a4851eeeSMiguel Ojeda         ($tt1:tt $tt2:tt) => {{
513a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
514a4851eeeSMiguel Ojeda             $crate::quote_token!{$tt1 _s}
515a4851eeeSMiguel Ojeda             $crate::quote_token!{$tt2 _s}
516a4851eeeSMiguel Ojeda             _s
517a4851eeeSMiguel Ojeda         }};
518a4851eeeSMiguel Ojeda 
519a4851eeeSMiguel Ojeda         // Rule for any other number of tokens.
520a4851eeeSMiguel Ojeda         ($($tt:tt)*) => {{
521a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
522a4851eeeSMiguel Ojeda             $crate::quote_each_token!{_s $($tt)*}
523a4851eeeSMiguel Ojeda             _s
524a4851eeeSMiguel Ojeda         }};
525a4851eeeSMiguel Ojeda     }
526a4851eeeSMiguel Ojeda ];
527a4851eeeSMiguel Ojeda 
528a4851eeeSMiguel Ojeda macro_rules! __quote_spanned {
529a4851eeeSMiguel Ojeda     ($quote_spanned:item) => {
530a4851eeeSMiguel Ojeda         /// Same as `quote!`, but applies a given span to all tokens originating within
531a4851eeeSMiguel Ojeda         /// the macro invocation.
532a4851eeeSMiguel Ojeda         ///
533a4851eeeSMiguel Ojeda         /// <br>
534a4851eeeSMiguel Ojeda         ///
535a4851eeeSMiguel Ojeda         /// # Syntax
536a4851eeeSMiguel Ojeda         ///
537a4851eeeSMiguel Ojeda         /// A span expression of type [`Span`], followed by `=>`, followed by the tokens
538a4851eeeSMiguel Ojeda         /// to quote. The span expression should be brief &mdash; use a variable for
539a4851eeeSMiguel Ojeda         /// anything more than a few characters. There should be no space before the
540a4851eeeSMiguel Ojeda         /// `=>` token.
541a4851eeeSMiguel Ojeda         ///
542a4851eeeSMiguel Ojeda         /// [`Span`]: proc_macro2::Span
543a4851eeeSMiguel Ojeda         ///
544a4851eeeSMiguel Ojeda         /// ```
545a4851eeeSMiguel Ojeda         /// # use proc_macro2::Span;
546a4851eeeSMiguel Ojeda         /// # use quote::quote_spanned;
547a4851eeeSMiguel Ojeda         /// #
548a4851eeeSMiguel Ojeda         /// # const IGNORE_TOKENS: &'static str = stringify! {
549a4851eeeSMiguel Ojeda         /// let span = /* ... */;
550a4851eeeSMiguel Ojeda         /// # };
551a4851eeeSMiguel Ojeda         /// # let span = Span::call_site();
552a4851eeeSMiguel Ojeda         /// # let init = 0;
553a4851eeeSMiguel Ojeda         ///
554a4851eeeSMiguel Ojeda         /// // On one line, use parentheses.
555a4851eeeSMiguel Ojeda         /// let tokens = quote_spanned!(span=> Box::into_raw(Box::new(#init)));
556a4851eeeSMiguel Ojeda         ///
557a4851eeeSMiguel Ojeda         /// // On multiple lines, place the span at the top and use braces.
558a4851eeeSMiguel Ojeda         /// let tokens = quote_spanned! {span=>
559a4851eeeSMiguel Ojeda         ///     Box::into_raw(Box::new(#init))
560a4851eeeSMiguel Ojeda         /// };
561a4851eeeSMiguel Ojeda         /// ```
562a4851eeeSMiguel Ojeda         ///
563a4851eeeSMiguel Ojeda         /// The lack of space before the `=>` should look jarring to Rust programmers
564a4851eeeSMiguel Ojeda         /// and this is intentional. The formatting is designed to be visibly
565a4851eeeSMiguel Ojeda         /// off-balance and draw the eye a particular way, due to the span expression
566a4851eeeSMiguel Ojeda         /// being evaluated in the context of the procedural macro and the remaining
567a4851eeeSMiguel Ojeda         /// tokens being evaluated in the generated code.
568a4851eeeSMiguel Ojeda         ///
569a4851eeeSMiguel Ojeda         /// <br>
570a4851eeeSMiguel Ojeda         ///
571a4851eeeSMiguel Ojeda         /// # Hygiene
572a4851eeeSMiguel Ojeda         ///
573a4851eeeSMiguel Ojeda         /// Any interpolated tokens preserve the `Span` information provided by their
574a4851eeeSMiguel Ojeda         /// `ToTokens` implementation. Tokens that originate within the `quote_spanned!`
575a4851eeeSMiguel Ojeda         /// invocation are spanned with the given span argument.
576a4851eeeSMiguel Ojeda         ///
577a4851eeeSMiguel Ojeda         /// <br>
578a4851eeeSMiguel Ojeda         ///
579a4851eeeSMiguel Ojeda         /// # Example
580a4851eeeSMiguel Ojeda         ///
581a4851eeeSMiguel Ojeda         /// The following procedural macro code uses `quote_spanned!` to assert that a
582a4851eeeSMiguel Ojeda         /// particular Rust type implements the [`Sync`] trait so that references can be
583a4851eeeSMiguel Ojeda         /// safely shared between threads.
584a4851eeeSMiguel Ojeda         ///
585a4851eeeSMiguel Ojeda         /// ```
586a4851eeeSMiguel Ojeda         /// # use quote::{quote_spanned, TokenStreamExt, ToTokens};
587a4851eeeSMiguel Ojeda         /// # use proc_macro2::{Span, TokenStream};
588a4851eeeSMiguel Ojeda         /// #
589a4851eeeSMiguel Ojeda         /// # struct Type;
590a4851eeeSMiguel Ojeda         /// #
591a4851eeeSMiguel Ojeda         /// # impl Type {
592a4851eeeSMiguel Ojeda         /// #     fn span(&self) -> Span {
593a4851eeeSMiguel Ojeda         /// #         Span::call_site()
594a4851eeeSMiguel Ojeda         /// #     }
595a4851eeeSMiguel Ojeda         /// # }
596a4851eeeSMiguel Ojeda         /// #
597a4851eeeSMiguel Ojeda         /// # impl ToTokens for Type {
598a4851eeeSMiguel Ojeda         /// #     fn to_tokens(&self, _tokens: &mut TokenStream) {}
599a4851eeeSMiguel Ojeda         /// # }
600a4851eeeSMiguel Ojeda         /// #
601a4851eeeSMiguel Ojeda         /// # let ty = Type;
602a4851eeeSMiguel Ojeda         /// # let call_site = Span::call_site();
603a4851eeeSMiguel Ojeda         /// #
604a4851eeeSMiguel Ojeda         /// let ty_span = ty.span();
605a4851eeeSMiguel Ojeda         /// let assert_sync = quote_spanned! {ty_span=>
606a4851eeeSMiguel Ojeda         ///     struct _AssertSync where #ty: Sync;
607a4851eeeSMiguel Ojeda         /// };
608a4851eeeSMiguel Ojeda         /// ```
609a4851eeeSMiguel Ojeda         ///
610a4851eeeSMiguel Ojeda         /// If the assertion fails, the user will see an error like the following. The
611a4851eeeSMiguel Ojeda         /// input span of their type is highlighted in the error.
612a4851eeeSMiguel Ojeda         ///
613a4851eeeSMiguel Ojeda         /// ```text
614a4851eeeSMiguel Ojeda         /// error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
615a4851eeeSMiguel Ojeda         ///   --> src/main.rs:10:21
616a4851eeeSMiguel Ojeda         ///    |
617a4851eeeSMiguel Ojeda         /// 10 |     static ref PTR: *const () = &();
618a4851eeeSMiguel Ojeda         ///    |                     ^^^^^^^^^ `*const ()` cannot be shared between threads safely
619a4851eeeSMiguel Ojeda         /// ```
620a4851eeeSMiguel Ojeda         ///
621a4851eeeSMiguel Ojeda         /// In this example it is important for the where-clause to be spanned with the
622a4851eeeSMiguel Ojeda         /// line/column information of the user's input type so that error messages are
623a4851eeeSMiguel Ojeda         /// placed appropriately by the compiler.
624a4851eeeSMiguel Ojeda         $quote_spanned
625a4851eeeSMiguel Ojeda     };
626a4851eeeSMiguel Ojeda }
627a4851eeeSMiguel Ojeda 
628a4851eeeSMiguel Ojeda #[cfg(doc)]
629a4851eeeSMiguel Ojeda __quote_spanned![
630a4851eeeSMiguel Ojeda     #[macro_export]
631a4851eeeSMiguel Ojeda     macro_rules! quote_spanned {
632a4851eeeSMiguel Ojeda         ($span:expr=> $($tt:tt)*) => {
633a4851eeeSMiguel Ojeda             ...
634a4851eeeSMiguel Ojeda         };
635a4851eeeSMiguel Ojeda     }
636a4851eeeSMiguel Ojeda ];
637a4851eeeSMiguel Ojeda 
638a4851eeeSMiguel Ojeda #[cfg(not(doc))]
639a4851eeeSMiguel Ojeda __quote_spanned![
640a4851eeeSMiguel Ojeda     #[macro_export]
641a4851eeeSMiguel Ojeda     macro_rules! quote_spanned {
642a4851eeeSMiguel Ojeda         ($span:expr=>) => {{
643a4851eeeSMiguel Ojeda             let _: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
644a4851eeeSMiguel Ojeda             $crate::__private::TokenStream::new()
645a4851eeeSMiguel Ojeda         }};
646a4851eeeSMiguel Ojeda 
647a4851eeeSMiguel Ojeda         // Special case rule for a single tt, for performance.
648a4851eeeSMiguel Ojeda         ($span:expr=> $tt:tt) => {{
649a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
650a4851eeeSMiguel Ojeda             let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
651a4851eeeSMiguel Ojeda             $crate::quote_token_spanned!{$tt _s _span}
652a4851eeeSMiguel Ojeda             _s
653a4851eeeSMiguel Ojeda         }};
654a4851eeeSMiguel Ojeda 
655a4851eeeSMiguel Ojeda         // Special case rules for two tts, for performance.
656a4851eeeSMiguel Ojeda         ($span:expr=> # $var:ident) => {{
657a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
658a4851eeeSMiguel Ojeda             let _: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
659a4851eeeSMiguel Ojeda             $crate::ToTokens::to_tokens(&$var, &mut _s);
660a4851eeeSMiguel Ojeda             _s
661a4851eeeSMiguel Ojeda         }};
662a4851eeeSMiguel Ojeda         ($span:expr=> $tt1:tt $tt2:tt) => {{
663a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
664a4851eeeSMiguel Ojeda             let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
665a4851eeeSMiguel Ojeda             $crate::quote_token_spanned!{$tt1 _s _span}
666a4851eeeSMiguel Ojeda             $crate::quote_token_spanned!{$tt2 _s _span}
667a4851eeeSMiguel Ojeda             _s
668a4851eeeSMiguel Ojeda         }};
669a4851eeeSMiguel Ojeda 
670a4851eeeSMiguel Ojeda         // Rule for any other number of tokens.
671a4851eeeSMiguel Ojeda         ($span:expr=> $($tt:tt)*) => {{
672a4851eeeSMiguel Ojeda             let mut _s = $crate::__private::TokenStream::new();
673a4851eeeSMiguel Ojeda             let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
674a4851eeeSMiguel Ojeda             $crate::quote_each_token_spanned!{_s _span $($tt)*}
675a4851eeeSMiguel Ojeda             _s
676a4851eeeSMiguel Ojeda         }};
677a4851eeeSMiguel Ojeda     }
678a4851eeeSMiguel Ojeda ];
679a4851eeeSMiguel Ojeda 
680a4851eeeSMiguel Ojeda // Extract the names of all #metavariables and pass them to the $call macro.
681a4851eeeSMiguel Ojeda //
682a4851eeeSMiguel Ojeda // in:   pounded_var_names!(then!(...) a #b c #( #d )* #e)
683a4851eeeSMiguel Ojeda // out:  then!(... b);
684a4851eeeSMiguel Ojeda //       then!(... d);
685a4851eeeSMiguel Ojeda //       then!(... e);
686a4851eeeSMiguel Ojeda #[macro_export]
687a4851eeeSMiguel Ojeda #[doc(hidden)]
688a4851eeeSMiguel Ojeda macro_rules! pounded_var_names {
689a4851eeeSMiguel Ojeda     ($call:ident! $extra:tt $($tts:tt)*) => {
690a4851eeeSMiguel Ojeda         $crate::pounded_var_names_with_context!{$call! $extra
691a4851eeeSMiguel Ojeda             (@ $($tts)*)
692a4851eeeSMiguel Ojeda             ($($tts)* @)
693a4851eeeSMiguel Ojeda         }
694a4851eeeSMiguel Ojeda     };
695a4851eeeSMiguel Ojeda }
696a4851eeeSMiguel Ojeda 
697a4851eeeSMiguel Ojeda #[macro_export]
698a4851eeeSMiguel Ojeda #[doc(hidden)]
699a4851eeeSMiguel Ojeda macro_rules! pounded_var_names_with_context {
700a4851eeeSMiguel Ojeda     ($call:ident! $extra:tt ($($b1:tt)*) ($($curr:tt)*)) => {
701a4851eeeSMiguel Ojeda         $(
702a4851eeeSMiguel Ojeda             $crate::pounded_var_with_context!{$call! $extra $b1 $curr}
703a4851eeeSMiguel Ojeda         )*
704a4851eeeSMiguel Ojeda     };
705a4851eeeSMiguel Ojeda }
706a4851eeeSMiguel Ojeda 
707a4851eeeSMiguel Ojeda #[macro_export]
708a4851eeeSMiguel Ojeda #[doc(hidden)]
709a4851eeeSMiguel Ojeda macro_rules! pounded_var_with_context {
710a4851eeeSMiguel Ojeda     ($call:ident! $extra:tt $b1:tt ( $($inner:tt)* )) => {
711a4851eeeSMiguel Ojeda         $crate::pounded_var_names!{$call! $extra $($inner)*}
712a4851eeeSMiguel Ojeda     };
713a4851eeeSMiguel Ojeda 
714a4851eeeSMiguel Ojeda     ($call:ident! $extra:tt $b1:tt [ $($inner:tt)* ]) => {
715a4851eeeSMiguel Ojeda         $crate::pounded_var_names!{$call! $extra $($inner)*}
716a4851eeeSMiguel Ojeda     };
717a4851eeeSMiguel Ojeda 
718a4851eeeSMiguel Ojeda     ($call:ident! $extra:tt $b1:tt { $($inner:tt)* }) => {
719a4851eeeSMiguel Ojeda         $crate::pounded_var_names!{$call! $extra $($inner)*}
720a4851eeeSMiguel Ojeda     };
721a4851eeeSMiguel Ojeda 
722a4851eeeSMiguel Ojeda     ($call:ident!($($extra:tt)*) # $var:ident) => {
723a4851eeeSMiguel Ojeda         $crate::$call!($($extra)* $var);
724a4851eeeSMiguel Ojeda     };
725a4851eeeSMiguel Ojeda 
726a4851eeeSMiguel Ojeda     ($call:ident! $extra:tt $b1:tt $curr:tt) => {};
727a4851eeeSMiguel Ojeda }
728a4851eeeSMiguel Ojeda 
729a4851eeeSMiguel Ojeda #[macro_export]
730a4851eeeSMiguel Ojeda #[doc(hidden)]
731a4851eeeSMiguel Ojeda macro_rules! quote_bind_into_iter {
732a4851eeeSMiguel Ojeda     ($has_iter:ident $var:ident) => {
733a4851eeeSMiguel Ojeda         // `mut` may be unused if $var occurs multiple times in the list.
734a4851eeeSMiguel Ojeda         #[allow(unused_mut)]
735a4851eeeSMiguel Ojeda         let (mut $var, i) = $var.quote_into_iter();
736a4851eeeSMiguel Ojeda         let $has_iter = $has_iter | i;
737a4851eeeSMiguel Ojeda     };
738a4851eeeSMiguel Ojeda }
739a4851eeeSMiguel Ojeda 
740a4851eeeSMiguel Ojeda #[macro_export]
741a4851eeeSMiguel Ojeda #[doc(hidden)]
742a4851eeeSMiguel Ojeda macro_rules! quote_bind_next_or_break {
743a4851eeeSMiguel Ojeda     ($var:ident) => {
744a4851eeeSMiguel Ojeda         let $var = match $var.next() {
745a4851eeeSMiguel Ojeda             Some(_x) => $crate::__private::RepInterp(_x),
746a4851eeeSMiguel Ojeda             None => break,
747a4851eeeSMiguel Ojeda         };
748a4851eeeSMiguel Ojeda     };
749a4851eeeSMiguel Ojeda }
750a4851eeeSMiguel Ojeda 
751a4851eeeSMiguel Ojeda // The obvious way to write this macro is as a tt muncher. This implementation
752a4851eeeSMiguel Ojeda // does something more complex for two reasons.
753a4851eeeSMiguel Ojeda //
754a4851eeeSMiguel Ojeda //   - With a tt muncher it's easy to hit Rust's built-in recursion_limit, which
755a4851eeeSMiguel Ojeda //     this implementation avoids because it isn't tail recursive.
756a4851eeeSMiguel Ojeda //
757a4851eeeSMiguel Ojeda //   - Compile times for a tt muncher are quadratic relative to the length of
758a4851eeeSMiguel Ojeda //     the input. This implementation is linear, so it will be faster
759a4851eeeSMiguel Ojeda //     (potentially much faster) for big inputs. However, the constant factors
760a4851eeeSMiguel Ojeda //     of this implementation are higher than that of a tt muncher, so it is
761a4851eeeSMiguel Ojeda //     somewhat slower than a tt muncher if there are many invocations with
762a4851eeeSMiguel Ojeda //     short inputs.
763a4851eeeSMiguel Ojeda //
764a4851eeeSMiguel Ojeda // An invocation like this:
765a4851eeeSMiguel Ojeda //
766a4851eeeSMiguel Ojeda //     quote_each_token!(_s a b c d e f g h i j);
767a4851eeeSMiguel Ojeda //
768a4851eeeSMiguel Ojeda // expands to this:
769a4851eeeSMiguel Ojeda //
770a4851eeeSMiguel Ojeda //     quote_tokens_with_context!(_s
771a4851eeeSMiguel Ojeda //         (@  @  @  @   @   @   a   b   c   d   e   f   g  h  i  j)
772a4851eeeSMiguel Ojeda //         (@  @  @  @   @   a   b   c   d   e   f   g   h  i  j  @)
773a4851eeeSMiguel Ojeda //         (@  @  @  @   a   b   c   d   e   f   g   h   i  j  @  @)
774a4851eeeSMiguel Ojeda //         (@  @  @ (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) @  @  @)
775a4851eeeSMiguel Ojeda //         (@  @  a  b   c   d   e   f   g   h   i   j   @  @  @  @)
776a4851eeeSMiguel Ojeda //         (@  a  b  c   d   e   f   g   h   i   j   @   @  @  @  @)
777a4851eeeSMiguel Ojeda //         (a  b  c  d   e   f   g   h   i   j   @   @   @  @  @  @)
778a4851eeeSMiguel Ojeda //     );
779a4851eeeSMiguel Ojeda //
780a4851eeeSMiguel Ojeda // which gets transposed and expanded to this:
781a4851eeeSMiguel Ojeda //
782a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s @ @ @  @  @ @ a);
783a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s @ @ @  @  @ a b);
784a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s @ @ @  @  a b c);
785a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s @ @ @ (a) b c d);
786a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s @ @ a (b) c d e);
787a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s @ a b (c) d e f);
788a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s a b c (d) e f g);
789a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s b c d (e) f g h);
790a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s c d e (f) g h i);
791a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s d e f (g) h i j);
792a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s e f g (h) i j @);
793a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s f g h (i) j @ @);
794a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s g h i (j) @ @ @);
795a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s h i j  @  @ @ @);
796a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s i j @  @  @ @ @);
797a4851eeeSMiguel Ojeda //     quote_token_with_context!(_s j @ @  @  @ @ @);
798a4851eeeSMiguel Ojeda //
799a4851eeeSMiguel Ojeda // Without having used muncher-style recursion, we get one invocation of
800a4851eeeSMiguel Ojeda // quote_token_with_context for each original tt, with three tts of context on
801a4851eeeSMiguel Ojeda // either side. This is enough for the longest possible interpolation form (a
802a4851eeeSMiguel Ojeda // repetition with separator, as in `# (#var) , *`) to be fully represented with
803a4851eeeSMiguel Ojeda // the first or last tt in the middle.
804a4851eeeSMiguel Ojeda //
805a4851eeeSMiguel Ojeda // The middle tt (surrounded by parentheses) is the tt being processed.
806a4851eeeSMiguel Ojeda //
807a4851eeeSMiguel Ojeda //   - When it is a `#`, quote_token_with_context can do an interpolation. The
808a4851eeeSMiguel Ojeda //     interpolation kind will depend on the three subsequent tts.
809a4851eeeSMiguel Ojeda //
810a4851eeeSMiguel Ojeda //   - When it is within a later part of an interpolation, it can be ignored
811a4851eeeSMiguel Ojeda //     because the interpolation has already been done.
812a4851eeeSMiguel Ojeda //
813a4851eeeSMiguel Ojeda //   - When it is not part of an interpolation it can be pushed as a single
814a4851eeeSMiguel Ojeda //     token into the output.
815a4851eeeSMiguel Ojeda //
816a4851eeeSMiguel Ojeda //   - When the middle token is an unparenthesized `@`, that call is one of the
817a4851eeeSMiguel Ojeda //     first 3 or last 3 calls of quote_token_with_context and does not
818a4851eeeSMiguel Ojeda //     correspond to one of the original input tokens, so turns into nothing.
819a4851eeeSMiguel Ojeda #[macro_export]
820a4851eeeSMiguel Ojeda #[doc(hidden)]
821a4851eeeSMiguel Ojeda macro_rules! quote_each_token {
822a4851eeeSMiguel Ojeda     ($tokens:ident $($tts:tt)*) => {
823a4851eeeSMiguel Ojeda         $crate::quote_tokens_with_context!{$tokens
824a4851eeeSMiguel Ojeda             (@ @ @ @ @ @ $($tts)*)
825a4851eeeSMiguel Ojeda             (@ @ @ @ @ $($tts)* @)
826a4851eeeSMiguel Ojeda             (@ @ @ @ $($tts)* @ @)
827a4851eeeSMiguel Ojeda             (@ @ @ $(($tts))* @ @ @)
828a4851eeeSMiguel Ojeda             (@ @ $($tts)* @ @ @ @)
829a4851eeeSMiguel Ojeda             (@ $($tts)* @ @ @ @ @)
830a4851eeeSMiguel Ojeda             ($($tts)* @ @ @ @ @ @)
831a4851eeeSMiguel Ojeda         }
832a4851eeeSMiguel Ojeda     };
833a4851eeeSMiguel Ojeda }
834a4851eeeSMiguel Ojeda 
835a4851eeeSMiguel Ojeda // See the explanation on quote_each_token.
836a4851eeeSMiguel Ojeda #[macro_export]
837a4851eeeSMiguel Ojeda #[doc(hidden)]
838a4851eeeSMiguel Ojeda macro_rules! quote_each_token_spanned {
839a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $($tts:tt)*) => {
840a4851eeeSMiguel Ojeda         $crate::quote_tokens_with_context_spanned!{$tokens $span
841a4851eeeSMiguel Ojeda             (@ @ @ @ @ @ $($tts)*)
842a4851eeeSMiguel Ojeda             (@ @ @ @ @ $($tts)* @)
843a4851eeeSMiguel Ojeda             (@ @ @ @ $($tts)* @ @)
844a4851eeeSMiguel Ojeda             (@ @ @ $(($tts))* @ @ @)
845a4851eeeSMiguel Ojeda             (@ @ $($tts)* @ @ @ @)
846a4851eeeSMiguel Ojeda             (@ $($tts)* @ @ @ @ @)
847a4851eeeSMiguel Ojeda             ($($tts)* @ @ @ @ @ @)
848a4851eeeSMiguel Ojeda         }
849a4851eeeSMiguel Ojeda     };
850a4851eeeSMiguel Ojeda }
851a4851eeeSMiguel Ojeda 
852a4851eeeSMiguel Ojeda // See the explanation on quote_each_token.
853a4851eeeSMiguel Ojeda #[macro_export]
854a4851eeeSMiguel Ojeda #[doc(hidden)]
855a4851eeeSMiguel Ojeda macro_rules! quote_tokens_with_context {
856a4851eeeSMiguel Ojeda     ($tokens:ident
857a4851eeeSMiguel Ojeda         ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*)
858a4851eeeSMiguel Ojeda         ($($curr:tt)*)
859a4851eeeSMiguel Ojeda         ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*)
860a4851eeeSMiguel Ojeda     ) => {
861a4851eeeSMiguel Ojeda         $(
862a4851eeeSMiguel Ojeda             $crate::quote_token_with_context!{$tokens $b3 $b2 $b1 $curr $a1 $a2 $a3}
863a4851eeeSMiguel Ojeda         )*
864a4851eeeSMiguel Ojeda     };
865a4851eeeSMiguel Ojeda }
866a4851eeeSMiguel Ojeda 
867a4851eeeSMiguel Ojeda // See the explanation on quote_each_token.
868a4851eeeSMiguel Ojeda #[macro_export]
869a4851eeeSMiguel Ojeda #[doc(hidden)]
870a4851eeeSMiguel Ojeda macro_rules! quote_tokens_with_context_spanned {
871a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident
872a4851eeeSMiguel Ojeda         ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*)
873a4851eeeSMiguel Ojeda         ($($curr:tt)*)
874a4851eeeSMiguel Ojeda         ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*)
875a4851eeeSMiguel Ojeda     ) => {
876a4851eeeSMiguel Ojeda         $(
877a4851eeeSMiguel Ojeda             $crate::quote_token_with_context_spanned!{$tokens $span $b3 $b2 $b1 $curr $a1 $a2 $a3}
878a4851eeeSMiguel Ojeda         )*
879a4851eeeSMiguel Ojeda     };
880a4851eeeSMiguel Ojeda }
881a4851eeeSMiguel Ojeda 
882a4851eeeSMiguel Ojeda // See the explanation on quote_each_token.
883a4851eeeSMiguel Ojeda #[macro_export]
884a4851eeeSMiguel Ojeda #[doc(hidden)]
885a4851eeeSMiguel Ojeda macro_rules! quote_token_with_context {
886a4851eeeSMiguel Ojeda     // Unparenthesized `@` indicates this call does not correspond to one of the
887a4851eeeSMiguel Ojeda     // original input tokens. Ignore it.
888a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};
889a4851eeeSMiguel Ojeda 
890a4851eeeSMiguel Ojeda     // A repetition with no separator.
891a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
892a4851eeeSMiguel Ojeda         use $crate::__private::ext::*;
893a4851eeeSMiguel Ojeda         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
894a4851eeeSMiguel Ojeda         $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
895a4851eeeSMiguel Ojeda         let _: $crate::__private::HasIterator = has_iter;
896a4851eeeSMiguel Ojeda         // This is `while true` instead of `loop` because if there are no
897a4851eeeSMiguel Ojeda         // iterators used inside of this repetition then the body would not
898a4851eeeSMiguel Ojeda         // contain any `break`, so the compiler would emit unreachable code
899a4851eeeSMiguel Ojeda         // warnings on anything below the loop. We use has_iter to detect and
900a4851eeeSMiguel Ojeda         // fail to compile when there are no iterators, so here we just work
901a4851eeeSMiguel Ojeda         // around the unneeded extra warning.
902a4851eeeSMiguel Ojeda         while true {
903a4851eeeSMiguel Ojeda             $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
904a4851eeeSMiguel Ojeda             $crate::quote_each_token!{$tokens $($inner)*}
905a4851eeeSMiguel Ojeda         }
906a4851eeeSMiguel Ojeda     }};
907a4851eeeSMiguel Ojeda     // ... and one step later.
908a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {};
909a4851eeeSMiguel Ojeda     // ... and one step later.
910a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {};
911a4851eeeSMiguel Ojeda 
912a4851eeeSMiguel Ojeda     // A repetition with separator.
913a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{
914a4851eeeSMiguel Ojeda         use $crate::__private::ext::*;
915a4851eeeSMiguel Ojeda         let mut _i = 0usize;
916a4851eeeSMiguel Ojeda         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
917a4851eeeSMiguel Ojeda         $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
918a4851eeeSMiguel Ojeda         let _: $crate::__private::HasIterator = has_iter;
919a4851eeeSMiguel Ojeda         while true {
920a4851eeeSMiguel Ojeda             $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
921a4851eeeSMiguel Ojeda             if _i > 0 {
922a4851eeeSMiguel Ojeda                 $crate::quote_token!{$sep $tokens}
923a4851eeeSMiguel Ojeda             }
924a4851eeeSMiguel Ojeda             _i += 1;
925a4851eeeSMiguel Ojeda             $crate::quote_each_token!{$tokens $($inner)*}
926a4851eeeSMiguel Ojeda         }
927a4851eeeSMiguel Ojeda     }};
928a4851eeeSMiguel Ojeda     // ... and one step later.
929a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {};
930a4851eeeSMiguel Ojeda     // ... and one step later.
931a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {};
932a4851eeeSMiguel Ojeda     // (A special case for `#(var)**`, where the first `*` is treated as the
933a4851eeeSMiguel Ojeda     // repetition symbol and the second `*` is treated as an ordinary token.)
934a4851eeeSMiguel Ojeda     ($tokens:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => {
935a4851eeeSMiguel Ojeda         // https://github.com/dtolnay/quote/issues/130
936a4851eeeSMiguel Ojeda         $crate::quote_token!{* $tokens}
937a4851eeeSMiguel Ojeda     };
938a4851eeeSMiguel Ojeda     // ... and one step later.
939a4851eeeSMiguel Ojeda     ($tokens:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {};
940a4851eeeSMiguel Ojeda 
941a4851eeeSMiguel Ojeda     // A non-repetition interpolation.
942a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => {
943a4851eeeSMiguel Ojeda         $crate::ToTokens::to_tokens(&$var, &mut $tokens);
944a4851eeeSMiguel Ojeda     };
945a4851eeeSMiguel Ojeda     // ... and one step later.
946a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
947a4851eeeSMiguel Ojeda 
948a4851eeeSMiguel Ojeda     // An ordinary token, not part of any interpolation.
949a4851eeeSMiguel Ojeda     ($tokens:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {
950a4851eeeSMiguel Ojeda         $crate::quote_token!{$curr $tokens}
951a4851eeeSMiguel Ojeda     };
952a4851eeeSMiguel Ojeda }
953a4851eeeSMiguel Ojeda 
954a4851eeeSMiguel Ojeda // See the explanation on quote_each_token, and on the individual rules of
955a4851eeeSMiguel Ojeda // quote_token_with_context.
956a4851eeeSMiguel Ojeda #[macro_export]
957a4851eeeSMiguel Ojeda #[doc(hidden)]
958a4851eeeSMiguel Ojeda macro_rules! quote_token_with_context_spanned {
959a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};
960a4851eeeSMiguel Ojeda 
961a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
962a4851eeeSMiguel Ojeda         use $crate::__private::ext::*;
963a4851eeeSMiguel Ojeda         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
964a4851eeeSMiguel Ojeda         $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
965a4851eeeSMiguel Ojeda         let _: $crate::__private::HasIterator = has_iter;
966a4851eeeSMiguel Ojeda         while true {
967a4851eeeSMiguel Ojeda             $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
968a4851eeeSMiguel Ojeda             $crate::quote_each_token_spanned!{$tokens $span $($inner)*}
969a4851eeeSMiguel Ojeda         }
970a4851eeeSMiguel Ojeda     }};
971a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {};
972a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {};
973a4851eeeSMiguel Ojeda 
974a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{
975a4851eeeSMiguel Ojeda         use $crate::__private::ext::*;
976a4851eeeSMiguel Ojeda         let mut _i = 0usize;
977a4851eeeSMiguel Ojeda         let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
978a4851eeeSMiguel Ojeda         $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
979a4851eeeSMiguel Ojeda         let _: $crate::__private::HasIterator = has_iter;
980a4851eeeSMiguel Ojeda         while true {
981a4851eeeSMiguel Ojeda             $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
982a4851eeeSMiguel Ojeda             if _i > 0 {
983a4851eeeSMiguel Ojeda                 $crate::quote_token_spanned!{$sep $tokens $span}
984a4851eeeSMiguel Ojeda             }
985a4851eeeSMiguel Ojeda             _i += 1;
986a4851eeeSMiguel Ojeda             $crate::quote_each_token_spanned!{$tokens $span $($inner)*}
987a4851eeeSMiguel Ojeda         }
988a4851eeeSMiguel Ojeda     }};
989a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {};
990a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {};
991a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => {
992a4851eeeSMiguel Ojeda         // https://github.com/dtolnay/quote/issues/130
993a4851eeeSMiguel Ojeda         $crate::quote_token_spanned!{* $tokens $span}
994a4851eeeSMiguel Ojeda     };
995a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {};
996a4851eeeSMiguel Ojeda 
997a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => {
998a4851eeeSMiguel Ojeda         $crate::ToTokens::to_tokens(&$var, &mut $tokens);
999a4851eeeSMiguel Ojeda     };
1000a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
1001a4851eeeSMiguel Ojeda 
1002a4851eeeSMiguel Ojeda     ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {
1003a4851eeeSMiguel Ojeda         $crate::quote_token_spanned!{$curr $tokens $span}
1004a4851eeeSMiguel Ojeda     };
1005a4851eeeSMiguel Ojeda }
1006a4851eeeSMiguel Ojeda 
1007a4851eeeSMiguel Ojeda // These rules are ordered by approximate token frequency, at least for the
1008a4851eeeSMiguel Ojeda // first 10 or so, to improve compile times. Having `ident` first is by far the
1009a4851eeeSMiguel Ojeda // most important because it's typically 2-3x more common than the next most
1010a4851eeeSMiguel Ojeda // common token.
1011a4851eeeSMiguel Ojeda //
1012a4851eeeSMiguel Ojeda // Separately, we put the token being matched in the very front so that failing
1013a4851eeeSMiguel Ojeda // rules may fail to match as quickly as possible.
1014a4851eeeSMiguel Ojeda #[macro_export]
1015a4851eeeSMiguel Ojeda #[doc(hidden)]
1016a4851eeeSMiguel Ojeda macro_rules! quote_token {
1017a4851eeeSMiguel Ojeda     ($ident:ident $tokens:ident) => {
1018a4851eeeSMiguel Ojeda         $crate::__private::push_ident(&mut $tokens, stringify!($ident));
1019a4851eeeSMiguel Ojeda     };
1020a4851eeeSMiguel Ojeda 
1021a4851eeeSMiguel Ojeda     (:: $tokens:ident) => {
1022a4851eeeSMiguel Ojeda         $crate::__private::push_colon2(&mut $tokens);
1023a4851eeeSMiguel Ojeda     };
1024a4851eeeSMiguel Ojeda 
1025a4851eeeSMiguel Ojeda     (( $($inner:tt)* ) $tokens:ident) => {
1026a4851eeeSMiguel Ojeda         $crate::__private::push_group(
1027a4851eeeSMiguel Ojeda             &mut $tokens,
1028a4851eeeSMiguel Ojeda             $crate::__private::Delimiter::Parenthesis,
1029a4851eeeSMiguel Ojeda             $crate::quote!($($inner)*),
1030a4851eeeSMiguel Ojeda         );
1031a4851eeeSMiguel Ojeda     };
1032a4851eeeSMiguel Ojeda 
1033a4851eeeSMiguel Ojeda     ([ $($inner:tt)* ] $tokens:ident) => {
1034a4851eeeSMiguel Ojeda         $crate::__private::push_group(
1035a4851eeeSMiguel Ojeda             &mut $tokens,
1036a4851eeeSMiguel Ojeda             $crate::__private::Delimiter::Bracket,
1037a4851eeeSMiguel Ojeda             $crate::quote!($($inner)*),
1038a4851eeeSMiguel Ojeda         );
1039a4851eeeSMiguel Ojeda     };
1040a4851eeeSMiguel Ojeda 
1041a4851eeeSMiguel Ojeda     ({ $($inner:tt)* } $tokens:ident) => {
1042a4851eeeSMiguel Ojeda         $crate::__private::push_group(
1043a4851eeeSMiguel Ojeda             &mut $tokens,
1044a4851eeeSMiguel Ojeda             $crate::__private::Delimiter::Brace,
1045a4851eeeSMiguel Ojeda             $crate::quote!($($inner)*),
1046a4851eeeSMiguel Ojeda         );
1047a4851eeeSMiguel Ojeda     };
1048a4851eeeSMiguel Ojeda 
1049a4851eeeSMiguel Ojeda     (# $tokens:ident) => {
1050a4851eeeSMiguel Ojeda         $crate::__private::push_pound(&mut $tokens);
1051a4851eeeSMiguel Ojeda     };
1052a4851eeeSMiguel Ojeda 
1053a4851eeeSMiguel Ojeda     (, $tokens:ident) => {
1054a4851eeeSMiguel Ojeda         $crate::__private::push_comma(&mut $tokens);
1055a4851eeeSMiguel Ojeda     };
1056a4851eeeSMiguel Ojeda 
1057a4851eeeSMiguel Ojeda     (. $tokens:ident) => {
1058a4851eeeSMiguel Ojeda         $crate::__private::push_dot(&mut $tokens);
1059a4851eeeSMiguel Ojeda     };
1060a4851eeeSMiguel Ojeda 
1061a4851eeeSMiguel Ojeda     (; $tokens:ident) => {
1062a4851eeeSMiguel Ojeda         $crate::__private::push_semi(&mut $tokens);
1063a4851eeeSMiguel Ojeda     };
1064a4851eeeSMiguel Ojeda 
1065a4851eeeSMiguel Ojeda     (: $tokens:ident) => {
1066a4851eeeSMiguel Ojeda         $crate::__private::push_colon(&mut $tokens);
1067a4851eeeSMiguel Ojeda     };
1068a4851eeeSMiguel Ojeda 
1069a4851eeeSMiguel Ojeda     (+ $tokens:ident) => {
1070a4851eeeSMiguel Ojeda         $crate::__private::push_add(&mut $tokens);
1071a4851eeeSMiguel Ojeda     };
1072a4851eeeSMiguel Ojeda 
1073a4851eeeSMiguel Ojeda     (+= $tokens:ident) => {
1074a4851eeeSMiguel Ojeda         $crate::__private::push_add_eq(&mut $tokens);
1075a4851eeeSMiguel Ojeda     };
1076a4851eeeSMiguel Ojeda 
1077a4851eeeSMiguel Ojeda     (& $tokens:ident) => {
1078a4851eeeSMiguel Ojeda         $crate::__private::push_and(&mut $tokens);
1079a4851eeeSMiguel Ojeda     };
1080a4851eeeSMiguel Ojeda 
1081a4851eeeSMiguel Ojeda     (&& $tokens:ident) => {
1082a4851eeeSMiguel Ojeda         $crate::__private::push_and_and(&mut $tokens);
1083a4851eeeSMiguel Ojeda     };
1084a4851eeeSMiguel Ojeda 
1085a4851eeeSMiguel Ojeda     (&= $tokens:ident) => {
1086a4851eeeSMiguel Ojeda         $crate::__private::push_and_eq(&mut $tokens);
1087a4851eeeSMiguel Ojeda     };
1088a4851eeeSMiguel Ojeda 
1089a4851eeeSMiguel Ojeda     (@ $tokens:ident) => {
1090a4851eeeSMiguel Ojeda         $crate::__private::push_at(&mut $tokens);
1091a4851eeeSMiguel Ojeda     };
1092a4851eeeSMiguel Ojeda 
1093a4851eeeSMiguel Ojeda     (! $tokens:ident) => {
1094a4851eeeSMiguel Ojeda         $crate::__private::push_bang(&mut $tokens);
1095a4851eeeSMiguel Ojeda     };
1096a4851eeeSMiguel Ojeda 
1097a4851eeeSMiguel Ojeda     (^ $tokens:ident) => {
1098a4851eeeSMiguel Ojeda         $crate::__private::push_caret(&mut $tokens);
1099a4851eeeSMiguel Ojeda     };
1100a4851eeeSMiguel Ojeda 
1101a4851eeeSMiguel Ojeda     (^= $tokens:ident) => {
1102a4851eeeSMiguel Ojeda         $crate::__private::push_caret_eq(&mut $tokens);
1103a4851eeeSMiguel Ojeda     };
1104a4851eeeSMiguel Ojeda 
1105a4851eeeSMiguel Ojeda     (/ $tokens:ident) => {
1106a4851eeeSMiguel Ojeda         $crate::__private::push_div(&mut $tokens);
1107a4851eeeSMiguel Ojeda     };
1108a4851eeeSMiguel Ojeda 
1109a4851eeeSMiguel Ojeda     (/= $tokens:ident) => {
1110a4851eeeSMiguel Ojeda         $crate::__private::push_div_eq(&mut $tokens);
1111a4851eeeSMiguel Ojeda     };
1112a4851eeeSMiguel Ojeda 
1113a4851eeeSMiguel Ojeda     (.. $tokens:ident) => {
1114a4851eeeSMiguel Ojeda         $crate::__private::push_dot2(&mut $tokens);
1115a4851eeeSMiguel Ojeda     };
1116a4851eeeSMiguel Ojeda 
1117a4851eeeSMiguel Ojeda     (... $tokens:ident) => {
1118a4851eeeSMiguel Ojeda         $crate::__private::push_dot3(&mut $tokens);
1119a4851eeeSMiguel Ojeda     };
1120a4851eeeSMiguel Ojeda 
1121a4851eeeSMiguel Ojeda     (..= $tokens:ident) => {
1122a4851eeeSMiguel Ojeda         $crate::__private::push_dot_dot_eq(&mut $tokens);
1123a4851eeeSMiguel Ojeda     };
1124a4851eeeSMiguel Ojeda 
1125a4851eeeSMiguel Ojeda     (= $tokens:ident) => {
1126a4851eeeSMiguel Ojeda         $crate::__private::push_eq(&mut $tokens);
1127a4851eeeSMiguel Ojeda     };
1128a4851eeeSMiguel Ojeda 
1129a4851eeeSMiguel Ojeda     (== $tokens:ident) => {
1130a4851eeeSMiguel Ojeda         $crate::__private::push_eq_eq(&mut $tokens);
1131a4851eeeSMiguel Ojeda     };
1132a4851eeeSMiguel Ojeda 
1133a4851eeeSMiguel Ojeda     (>= $tokens:ident) => {
1134a4851eeeSMiguel Ojeda         $crate::__private::push_ge(&mut $tokens);
1135a4851eeeSMiguel Ojeda     };
1136a4851eeeSMiguel Ojeda 
1137a4851eeeSMiguel Ojeda     (> $tokens:ident) => {
1138a4851eeeSMiguel Ojeda         $crate::__private::push_gt(&mut $tokens);
1139a4851eeeSMiguel Ojeda     };
1140a4851eeeSMiguel Ojeda 
1141a4851eeeSMiguel Ojeda     (<= $tokens:ident) => {
1142a4851eeeSMiguel Ojeda         $crate::__private::push_le(&mut $tokens);
1143a4851eeeSMiguel Ojeda     };
1144a4851eeeSMiguel Ojeda 
1145a4851eeeSMiguel Ojeda     (< $tokens:ident) => {
1146a4851eeeSMiguel Ojeda         $crate::__private::push_lt(&mut $tokens);
1147a4851eeeSMiguel Ojeda     };
1148a4851eeeSMiguel Ojeda 
1149a4851eeeSMiguel Ojeda     (*= $tokens:ident) => {
1150a4851eeeSMiguel Ojeda         $crate::__private::push_mul_eq(&mut $tokens);
1151a4851eeeSMiguel Ojeda     };
1152a4851eeeSMiguel Ojeda 
1153a4851eeeSMiguel Ojeda     (!= $tokens:ident) => {
1154a4851eeeSMiguel Ojeda         $crate::__private::push_ne(&mut $tokens);
1155a4851eeeSMiguel Ojeda     };
1156a4851eeeSMiguel Ojeda 
1157a4851eeeSMiguel Ojeda     (| $tokens:ident) => {
1158a4851eeeSMiguel Ojeda         $crate::__private::push_or(&mut $tokens);
1159a4851eeeSMiguel Ojeda     };
1160a4851eeeSMiguel Ojeda 
1161a4851eeeSMiguel Ojeda     (|= $tokens:ident) => {
1162a4851eeeSMiguel Ojeda         $crate::__private::push_or_eq(&mut $tokens);
1163a4851eeeSMiguel Ojeda     };
1164a4851eeeSMiguel Ojeda 
1165a4851eeeSMiguel Ojeda     (|| $tokens:ident) => {
1166a4851eeeSMiguel Ojeda         $crate::__private::push_or_or(&mut $tokens);
1167a4851eeeSMiguel Ojeda     };
1168a4851eeeSMiguel Ojeda 
1169a4851eeeSMiguel Ojeda     (? $tokens:ident) => {
1170a4851eeeSMiguel Ojeda         $crate::__private::push_question(&mut $tokens);
1171a4851eeeSMiguel Ojeda     };
1172a4851eeeSMiguel Ojeda 
1173a4851eeeSMiguel Ojeda     (-> $tokens:ident) => {
1174a4851eeeSMiguel Ojeda         $crate::__private::push_rarrow(&mut $tokens);
1175a4851eeeSMiguel Ojeda     };
1176a4851eeeSMiguel Ojeda 
1177a4851eeeSMiguel Ojeda     (<- $tokens:ident) => {
1178a4851eeeSMiguel Ojeda         $crate::__private::push_larrow(&mut $tokens);
1179a4851eeeSMiguel Ojeda     };
1180a4851eeeSMiguel Ojeda 
1181a4851eeeSMiguel Ojeda     (% $tokens:ident) => {
1182a4851eeeSMiguel Ojeda         $crate::__private::push_rem(&mut $tokens);
1183a4851eeeSMiguel Ojeda     };
1184a4851eeeSMiguel Ojeda 
1185a4851eeeSMiguel Ojeda     (%= $tokens:ident) => {
1186a4851eeeSMiguel Ojeda         $crate::__private::push_rem_eq(&mut $tokens);
1187a4851eeeSMiguel Ojeda     };
1188a4851eeeSMiguel Ojeda 
1189a4851eeeSMiguel Ojeda     (=> $tokens:ident) => {
1190a4851eeeSMiguel Ojeda         $crate::__private::push_fat_arrow(&mut $tokens);
1191a4851eeeSMiguel Ojeda     };
1192a4851eeeSMiguel Ojeda 
1193a4851eeeSMiguel Ojeda     (<< $tokens:ident) => {
1194a4851eeeSMiguel Ojeda         $crate::__private::push_shl(&mut $tokens);
1195a4851eeeSMiguel Ojeda     };
1196a4851eeeSMiguel Ojeda 
1197a4851eeeSMiguel Ojeda     (<<= $tokens:ident) => {
1198a4851eeeSMiguel Ojeda         $crate::__private::push_shl_eq(&mut $tokens);
1199a4851eeeSMiguel Ojeda     };
1200a4851eeeSMiguel Ojeda 
1201a4851eeeSMiguel Ojeda     (>> $tokens:ident) => {
1202a4851eeeSMiguel Ojeda         $crate::__private::push_shr(&mut $tokens);
1203a4851eeeSMiguel Ojeda     };
1204a4851eeeSMiguel Ojeda 
1205a4851eeeSMiguel Ojeda     (>>= $tokens:ident) => {
1206a4851eeeSMiguel Ojeda         $crate::__private::push_shr_eq(&mut $tokens);
1207a4851eeeSMiguel Ojeda     };
1208a4851eeeSMiguel Ojeda 
1209a4851eeeSMiguel Ojeda     (* $tokens:ident) => {
1210a4851eeeSMiguel Ojeda         $crate::__private::push_star(&mut $tokens);
1211a4851eeeSMiguel Ojeda     };
1212a4851eeeSMiguel Ojeda 
1213a4851eeeSMiguel Ojeda     (- $tokens:ident) => {
1214a4851eeeSMiguel Ojeda         $crate::__private::push_sub(&mut $tokens);
1215a4851eeeSMiguel Ojeda     };
1216a4851eeeSMiguel Ojeda 
1217a4851eeeSMiguel Ojeda     (-= $tokens:ident) => {
1218a4851eeeSMiguel Ojeda         $crate::__private::push_sub_eq(&mut $tokens);
1219a4851eeeSMiguel Ojeda     };
1220a4851eeeSMiguel Ojeda 
1221a4851eeeSMiguel Ojeda     ($lifetime:lifetime $tokens:ident) => {
1222a4851eeeSMiguel Ojeda         $crate::__private::push_lifetime(&mut $tokens, stringify!($lifetime));
1223a4851eeeSMiguel Ojeda     };
1224a4851eeeSMiguel Ojeda 
1225a4851eeeSMiguel Ojeda     (_ $tokens:ident) => {
1226a4851eeeSMiguel Ojeda         $crate::__private::push_underscore(&mut $tokens);
1227a4851eeeSMiguel Ojeda     };
1228a4851eeeSMiguel Ojeda 
1229a4851eeeSMiguel Ojeda     ($other:tt $tokens:ident) => {
1230a4851eeeSMiguel Ojeda         $crate::__private::parse(&mut $tokens, stringify!($other));
1231a4851eeeSMiguel Ojeda     };
1232a4851eeeSMiguel Ojeda }
1233a4851eeeSMiguel Ojeda 
1234a4851eeeSMiguel Ojeda // See the comment above `quote_token!` about the rule ordering.
1235a4851eeeSMiguel Ojeda #[macro_export]
1236a4851eeeSMiguel Ojeda #[doc(hidden)]
1237a4851eeeSMiguel Ojeda macro_rules! quote_token_spanned {
1238a4851eeeSMiguel Ojeda     ($ident:ident $tokens:ident $span:ident) => {
1239a4851eeeSMiguel Ojeda         $crate::__private::push_ident_spanned(&mut $tokens, $span, stringify!($ident));
1240a4851eeeSMiguel Ojeda     };
1241a4851eeeSMiguel Ojeda 
1242a4851eeeSMiguel Ojeda     (:: $tokens:ident $span:ident) => {
1243a4851eeeSMiguel Ojeda         $crate::__private::push_colon2_spanned(&mut $tokens, $span);
1244a4851eeeSMiguel Ojeda     };
1245a4851eeeSMiguel Ojeda 
1246a4851eeeSMiguel Ojeda     (( $($inner:tt)* ) $tokens:ident $span:ident) => {
1247a4851eeeSMiguel Ojeda         $crate::__private::push_group_spanned(
1248a4851eeeSMiguel Ojeda             &mut $tokens,
1249a4851eeeSMiguel Ojeda             $span,
1250a4851eeeSMiguel Ojeda             $crate::__private::Delimiter::Parenthesis,
1251a4851eeeSMiguel Ojeda             $crate::quote_spanned!($span=> $($inner)*),
1252a4851eeeSMiguel Ojeda         );
1253a4851eeeSMiguel Ojeda     };
1254a4851eeeSMiguel Ojeda 
1255a4851eeeSMiguel Ojeda     ([ $($inner:tt)* ] $tokens:ident $span:ident) => {
1256a4851eeeSMiguel Ojeda         $crate::__private::push_group_spanned(
1257a4851eeeSMiguel Ojeda             &mut $tokens,
1258a4851eeeSMiguel Ojeda             $span,
1259a4851eeeSMiguel Ojeda             $crate::__private::Delimiter::Bracket,
1260a4851eeeSMiguel Ojeda             $crate::quote_spanned!($span=> $($inner)*),
1261a4851eeeSMiguel Ojeda         );
1262a4851eeeSMiguel Ojeda     };
1263a4851eeeSMiguel Ojeda 
1264a4851eeeSMiguel Ojeda     ({ $($inner:tt)* } $tokens:ident $span:ident) => {
1265a4851eeeSMiguel Ojeda         $crate::__private::push_group_spanned(
1266a4851eeeSMiguel Ojeda             &mut $tokens,
1267a4851eeeSMiguel Ojeda             $span,
1268a4851eeeSMiguel Ojeda             $crate::__private::Delimiter::Brace,
1269a4851eeeSMiguel Ojeda             $crate::quote_spanned!($span=> $($inner)*),
1270a4851eeeSMiguel Ojeda         );
1271a4851eeeSMiguel Ojeda     };
1272a4851eeeSMiguel Ojeda 
1273a4851eeeSMiguel Ojeda     (# $tokens:ident $span:ident) => {
1274a4851eeeSMiguel Ojeda         $crate::__private::push_pound_spanned(&mut $tokens, $span);
1275a4851eeeSMiguel Ojeda     };
1276a4851eeeSMiguel Ojeda 
1277a4851eeeSMiguel Ojeda     (, $tokens:ident $span:ident) => {
1278a4851eeeSMiguel Ojeda         $crate::__private::push_comma_spanned(&mut $tokens, $span);
1279a4851eeeSMiguel Ojeda     };
1280a4851eeeSMiguel Ojeda 
1281a4851eeeSMiguel Ojeda     (. $tokens:ident $span:ident) => {
1282a4851eeeSMiguel Ojeda         $crate::__private::push_dot_spanned(&mut $tokens, $span);
1283a4851eeeSMiguel Ojeda     };
1284a4851eeeSMiguel Ojeda 
1285a4851eeeSMiguel Ojeda     (; $tokens:ident $span:ident) => {
1286a4851eeeSMiguel Ojeda         $crate::__private::push_semi_spanned(&mut $tokens, $span);
1287a4851eeeSMiguel Ojeda     };
1288a4851eeeSMiguel Ojeda 
1289a4851eeeSMiguel Ojeda     (: $tokens:ident $span:ident) => {
1290a4851eeeSMiguel Ojeda         $crate::__private::push_colon_spanned(&mut $tokens, $span);
1291a4851eeeSMiguel Ojeda     };
1292a4851eeeSMiguel Ojeda 
1293a4851eeeSMiguel Ojeda     (+ $tokens:ident $span:ident) => {
1294a4851eeeSMiguel Ojeda         $crate::__private::push_add_spanned(&mut $tokens, $span);
1295a4851eeeSMiguel Ojeda     };
1296a4851eeeSMiguel Ojeda 
1297a4851eeeSMiguel Ojeda     (+= $tokens:ident $span:ident) => {
1298a4851eeeSMiguel Ojeda         $crate::__private::push_add_eq_spanned(&mut $tokens, $span);
1299a4851eeeSMiguel Ojeda     };
1300a4851eeeSMiguel Ojeda 
1301a4851eeeSMiguel Ojeda     (& $tokens:ident $span:ident) => {
1302a4851eeeSMiguel Ojeda         $crate::__private::push_and_spanned(&mut $tokens, $span);
1303a4851eeeSMiguel Ojeda     };
1304a4851eeeSMiguel Ojeda 
1305a4851eeeSMiguel Ojeda     (&& $tokens:ident $span:ident) => {
1306a4851eeeSMiguel Ojeda         $crate::__private::push_and_and_spanned(&mut $tokens, $span);
1307a4851eeeSMiguel Ojeda     };
1308a4851eeeSMiguel Ojeda 
1309a4851eeeSMiguel Ojeda     (&= $tokens:ident $span:ident) => {
1310a4851eeeSMiguel Ojeda         $crate::__private::push_and_eq_spanned(&mut $tokens, $span);
1311a4851eeeSMiguel Ojeda     };
1312a4851eeeSMiguel Ojeda 
1313a4851eeeSMiguel Ojeda     (@ $tokens:ident $span:ident) => {
1314a4851eeeSMiguel Ojeda         $crate::__private::push_at_spanned(&mut $tokens, $span);
1315a4851eeeSMiguel Ojeda     };
1316a4851eeeSMiguel Ojeda 
1317a4851eeeSMiguel Ojeda     (! $tokens:ident $span:ident) => {
1318a4851eeeSMiguel Ojeda         $crate::__private::push_bang_spanned(&mut $tokens, $span);
1319a4851eeeSMiguel Ojeda     };
1320a4851eeeSMiguel Ojeda 
1321a4851eeeSMiguel Ojeda     (^ $tokens:ident $span:ident) => {
1322a4851eeeSMiguel Ojeda         $crate::__private::push_caret_spanned(&mut $tokens, $span);
1323a4851eeeSMiguel Ojeda     };
1324a4851eeeSMiguel Ojeda 
1325a4851eeeSMiguel Ojeda     (^= $tokens:ident $span:ident) => {
1326a4851eeeSMiguel Ojeda         $crate::__private::push_caret_eq_spanned(&mut $tokens, $span);
1327a4851eeeSMiguel Ojeda     };
1328a4851eeeSMiguel Ojeda 
1329a4851eeeSMiguel Ojeda     (/ $tokens:ident $span:ident) => {
1330a4851eeeSMiguel Ojeda         $crate::__private::push_div_spanned(&mut $tokens, $span);
1331a4851eeeSMiguel Ojeda     };
1332a4851eeeSMiguel Ojeda 
1333a4851eeeSMiguel Ojeda     (/= $tokens:ident $span:ident) => {
1334a4851eeeSMiguel Ojeda         $crate::__private::push_div_eq_spanned(&mut $tokens, $span);
1335a4851eeeSMiguel Ojeda     };
1336a4851eeeSMiguel Ojeda 
1337a4851eeeSMiguel Ojeda     (.. $tokens:ident $span:ident) => {
1338a4851eeeSMiguel Ojeda         $crate::__private::push_dot2_spanned(&mut $tokens, $span);
1339a4851eeeSMiguel Ojeda     };
1340a4851eeeSMiguel Ojeda 
1341a4851eeeSMiguel Ojeda     (... $tokens:ident $span:ident) => {
1342a4851eeeSMiguel Ojeda         $crate::__private::push_dot3_spanned(&mut $tokens, $span);
1343a4851eeeSMiguel Ojeda     };
1344a4851eeeSMiguel Ojeda 
1345a4851eeeSMiguel Ojeda     (..= $tokens:ident $span:ident) => {
1346a4851eeeSMiguel Ojeda         $crate::__private::push_dot_dot_eq_spanned(&mut $tokens, $span);
1347a4851eeeSMiguel Ojeda     };
1348a4851eeeSMiguel Ojeda 
1349a4851eeeSMiguel Ojeda     (= $tokens:ident $span:ident) => {
1350a4851eeeSMiguel Ojeda         $crate::__private::push_eq_spanned(&mut $tokens, $span);
1351a4851eeeSMiguel Ojeda     };
1352a4851eeeSMiguel Ojeda 
1353a4851eeeSMiguel Ojeda     (== $tokens:ident $span:ident) => {
1354a4851eeeSMiguel Ojeda         $crate::__private::push_eq_eq_spanned(&mut $tokens, $span);
1355a4851eeeSMiguel Ojeda     };
1356a4851eeeSMiguel Ojeda 
1357a4851eeeSMiguel Ojeda     (>= $tokens:ident $span:ident) => {
1358a4851eeeSMiguel Ojeda         $crate::__private::push_ge_spanned(&mut $tokens, $span);
1359a4851eeeSMiguel Ojeda     };
1360a4851eeeSMiguel Ojeda 
1361a4851eeeSMiguel Ojeda     (> $tokens:ident $span:ident) => {
1362a4851eeeSMiguel Ojeda         $crate::__private::push_gt_spanned(&mut $tokens, $span);
1363a4851eeeSMiguel Ojeda     };
1364a4851eeeSMiguel Ojeda 
1365a4851eeeSMiguel Ojeda     (<= $tokens:ident $span:ident) => {
1366a4851eeeSMiguel Ojeda         $crate::__private::push_le_spanned(&mut $tokens, $span);
1367a4851eeeSMiguel Ojeda     };
1368a4851eeeSMiguel Ojeda 
1369a4851eeeSMiguel Ojeda     (< $tokens:ident $span:ident) => {
1370a4851eeeSMiguel Ojeda         $crate::__private::push_lt_spanned(&mut $tokens, $span);
1371a4851eeeSMiguel Ojeda     };
1372a4851eeeSMiguel Ojeda 
1373a4851eeeSMiguel Ojeda     (*= $tokens:ident $span:ident) => {
1374a4851eeeSMiguel Ojeda         $crate::__private::push_mul_eq_spanned(&mut $tokens, $span);
1375a4851eeeSMiguel Ojeda     };
1376a4851eeeSMiguel Ojeda 
1377a4851eeeSMiguel Ojeda     (!= $tokens:ident $span:ident) => {
1378a4851eeeSMiguel Ojeda         $crate::__private::push_ne_spanned(&mut $tokens, $span);
1379a4851eeeSMiguel Ojeda     };
1380a4851eeeSMiguel Ojeda 
1381a4851eeeSMiguel Ojeda     (| $tokens:ident $span:ident) => {
1382a4851eeeSMiguel Ojeda         $crate::__private::push_or_spanned(&mut $tokens, $span);
1383a4851eeeSMiguel Ojeda     };
1384a4851eeeSMiguel Ojeda 
1385a4851eeeSMiguel Ojeda     (|= $tokens:ident $span:ident) => {
1386a4851eeeSMiguel Ojeda         $crate::__private::push_or_eq_spanned(&mut $tokens, $span);
1387a4851eeeSMiguel Ojeda     };
1388a4851eeeSMiguel Ojeda 
1389a4851eeeSMiguel Ojeda     (|| $tokens:ident $span:ident) => {
1390a4851eeeSMiguel Ojeda         $crate::__private::push_or_or_spanned(&mut $tokens, $span);
1391a4851eeeSMiguel Ojeda     };
1392a4851eeeSMiguel Ojeda 
1393a4851eeeSMiguel Ojeda     (? $tokens:ident $span:ident) => {
1394a4851eeeSMiguel Ojeda         $crate::__private::push_question_spanned(&mut $tokens, $span);
1395a4851eeeSMiguel Ojeda     };
1396a4851eeeSMiguel Ojeda 
1397a4851eeeSMiguel Ojeda     (-> $tokens:ident $span:ident) => {
1398a4851eeeSMiguel Ojeda         $crate::__private::push_rarrow_spanned(&mut $tokens, $span);
1399a4851eeeSMiguel Ojeda     };
1400a4851eeeSMiguel Ojeda 
1401a4851eeeSMiguel Ojeda     (<- $tokens:ident $span:ident) => {
1402a4851eeeSMiguel Ojeda         $crate::__private::push_larrow_spanned(&mut $tokens, $span);
1403a4851eeeSMiguel Ojeda     };
1404a4851eeeSMiguel Ojeda 
1405a4851eeeSMiguel Ojeda     (% $tokens:ident $span:ident) => {
1406a4851eeeSMiguel Ojeda         $crate::__private::push_rem_spanned(&mut $tokens, $span);
1407a4851eeeSMiguel Ojeda     };
1408a4851eeeSMiguel Ojeda 
1409a4851eeeSMiguel Ojeda     (%= $tokens:ident $span:ident) => {
1410a4851eeeSMiguel Ojeda         $crate::__private::push_rem_eq_spanned(&mut $tokens, $span);
1411a4851eeeSMiguel Ojeda     };
1412a4851eeeSMiguel Ojeda 
1413a4851eeeSMiguel Ojeda     (=> $tokens:ident $span:ident) => {
1414a4851eeeSMiguel Ojeda         $crate::__private::push_fat_arrow_spanned(&mut $tokens, $span);
1415a4851eeeSMiguel Ojeda     };
1416a4851eeeSMiguel Ojeda 
1417a4851eeeSMiguel Ojeda     (<< $tokens:ident $span:ident) => {
1418a4851eeeSMiguel Ojeda         $crate::__private::push_shl_spanned(&mut $tokens, $span);
1419a4851eeeSMiguel Ojeda     };
1420a4851eeeSMiguel Ojeda 
1421a4851eeeSMiguel Ojeda     (<<= $tokens:ident $span:ident) => {
1422a4851eeeSMiguel Ojeda         $crate::__private::push_shl_eq_spanned(&mut $tokens, $span);
1423a4851eeeSMiguel Ojeda     };
1424a4851eeeSMiguel Ojeda 
1425a4851eeeSMiguel Ojeda     (>> $tokens:ident $span:ident) => {
1426a4851eeeSMiguel Ojeda         $crate::__private::push_shr_spanned(&mut $tokens, $span);
1427a4851eeeSMiguel Ojeda     };
1428a4851eeeSMiguel Ojeda 
1429a4851eeeSMiguel Ojeda     (>>= $tokens:ident $span:ident) => {
1430a4851eeeSMiguel Ojeda         $crate::__private::push_shr_eq_spanned(&mut $tokens, $span);
1431a4851eeeSMiguel Ojeda     };
1432a4851eeeSMiguel Ojeda 
1433a4851eeeSMiguel Ojeda     (* $tokens:ident $span:ident) => {
1434a4851eeeSMiguel Ojeda         $crate::__private::push_star_spanned(&mut $tokens, $span);
1435a4851eeeSMiguel Ojeda     };
1436a4851eeeSMiguel Ojeda 
1437a4851eeeSMiguel Ojeda     (- $tokens:ident $span:ident) => {
1438a4851eeeSMiguel Ojeda         $crate::__private::push_sub_spanned(&mut $tokens, $span);
1439a4851eeeSMiguel Ojeda     };
1440a4851eeeSMiguel Ojeda 
1441a4851eeeSMiguel Ojeda     (-= $tokens:ident $span:ident) => {
1442a4851eeeSMiguel Ojeda         $crate::__private::push_sub_eq_spanned(&mut $tokens, $span);
1443a4851eeeSMiguel Ojeda     };
1444a4851eeeSMiguel Ojeda 
1445a4851eeeSMiguel Ojeda     ($lifetime:lifetime $tokens:ident $span:ident) => {
1446a4851eeeSMiguel Ojeda         $crate::__private::push_lifetime_spanned(&mut $tokens, $span, stringify!($lifetime));
1447a4851eeeSMiguel Ojeda     };
1448a4851eeeSMiguel Ojeda 
1449a4851eeeSMiguel Ojeda     (_ $tokens:ident $span:ident) => {
1450a4851eeeSMiguel Ojeda         $crate::__private::push_underscore_spanned(&mut $tokens, $span);
1451a4851eeeSMiguel Ojeda     };
1452a4851eeeSMiguel Ojeda 
1453a4851eeeSMiguel Ojeda     ($other:tt $tokens:ident $span:ident) => {
1454a4851eeeSMiguel Ojeda         $crate::__private::parse_spanned(&mut $tokens, $span, stringify!($other));
1455a4851eeeSMiguel Ojeda     };
1456a4851eeeSMiguel Ojeda }
1457