1 //! This crate provides the [`quote!`] macro for turning Rust syntax tree data
2 //! structures into tokens of source code.
4 //! [`quote!`]: macro.quote.html
6 //! Procedural macros in Rust receive a stream of tokens as input, execute
7 //! arbitrary Rust code to determine how to manipulate those tokens, and produce
8 //! a stream of tokens to hand back to the compiler to compile into the caller's
9 //! crate. Quasi-quoting is a solution to one piece of that -- producing tokens
10 //! to return to the compiler.
12 //! The idea of quasi-quoting is that we write *code* that we treat as *data*.
13 //! Within the `quote!` macro, we can write what looks like code to our text
14 //! editor or IDE. We get all the benefits of the editor's brace matching,
15 //! syntax highlighting, indentation, and maybe autocompletion. But rather than
16 //! compiling that as code into the current crate, we can treat it as data, pass
17 //! it around, mutate it, and eventually hand it back to the compiler as tokens
18 //! to compile into the macro caller's crate.
20 //! This crate is motivated by the procedural macro use case, but is a
21 //! general-purpose Rust quasi-quoting library and is not specific to procedural
24 //! *Version requirement: Quote supports any compiler version back to Rust's
25 //! very first support for procedural macros in Rust 1.15.0.*
34 //! The following quasi-quoted block of code is something you might find in [a]
35 //! procedural macro having to do with data structure serialization. The `#var`
36 //! syntax performs interpolation of runtime variables into the quoted tokens.
37 //! Check out the documentation of the [`quote!`] macro for more detail about
38 //! the syntax. See also the [`quote_spanned!`] macro which is important for
39 //! implementing hygienic procedural macros.
41 //! [a]: https://serde.rs/
42 //! [`quote_spanned!`]: macro.quote_spanned.html
45 //! # use quote::quote;
47 //! # let generics = "";
48 //! # let where_clause = "";
49 //! # let field_ty = "";
50 //! # let item_ty = "";
54 //! let tokens = quote! {
55 //! struct SerializeWith #generics #where_clause {
56 //! value: &'a #field_ty,
57 //! phantom: core::marker::PhantomData<#item_ty>,
60 //! impl #generics serde::Serialize for SerializeWith #generics #where_clause {
61 //! fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
63 //! S: serde::Serializer,
65 //! #path(self.value, serializer)
71 //! phantom: core::marker::PhantomData::<#item_ty>,
78 //! The `quote!` macro relies on deep recursion so some large invocations may
79 //! fail with "recursion limit reached" when you compile. If it fails, bump up
80 //! the recursion limit by adding `#![recursion_limit = "128"]` to your crate.
81 //! An even higher limit may be necessary for especially large invocations.
83 // Quote types in rustdoc of other crates get linked to here.
84 #![doc(html_root_url = "https://docs.rs/quote/0.6.13")]
87 not(all(target_arch
= "wasm32", target_os
= "unknown")),
88 feature
= "proc-macro"
90 extern crate proc_macro
;
91 extern crate proc_macro2
;
94 pub use ext
::TokenStreamExt
;
97 pub use to_tokens
::ToTokens
;
101 #[path = "runtime.rs"]
106 /// Performs variable interpolation against the input and produces it as
107 /// [`TokenStream`]. For returning tokens to the compiler in a procedural macro, use
108 /// `into()` to build a `TokenStream`.
110 /// [`TokenStream`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.TokenStream.html
114 /// Variable interpolation is done with `#var` (similar to `$var` in
115 /// `macro_rules!` macros). This grabs the `var` variable that is currently in
116 /// scope and inserts it in that location in the output tokens. Any type
117 /// implementing the [`ToTokens`] trait can be interpolated. This includes most
118 /// Rust primitive types as well as most of the syntax tree types from the [Syn]
121 /// [`ToTokens`]: trait.ToTokens.html
122 /// [Syn]: https://github.com/dtolnay/syn
124 /// Repetition is done using `#(...)*` or `#(...),*` again similar to
125 /// `macro_rules!`. This iterates through the elements of any variable
126 /// interpolated within the repetition and inserts a copy of the repetition body
127 /// for each one. The variables in an interpolation may be anything that
128 /// implements `IntoIterator`, including `Vec` or a pre-existing iterator.
130 /// - `#(#var)*` — no separators
131 /// - `#(#var),*` — the character before the asterisk is used as a separator
132 /// - `#( struct #var; )*` — the repetition can contain other tokens
133 /// - `#( #k => println!("{}", #v), )*` — even multiple interpolations
135 /// There are two limitations around interpolations in a repetition:
137 /// - Every interpolation inside of a repetition must be a distinct variable.
138 /// That is, `#(#a #a)*` is not allowed. Work around this by collecting `a`
139 /// into a vector and taking references `a1 = &a` and `a2 = &a` which you use
140 /// inside the repetition: `#(#a1 #a2)*`. Where possible, use meaningful names
141 /// that indicate the distinct role of each copy.
143 /// - Every interpolation inside of a repetition must be iterable. If we have
144 /// `vec` which is a vector and `ident` which is a single identifier,
145 /// `#(#ident #vec)*` is not allowed. Work around this by using
146 /// `std::iter::repeat(ident)` to produce an iterable that can be used from
147 /// within the repetition.
151 /// Any interpolated tokens preserve the `Span` information provided by their
152 /// `ToTokens` implementation. Tokens that originate within the `quote!`
153 /// invocation are spanned with [`Span::call_site()`].
155 /// [`Span::call_site()`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html#method.call_site
157 /// A different span can be provided through the [`quote_spanned!`] macro.
159 /// [`quote_spanned!`]: macro.quote_spanned.html
163 /// The macro evaluates to an expression of type `proc_macro2::TokenStream`.
164 /// Meanwhile Rust procedural macros are expected to return the type
165 /// `proc_macro::TokenStream`.
167 /// The difference between the two types is that `proc_macro` types are entirely
168 /// specific to procedural macros and cannot ever exist in code outside of a
169 /// procedural macro, while `proc_macro2` types may exist anywhere including
170 /// tests and non-macro code like main.rs and build.rs. This is why even the
171 /// procedural macro ecosystem is largely built around `proc_macro2`, because
172 /// that ensures the libraries are unit testable and accessible in non-macro
175 /// There is a [`From`]-conversion in both directions so returning the output of
176 /// `quote!` from a procedural macro usually looks like `tokens.into()` or
177 /// `proc_macro::TokenStream::from(tokens)`.
179 /// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
183 /// ## Procedural macro
185 /// The structure of a basic procedural macro is as follows. Refer to the [Syn]
186 /// crate for further useful guidance on using `quote!` as part of a procedural
189 /// [Syn]: https://github.com/dtolnay/syn
193 /// extern crate proc_macro;
194 /// # use proc_macro2 as proc_macro;
196 /// use proc_macro::TokenStream;
197 /// use quote::quote;
199 /// # const IGNORE_TOKENS: &'static str = stringify! {
200 /// #[proc_macro_derive(HeapSize)]
202 /// pub fn derive_heap_size(input: TokenStream) -> TokenStream {
203 /// // Parse the input and figure out what implementation to generate...
204 /// # const IGNORE_TOKENS: &'static str = stringify! {
205 /// let name = /* ... */;
206 /// let expr = /* ... */;
212 /// let expanded = quote! {
213 /// // The generated impl.
214 /// impl heapsize::HeapSize for #name {
215 /// fn heap_size_of_children(&self) -> usize {
221 /// // Hand the output tokens back to the compiler.
222 /// TokenStream::from(expanded)
226 /// ## Combining quoted fragments
228 /// Usually you don't end up constructing an entire final `TokenStream` in one
229 /// piece. Different parts may come from different helper functions. The tokens
230 /// produced by `quote!` themselves implement `ToTokens` and so can be
231 /// interpolated into later `quote!` invocations to build up a final result.
234 /// # use quote::quote;
236 /// let type_definition = quote! {...};
237 /// let methods = quote! {...};
239 /// let tokens = quote! {
245 /// ## Constructing identifiers
247 /// Suppose we have an identifier `ident` which came from somewhere in a macro
248 /// input and we need to modify it in some way for the macro output. Let's
249 /// consider prepending the identifier with an underscore.
251 /// Simply interpolating the identifier next to an underscore will not have the
252 /// behavior of concatenating them. The underscore and the identifier will
253 /// continue to be two separate tokens as if you had written `_ x`.
256 /// # use proc_macro2::{self as syn, Span};
257 /// # use quote::quote;
259 /// # let ident = syn::Ident::new("i", Span::call_site());
263 /// let mut _#ident = 0;
268 /// The solution is to perform token-level manipulations using the APIs provided
269 /// by Syn and proc-macro2.
272 /// # use proc_macro2::{self as syn, Span};
273 /// # use quote::quote;
275 /// # let ident = syn::Ident::new("i", Span::call_site());
277 /// let concatenated = format!("_{}", ident);
278 /// let varname = syn::Ident::new(&concatenated, ident.span());
280 /// let mut #varname = 0;
285 /// ## Making method calls
287 /// Let's say our macro requires some type specified in the macro input to have
288 /// a constructor called `new`. We have the type in a variable called
289 /// `field_type` of type `syn::Type` and want to invoke the constructor.
292 /// # use quote::quote;
294 /// # let field_type = quote!(...);
298 /// let value = #field_type::new();
303 /// This works only sometimes. If `field_type` is `String`, the expanded code
304 /// contains `String::new()` which is fine. But if `field_type` is something
305 /// like `Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid
306 /// syntax. Ordinarily in handwritten Rust we would write `Vec::<i32>::new()`
307 /// but for macros often the following is more convenient.
310 /// # use quote::quote;
312 /// # let field_type = quote!(...);
315 /// let value = <#field_type>::new();
320 /// This expands to `<Vec<i32>>::new()` which behaves correctly.
322 /// A similar pattern is appropriate for trait methods.
325 /// # use quote::quote;
327 /// # let field_type = quote!(...);
330 /// let value = <#field_type as core::default::Default>::default();
334 #[macro_export(local_inner_macros)]
337 quote_spanned
!($
crate::__rt
::Span
::call_site()=> $
($tt
)*)
341 /// Same as `quote!`, but applies a given span to all tokens originating within
342 /// the macro invocation.
346 /// A span expression of type [`Span`], followed by `=>`, followed by the tokens
347 /// to quote. The span expression should be brief -- use a variable for anything
348 /// more than a few characters. There should be no space before the `=>` token.
350 /// [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html
353 /// # use proc_macro2::Span;
354 /// # use quote::quote_spanned;
356 /// # const IGNORE_TOKENS: &'static str = stringify! {
357 /// let span = /* ... */;
359 /// # let span = Span::call_site();
362 /// // On one line, use parentheses.
363 /// let tokens = quote_spanned!(span=> Box::into_raw(Box::new(#init)));
365 /// // On multiple lines, place the span at the top and use braces.
366 /// let tokens = quote_spanned! {span=>
367 /// Box::into_raw(Box::new(#init))
371 /// The lack of space before the `=>` should look jarring to Rust programmers
372 /// and this is intentional. The formatting is designed to be visibly
373 /// off-balance and draw the eye a particular way, due to the span expression
374 /// being evaluated in the context of the procedural macro and the remaining
375 /// tokens being evaluated in the generated code.
379 /// Any interpolated tokens preserve the `Span` information provided by their
380 /// `ToTokens` implementation. Tokens that originate within the `quote_spanned!`
381 /// invocation are spanned with the given span argument.
385 /// The following procedural macro code uses `quote_spanned!` to assert that a
386 /// particular Rust type implements the [`Sync`] trait so that references can be
387 /// safely shared between threads.
389 /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
392 /// # use quote::{quote_spanned, TokenStreamExt, ToTokens};
393 /// # use proc_macro2::{Span, TokenStream};
398 /// # fn span(&self) -> Span {
399 /// # Span::call_site()
403 /// # impl ToTokens for Type {
404 /// # fn to_tokens(&self, _tokens: &mut TokenStream) {}
408 /// # let call_site = Span::call_site();
410 /// let ty_span = ty.span();
411 /// let assert_sync = quote_spanned! {ty_span=>
412 /// struct _AssertSync where #ty: Sync;
416 /// If the assertion fails, the user will see an error like the following. The
417 /// input span of their type is hightlighted in the error.
420 /// error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
421 /// --> src/main.rs:10:21
423 /// 10 | static ref PTR: *const () = &();
424 /// | ^^^^^^^^^ `*const ()` cannot be shared between threads safely
427 /// In this example it is important for the where-clause to be spanned with the
428 /// line/column information of the user's input type so that error messages are
429 /// placed appropriately by the compiler. But it is also incredibly important
430 /// that `Sync` resolves at the macro definition site and not the macro call
431 /// site. If we resolve `Sync` at the same span that the user's type is going to
432 /// be resolved, then they could bypass our check by defining their own trait
433 /// named `Sync` that is implemented for their type.
434 #[macro_export(local_inner_macros)]
435 macro_rules
! quote_spanned
{
436 ($span
:expr
=> $
($tt
:tt
)*) => {{
437 let mut _s
= $
crate::__rt
::TokenStream
::new();
439 quote_each_token
!(_s _span $
($tt
)*);
444 // Extract the names of all #metavariables and pass them to the $finish macro.
446 // in: pounded_var_names!(then () a #b c #( #d )* #e)
447 // out: then!(() b d e)
448 #[macro_export(local_inner_macros)]
450 macro_rules
! pounded_var_names
{
451 ($finish
:ident ($
($found
:ident
)*) # ( $($inner:tt)* ) $($rest:tt)*) => {
452 pounded_var_names
!($
finish ($
($found
)*) $
($inner
)* $
($rest
)*)
455 ($finish
:ident ($
($found
:ident
)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
456 pounded_var_names
!($
finish ($
($found
)*) $
($inner
)* $
($rest
)*)
459 ($finish
:ident ($
($found
:ident
)*) # { $($inner:tt)* } $($rest:tt)*) => {
460 pounded_var_names
!($
finish ($
($found
)*) $
($inner
)* $
($rest
)*)
463 ($finish
:ident ($
($found
:ident
)*) # $first:ident $($rest:tt)*) => {
464 pounded_var_names
!($
finish ($
($found
)* $first
) $
($rest
)*)
467 ($finish
:ident ($
($found
:ident
)*) ( $
($inner
:tt
)* ) $
($rest
:tt
)*) => {
468 pounded_var_names
!($
finish ($
($found
)*) $
($inner
)* $
($rest
)*)
471 ($finish
:ident ($
($found
:ident
)*) [ $
($inner
:tt
)* ] $
($rest
:tt
)*) => {
472 pounded_var_names
!($
finish ($
($found
)*) $
($inner
)* $
($rest
)*)
475 ($finish
:ident ($
($found
:ident
)*) { $($inner:tt)* } $
($rest
:tt
)*) => {
476 pounded_var_names
!($
finish ($
($found
)*) $
($inner
)* $
($rest
)*)
479 ($finish
:ident ($
($found
:ident
)*) $ignore
:tt $
($rest
:tt
)*) => {
480 pounded_var_names
!($
finish ($
($found
)*) $
($rest
)*)
483 ($finish
:ident ($
($found
:ident
)*)) => {
484 $finish
!(() $
($found
)*)
488 // in: nested_tuples_pat!(() a b c d e)
489 // out: ((((a b) c) d) e)
491 // in: nested_tuples_pat!(() a)
493 #[macro_export(local_inner_macros)]
495 macro_rules
! nested_tuples_pat
{
500 (() $first
:ident $
($rest
:ident
)*) => {
501 nested_tuples_pat
!(($first
) $
($rest
)*)
504 (($pat
:pat
) $first
:ident $
($rest
:ident
)*) => {
505 nested_tuples_pat
!((($pat
, $first
)) $
($rest
)*)
513 // in: multi_zip_expr!(() a b c d e)
514 // out: a.into_iter().zip(b).zip(c).zip(d).zip(e)
516 // in: multi_zip_iter!(() a)
518 #[macro_export(local_inner_macros)]
520 macro_rules
! multi_zip_expr
{
525 (() $single
:ident
) => {
529 (() $first
:ident $
($rest
:ident
)*) => {
530 multi_zip_expr
!(($first
.into_iter()) $
($rest
)*)
533 (($zips
:expr
) $first
:ident $
($rest
:ident
)*) => {
534 multi_zip_expr
!(($zips
.zip($first
)) $
($rest
)*)
542 #[macro_export(local_inner_macros)]
544 macro_rules
! quote_each_token
{
545 ($tokens
:ident $span
:ident
) => {}
;
547 ($tokens
:ident $span
:ident
# ! $($rest:tt)*) => {
548 quote_each_token
!($tokens $span
#);
549 quote_each_token
!($tokens $span
!);
550 quote_each_token
!($tokens $span $
($rest
)*);
553 ($tokens
:ident $span
:ident
# ( $($inner:tt)* ) * $($rest:tt)*) => {
554 for pounded_var_names
!(nested_tuples_pat () $
($inner
)*)
555 in pounded_var_names
!(multi_zip_expr () $
($inner
)*) {
556 quote_each_token
!($tokens $span $
($inner
)*);
558 quote_each_token
!($tokens $span $
($rest
)*);
561 ($tokens
:ident $span
:ident
# ( $($inner:tt)* ) $sep:tt * $($rest:tt)*) => {
562 for (_i
, pounded_var_names
!(nested_tuples_pat () $
($inner
)*))
563 in pounded_var_names
!(multi_zip_expr () $
($inner
)*).into_iter().enumerate() {
565 quote_each_token
!($tokens $span $sep
);
567 quote_each_token
!($tokens $span $
($inner
)*);
569 quote_each_token
!($tokens $span $
($rest
)*);
572 ($tokens
:ident $span
:ident
# [ $($inner:tt)* ] $($rest:tt)*) => {
573 quote_each_token
!($tokens $span
#);
575 let mut g
= $
crate::__rt
::Group
::new(
576 $
crate::__rt
::Delimiter
::Bracket
,
577 quote_spanned
!($span
=> $
($inner
)*),
580 Some($
crate::__rt
::TokenTree
::from(g
))
582 quote_each_token
!($tokens $span $
($rest
)*);
585 ($tokens
:ident $span
:ident
# $first:ident $($rest:tt)*) => {
586 $
crate::ToTokens
::to_tokens(&$first
, &mut $tokens
);
587 quote_each_token
!($tokens $span $
($rest
)*);
590 ($tokens
:ident $span
:ident ( $
($first
:tt
)* ) $
($rest
:tt
)*) => {
592 let mut g
= $
crate::__rt
::Group
::new(
593 $
crate::__rt
::Delimiter
::Parenthesis
,
594 quote_spanned
!($span
=> $
($first
)*),
597 Some($
crate::__rt
::TokenTree
::from(g
))
599 quote_each_token
!($tokens $span $
($rest
)*);
602 ($tokens
:ident $span
:ident
[ $
($first
:tt
)* ] $
($rest
:tt
)*) => {
604 let mut g
= $
crate::__rt
::Group
::new(
605 $
crate::__rt
::Delimiter
::Bracket
,
606 quote_spanned
!($span
=> $
($first
)*),
609 Some($
crate::__rt
::TokenTree
::from(g
))
611 quote_each_token
!($tokens $span $
($rest
)*);
614 ($tokens
:ident $span
:ident { $($first:tt)* } $
($rest
:tt
)*) => {
616 let mut g
= $
crate::__rt
::Group
::new(
617 $
crate::__rt
::Delimiter
::Brace
,
618 quote_spanned
!($span
=> $
($first
)*),
621 Some($
crate::__rt
::TokenTree
::from(g
))
623 quote_each_token
!($tokens $span $
($rest
)*);
626 ($tokens
:ident $span
:ident
+ $
($rest
:tt
)*) => {
627 $
crate::__rt
::push_add(&mut $tokens
, $span
);
628 quote_each_token
!($tokens $span $
($rest
)*);
631 ($tokens
:ident $span
:ident
+= $
($rest
:tt
)*) => {
632 $
crate::__rt
::push_add_eq(&mut $tokens
, $span
);
633 quote_each_token
!($tokens $span $
($rest
)*);
636 ($tokens
:ident $span
:ident
& $
($rest
:tt
)*) => {
637 $
crate::__rt
::push_and(&mut $tokens
, $span
);
638 quote_each_token
!($tokens $span $
($rest
)*);
641 ($tokens
:ident $span
:ident
&& $
($rest
:tt
)*) => {
642 $
crate::__rt
::push_and_and(&mut $tokens
, $span
);
643 quote_each_token
!($tokens $span $
($rest
)*);
646 ($tokens
:ident $span
:ident
&= $
($rest
:tt
)*) => {
647 $
crate::__rt
::push_and_eq(&mut $tokens
, $span
);
648 quote_each_token
!($tokens $span $
($rest
)*);
651 ($tokens
:ident $span
:ident @ $
($rest
:tt
)*) => {
652 $
crate::__rt
::push_at(&mut $tokens
, $span
);
653 quote_each_token
!($tokens $span $
($rest
)*);
656 ($tokens
:ident $span
:ident
! $
($rest
:tt
)*) => {
657 $
crate::__rt
::push_bang(&mut $tokens
, $span
);
658 quote_each_token
!($tokens $span $
($rest
)*);
661 ($tokens
:ident $span
:ident ^ $
($rest
:tt
)*) => {
662 $
crate::__rt
::push_caret(&mut $tokens
, $span
);
663 quote_each_token
!($tokens $span $
($rest
)*);
666 ($tokens
:ident $span
:ident ^
= $
($rest
:tt
)*) => {
667 $
crate::__rt
::push_caret_eq(&mut $tokens
, $span
);
668 quote_each_token
!($tokens $span $
($rest
)*);
671 ($tokens
:ident $span
:ident
: $
($rest
:tt
)*) => {
672 $
crate::__rt
::push_colon(&mut $tokens
, $span
);
673 quote_each_token
!($tokens $span $
($rest
)*);
676 ($tokens
:ident $span
:ident
:: $
($rest
:tt
)*) => {
677 $
crate::__rt
::push_colon2(&mut $tokens
, $span
);
678 quote_each_token
!($tokens $span $
($rest
)*);
681 ($tokens
:ident $span
:ident
, $
($rest
:tt
)*) => {
682 $
crate::__rt
::push_comma(&mut $tokens
, $span
);
683 quote_each_token
!($tokens $span $
($rest
)*);
686 ($tokens
:ident $span
:ident
/ $
($rest
:tt
)*) => {
687 $
crate::__rt
::push_div(&mut $tokens
, $span
);
688 quote_each_token
!($tokens $span $
($rest
)*);
691 ($tokens
:ident $span
:ident
/= $
($rest
:tt
)*) => {
692 $
crate::__rt
::push_div_eq(&mut $tokens
, $span
);
693 quote_each_token
!($tokens $span $
($rest
)*);
696 ($tokens
:ident $span
:ident
. $
($rest
:tt
)*) => {
697 $
crate::__rt
::push_dot(&mut $tokens
, $span
);
698 quote_each_token
!($tokens $span $
($rest
)*);
701 ($tokens
:ident $span
:ident
.. $
($rest
:tt
)*) => {
702 $
crate::__rt
::push_dot2(&mut $tokens
, $span
);
703 quote_each_token
!($tokens $span $
($rest
)*);
706 ($tokens
:ident $span
:ident
... $
($rest
:tt
)*) => {
707 $
crate::__rt
::push_dot3(&mut $tokens
, $span
);
708 quote_each_token
!($tokens $span $
($rest
)*);
711 ($tokens
:ident $span
:ident
..= $
($rest
:tt
)*) => {
712 $
crate::__rt
::push_dot_dot_eq(&mut $tokens
, $span
);
713 quote_each_token
!($tokens $span $
($rest
)*);
716 ($tokens
:ident $span
:ident
= $
($rest
:tt
)*) => {
717 $
crate::__rt
::push_eq(&mut $tokens
, $span
);
718 quote_each_token
!($tokens $span $
($rest
)*);
721 ($tokens
:ident $span
:ident
== $
($rest
:tt
)*) => {
722 $
crate::__rt
::push_eq_eq(&mut $tokens
, $span
);
723 quote_each_token
!($tokens $span $
($rest
)*);
726 ($tokens
:ident $span
:ident
>= $
($rest
:tt
)*) => {
727 $
crate::__rt
::push_ge(&mut $tokens
, $span
);
728 quote_each_token
!($tokens $span $
($rest
)*);
731 ($tokens
:ident $span
:ident
> $
($rest
:tt
)*) => {
732 $
crate::__rt
::push_gt(&mut $tokens
, $span
);
733 quote_each_token
!($tokens $span $
($rest
)*);
736 ($tokens
:ident $span
:ident
<= $
($rest
:tt
)*) => {
737 $
crate::__rt
::push_le(&mut $tokens
, $span
);
738 quote_each_token
!($tokens $span $
($rest
)*);
741 ($tokens
:ident $span
:ident
< $
($rest
:tt
)*) => {
742 $
crate::__rt
::push_lt(&mut $tokens
, $span
);
743 quote_each_token
!($tokens $span $
($rest
)*);
746 ($tokens
:ident $span
:ident
*= $
($rest
:tt
)*) => {
747 $
crate::__rt
::push_mul_eq(&mut $tokens
, $span
);
748 quote_each_token
!($tokens $span $
($rest
)*);
751 ($tokens
:ident $span
:ident
!= $
($rest
:tt
)*) => {
752 $
crate::__rt
::push_ne(&mut $tokens
, $span
);
753 quote_each_token
!($tokens $span $
($rest
)*);
756 ($tokens
:ident $span
:ident
| $
($rest
:tt
)*) => {
757 $
crate::__rt
::push_or(&mut $tokens
, $span
);
758 quote_each_token
!($tokens $span $
($rest
)*);
761 ($tokens
:ident $span
:ident
|= $
($rest
:tt
)*) => {
762 $
crate::__rt
::push_or_eq(&mut $tokens
, $span
);
763 quote_each_token
!($tokens $span $
($rest
)*);
766 ($tokens
:ident $span
:ident
|| $
($rest
:tt
)*) => {
767 $
crate::__rt
::push_or_or(&mut $tokens
, $span
);
768 quote_each_token
!($tokens $span $
($rest
)*);
771 ($tokens
:ident $span
:ident
# $($rest:tt)*) => {
772 $
crate::__rt
::push_pound(&mut $tokens
, $span
);
773 quote_each_token
!($tokens $span $
($rest
)*);
776 ($tokens
:ident $span
:ident ? $
($rest
:tt
)*) => {
777 $
crate::__rt
::push_question(&mut $tokens
, $span
);
778 quote_each_token
!($tokens $span $
($rest
)*);
781 ($tokens
:ident $span
:ident
-> $
($rest
:tt
)*) => {
782 $
crate::__rt
::push_rarrow(&mut $tokens
, $span
);
783 quote_each_token
!($tokens $span $
($rest
)*);
786 ($tokens
:ident $span
:ident
<- $
($rest
:tt
)*) => {
787 $
crate::__rt
::push_larrow(&mut $tokens
, $span
);
788 quote_each_token
!($tokens $span $
($rest
)*);
791 ($tokens
:ident $span
:ident
% $
($rest
:tt
)*) => {
792 $
crate::__rt
::push_rem(&mut $tokens
, $span
);
793 quote_each_token
!($tokens $span $
($rest
)*);
796 ($tokens
:ident $span
:ident
%= $
($rest
:tt
)*) => {
797 $
crate::__rt
::push_rem_eq(&mut $tokens
, $span
);
798 quote_each_token
!($tokens $span $
($rest
)*);
801 ($tokens
:ident $span
:ident
=> $
($rest
:tt
)*) => {
802 $
crate::__rt
::push_fat_arrow(&mut $tokens
, $span
);
803 quote_each_token
!($tokens $span $
($rest
)*);
806 ($tokens
:ident $span
:ident
; $
($rest
:tt
)*) => {
807 $
crate::__rt
::push_semi(&mut $tokens
, $span
);
808 quote_each_token
!($tokens $span $
($rest
)*);
811 ($tokens
:ident $span
:ident
<< $
($rest
:tt
)*) => {
812 $
crate::__rt
::push_shl(&mut $tokens
, $span
);
813 quote_each_token
!($tokens $span $
($rest
)*);
816 ($tokens
:ident $span
:ident
<<= $
($rest
:tt
)*) => {
817 $
crate::__rt
::push_shl_eq(&mut $tokens
, $span
);
818 quote_each_token
!($tokens $span $
($rest
)*);
821 ($tokens
:ident $span
:ident
>> $
($rest
:tt
)*) => {
822 $
crate::__rt
::push_shr(&mut $tokens
, $span
);
823 quote_each_token
!($tokens $span $
($rest
)*);
826 ($tokens
:ident $span
:ident
>>= $
($rest
:tt
)*) => {
827 $
crate::__rt
::push_shr_eq(&mut $tokens
, $span
);
828 quote_each_token
!($tokens $span $
($rest
)*);
831 ($tokens
:ident $span
:ident
* $
($rest
:tt
)*) => {
832 $
crate::__rt
::push_star(&mut $tokens
, $span
);
833 quote_each_token
!($tokens $span $
($rest
)*);
836 ($tokens
:ident $span
:ident
- $
($rest
:tt
)*) => {
837 $
crate::__rt
::push_sub(&mut $tokens
, $span
);
838 quote_each_token
!($tokens $span $
($rest
)*);
841 ($tokens
:ident $span
:ident
-= $
($rest
:tt
)*) => {
842 $
crate::__rt
::push_sub_eq(&mut $tokens
, $span
);
843 quote_each_token
!($tokens $span $
($rest
)*);
846 ($tokens
:ident $span
:ident $first
:tt $
($rest
:tt
)*) => {
847 $
crate::__rt
::parse(&mut $tokens
, $span
, quote_stringify
!($first
));
848 quote_each_token
!($tokens $span $
($rest
)*);
852 // Unhygienically invoke whatever `stringify` the caller has in scope i.e. not a
853 // local macro. The macros marked `local_inner_macros` above cannot invoke
854 // `stringify` directly.
857 macro_rules
! quote_stringify
{