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 — 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 — 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