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