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