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