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