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