proc_quote/lib.rs
1//! This crate provides the [`quote!`] macro for turning Rust syntax tree data
2//! structures into tokens of source code.
3//!
4//! [`quote!`]: macro.quote.html
5//!
6//! Procedural macros in Rust receive a stream of tokens as input, execute
7//! arbitrary Rust code to determine how to manipulate those tokens, and produce
8//! a stream of tokens to hand back to the compiler to compile into the caller's
9//! crate. Quasi-quoting is a solution to one piece of that -- producing tokens
10//! to return to the compiler.
11//!
12//! The idea of quasi-quoting is that we write *code* that we treat as *data*.
13//! Within the `quote!` macro, we can write what looks like code to our text
14//! editor or IDE. We get all the benefits of the editor's brace matching,
15//! syntax highlighting, indentation, and maybe autocompletion. But rather than
16//! compiling that as code into the current crate, we can treat it as data, pass
17//! it around, mutate it, and eventually hand it back to the compiler as tokens
18//! to compile into the macro caller's crate.
19//!
20//! This crate is motivated by the procedural macro use case, but it is a
21//! general-purpose Rust quasi-quoting library and is not specific to procedural
22//! macros.
23//!
24//! # Example
25//!
26//! The following quasi-quoted block of code is something you might find in [a]
27//! procedural macro having to do with data structure serialization. The `#var`
28//! syntax performs interpolation of runtime variables into the quoted tokens.
29//! Check out the documentation of the [`quote!`] macro for more detail about
30//! the syntax. See also the [`quote_spanned!`] macro which is important for
31//! implementing hygienic procedural macros.
32//!
33//! [a]: https://serde.rs/
34//! [`quote_spanned!`]: macro.quote_spanned.html
35//!
36//! ```edition2018
37//! # use quote::quote;
38//! #
39//! # let generics = "";
40//! # let where_clause = "";
41//! # let field_ty = "";
42//! # let item_ty = "";
43//! # let path = "";
44//! # let value = "";
45//! #
46//! let tokens = quote! {
47//! struct SerializeWith #generics #where_clause {
48//! value: &'a #field_ty,
49//! phantom: core::marker::PhantomData<#item_ty>,
50//! }
51//!
52//! impl #generics serde::Serialize for SerializeWith #generics #where_clause {
53//! fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
54//! where
55//! S: serde::Serializer,
56//! {
57//! #path(self.value, serializer)
58//! }
59//! }
60//!
61//! SerializeWith {
62//! value: #value,
63//! phantom: core::marker::PhantomData::<#item_ty>,
64//! }
65//! };
66//! ```
67use proc_macro_hack::proc_macro_hack;
68
69mod repeat;
70
71pub use self::repeat::*;
72pub use quote::ToTokens;
73pub use quote::TokenStreamExt;
74
75/// The whole point.
76///
77/// Performs variable interpolation against the input and produces it as
78/// [`TokenStream`]. For returning tokens to the compiler in a procedural macro, use
79/// `into()` to build a `TokenStream`.
80///
81/// [`TokenStream`]: https://docs.rs/proc-macro2/0/proc_macro2/struct.TokenStream.html
82///
83/// # Interpolation
84///
85/// Variable interpolation is done with `#var` (similar to `$var` in
86/// `macro_rules!` macros). This grabs the `var` variable that is currently in
87/// scope and inserts it in that location in the output tokens. Any type
88/// implementing the [`ToTokens`] trait can be interpolated. This includes most
89/// Rust primitive types as well as most of the syntax tree types from the [Syn]
90/// crate.
91///
92/// [`ToTokens`]: trait.ToTokens.html
93/// [Syn]: https://github.com/dtolnay/syn
94///
95/// Repetition is done using `#(...)*` or `#(...),*` again similar to
96/// `macro_rules!`. This iterates through the elements of any variable
97/// interpolated within the repetition and inserts a copy of the repetition
98/// body for each one.
99///
100/// - `#(#var)*` — no separators
101/// - `#(#var),*` — the character before the asterisk is used as a separator
102/// - `#( struct #var; )*` — the repetition can contain other tokens
103/// - `#( #k => println!("{}", #v), )*` — even multiple interpolations
104/// - `#(let #var = self.#var;)*` - the same variable can be used more than once
105///
106/// The [`proc_quote::Repeat`](https://docs.rs/proc-quote/0/proc_quote/trait.Repeat.html)
107/// trait defines which types are allowed to be interpolated inside a repition pattern.
108///
109/// Which types that implement the following traits *do* `Repeat`:
110/// - [`Iterator<T>`] consumes the iterator, iterating through every element.
111/// - <a href="https://doc.rust-lang.org/std/borrow/trait.Borrow.html">`Borrow<[T]>`</a>
112/// (includes [`Vec`], [`array`], and [`slice`]) iterates with the [`slice::iter`] method,
113/// thus not consuming the original data.
114/// - [`ToTokens`], interpolates the variable in every iteration.
115///
116/// Which types *do NOT* `Repeat`:
117/// - [`IntoIterator`], to avoid ambiguity (Ex. "Which behavior would have been used for [`Vec`],
118/// which implements both [`IntoIterator`] and <a href="https://doc.rust-lang.org/std/borrow/trait.Borrow.html">
119/// `Borrow<[T]>`</a>?"; "Which behavior would have been used for [`TokenStream`], which implements both
120/// [`IntoIterator`] and [`ToTokens`]?"). To use the iterator, you may call [`IntoIterator::into_iter`]
121/// explicitly.
122/// - Ambiguous types that implement at least two of the `Repeat` traits. In the very unlikely case
123/// this happens, disambiguate the type by wrapping it under some structure that only implements the
124/// trait you desire to use.
125///
126/// [`Iterator<T>`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
127/// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
128/// [`array`]: https://doc.rust-lang.org/std/primitive.array.html
129/// [`slice`]: https://doc.rust-lang.org/std/slice/index.html
130/// [`slice::iter`]: https://doc.rust-lang.org/std/primitive.slice.html#method.iter
131/// [`ToTokens`]: https://docs.rs/proc-quote/0/proc_quote/trait.ToTokens.html
132/// [`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html
133/// [`IntoIterator::into_iter`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html#tymethod.into_iter
134///
135/// # Hygiene
136///
137/// Any interpolated tokens preserve the `Span` information provided by their
138/// `ToTokens` implementation. Tokens that originate within the `quote!`
139/// invocation are spanned with [`Span::call_site()`].
140///
141/// [`Span::call_site()`]: https://docs.rs/proc-macro2/0/proc_macro2/struct.Span.html#method.call_site
142///
143/// A different span can be provided through the [`quote_spanned!`] macro.
144///
145/// [`quote_spanned!`]: macro.quote_spanned.html
146///
147/// # Return type
148///
149/// The macro evaluates to an expression of type `proc_macro2::TokenStream`.
150/// Meanwhile Rust procedural macros are expected to return the type
151/// `proc_macro::TokenStream`.
152///
153/// The difference between the two types is that `proc_macro` types are entirely
154/// specific to procedural macros and cannot ever exist in code outside of a
155/// procedural macro, while `proc_macro2` types may exist anywhere including
156/// tests and non-macro code like main.rs and build.rs. This is why even the
157/// procedural macro ecosystem is largely built around `proc_macro2`, because
158/// that ensures the libraries are unit testable and accessible in non-macro
159/// contexts.
160///
161/// There is a [`From`]-conversion in both directions so returning the output of
162/// `quote!` from a procedural macro usually looks like `tokens.into()` or
163/// `proc_macro::TokenStream::from(tokens)`.
164///
165/// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
166///
167/// # Examples
168///
169/// ## Procedural macro
170///
171/// The structure of a basic procedural macro is as follows. Refer to the [Syn]
172/// crate for further useful guidance on using `quote!` as part of a procedural
173/// macro.
174///
175/// [Syn]: https://github.com/dtolnay/syn
176///
177/// ```edition2018
178/// # #[cfg(any())]
179/// extern crate proc_macro;
180/// # use proc_macro2 as proc_macro;
181///
182/// use proc_macro::TokenStream;
183/// use quote::quote;
184///
185/// # const IGNORE_TOKENS: &'static str = stringify! {
186/// #[proc_macro_derive(HeapSize)]
187/// # };
188/// pub fn derive_heap_size(input: TokenStream) -> TokenStream {
189/// // Parse the input and figure out what implementation to generate...
190/// # const IGNORE_TOKENS: &'static str = stringify! {
191/// let name = /* ... */;
192/// let expr = /* ... */;
193/// # };
194/// #
195/// # let name = 0;
196/// # let expr = 0;
197///
198/// let expanded = quote! {
199/// // The generated impl.
200/// impl heapsize::HeapSize for #name {
201/// fn heap_size_of_children(&self) -> usize {
202/// #expr
203/// }
204/// }
205/// };
206///
207/// // Hand the output tokens back to the compiler.
208/// TokenStream::from(expanded)
209/// }
210/// ```
211///
212/// ## Combining quoted fragments
213///
214/// Usually you don't end up constructing an entire final `TokenStream` in one
215/// piece. Different parts may come from different helper functions. The tokens
216/// produced by `quote!` themselves implement `ToTokens` and so can be
217/// interpolated into later `quote!` invocations to build up a final result.
218///
219/// ```edition2018
220/// # use quote::quote;
221/// #
222/// let type_definition = quote! {...};
223/// let methods = quote! {...};
224///
225/// let tokens = quote! {
226/// #type_definition
227/// #methods
228/// };
229/// ```
230///
231/// ## Constructing identifiers
232///
233/// Suppose we have an identifier `ident` which came from somewhere in a macro
234/// input and we need to modify it in some way for the macro output. Let's
235/// consider prepending the identifier with an underscore.
236///
237/// Simply interpolating the identifier next to an underscore will not have the
238/// behavior of concatenating them. The underscore and the identifier will
239/// continue to be two separate tokens as if you had written `_ x`.
240///
241/// ```edition2018
242/// # use proc_macro2::{self as syn, Span};
243/// # use quote::quote;
244/// #
245/// # let ident = syn::Ident::new("i", Span::call_site());
246/// #
247/// // incorrect
248/// quote! {
249/// let mut _#ident = 0;
250/// }
251/// # ;
252/// ```
253///
254/// The solution is to perform token-level manipulations using the APIs provided
255/// by Syn and proc-macro2.
256///
257/// ```edition2018
258/// # use proc_macro2::{self as syn, Span};
259/// # use quote::quote;
260/// #
261/// # let ident = syn::Ident::new("i", Span::call_site());
262/// #
263/// let concatenated = format!("_{}", ident);
264/// let varname = syn::Ident::new(&concatenated, ident.span());
265/// quote! {
266/// let mut #varname = 0;
267/// }
268/// # ;
269/// ```
270///
271/// ## Making method calls
272///
273/// Let's say our macro requires some type specified in the macro input to have
274/// a constructor called `new`. We have the type in a variable called
275/// `field_type` of type `syn::Type` and want to invoke the constructor.
276///
277/// ```edition2018
278/// # use quote::quote;
279/// #
280/// # let field_type = quote!(...);
281/// #
282/// // incorrect
283/// quote! {
284/// let value = #field_type::new();
285/// }
286/// # ;
287/// ```
288///
289/// This works only sometimes. If `field_type` is `String`, the expanded code
290/// contains `String::new()` which is fine. But if `field_type` is something
291/// like `Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid
292/// syntax. Ordinarily in handwritten Rust we would write `Vec::<i32>::new()`
293/// but for macros often the following is more convenient.
294///
295/// ```edition2018
296/// # use quote::quote;
297/// #
298/// # let field_type = quote!(...);
299/// #
300/// quote! {
301/// let value = <#field_type>::new();
302/// }
303/// # ;
304/// ```
305///
306/// This expands to `<Vec<i32>>::new()` which behaves correctly.
307///
308/// A similar pattern is appropriate for trait methods.
309///
310/// ```edition2018
311/// # use quote::quote;
312/// #
313/// # let field_type = quote!(...);
314/// #
315/// quote! {
316/// let value = <#field_type as core::default::Default>::default();
317/// }
318/// # ;
319/// ```
320#[proc_macro_hack]
321pub use proc_quote_impl::quote;
322
323/// Same as `quote!`, but applies a given span to all tokens originating within
324/// the macro invocation.
325///
326/// # Syntax
327///
328/// A span expression of type [`Span`], followed by `=>`, followed by the tokens
329/// to quote. The span expression should be brief -- use a variable for anything
330/// more than a few characters. There should be no space before the `=>` token.
331///
332/// [`Span`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html
333///
334/// ```edition2018
335/// # use proc_macro2::Span;
336/// # use quote::quote_spanned;
337/// #
338/// # const IGNORE_TOKENS: &'static str = stringify! {
339/// let span = /* ... */;
340/// # };
341/// # let span = Span::call_site();
342/// # let init = 0;
343///
344/// // On one line, use parentheses.
345/// let tokens = quote_spanned!(span=> Box::into_raw(Box::new(#init)));
346///
347/// // On multiple lines, place the span at the top and use braces.
348/// let tokens = quote_spanned! {span=>
349/// Box::into_raw(Box::new(#init))
350/// };
351/// ```
352///
353/// The lack of space before the `=>` should look jarring to Rust programmers
354/// and this is intentional. The formatting is designed to be visibly
355/// off-balance and draw the eye a particular way, due to the span expression
356/// being evaluated in the context of the procedural macro and the remaining
357/// tokens being evaluated in the generated code.
358///
359/// # Hygiene
360///
361/// Any interpolated tokens preserve the `Span` information provided by their
362/// `ToTokens` implementation. Tokens that originate within the `quote_spanned!`
363/// invocation are spanned with the given span argument.
364///
365/// # Example
366///
367/// The following procedural macro code uses `quote_spanned!` to assert that a
368/// particular Rust type implements the [`Sync`] trait so that references can be
369/// safely shared between threads.
370///
371/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
372///
373/// ```edition2018
374/// # use quote::{quote_spanned, TokenStreamExt, ToTokens};
375/// # use proc_macro2::{Span, TokenStream};
376/// #
377/// # struct Type;
378/// #
379/// # impl Type {
380/// # fn span(&self) -> Span {
381/// # Span::call_site()
382/// # }
383/// # }
384/// #
385/// # impl ToTokens for Type {
386/// # fn to_tokens(&self, _tokens: &mut TokenStream) {}
387/// # }
388/// #
389/// # let ty = Type;
390/// # let call_site = Span::call_site();
391/// #
392/// let ty_span = ty.span();
393/// let assert_sync = quote_spanned! {ty_span=>
394/// struct _AssertSync where #ty: Sync;
395/// };
396/// ```
397///
398/// If the assertion fails, the user will see an error like the following. The
399/// input span of their type is hightlighted in the error.
400///
401/// ```text
402/// error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
403/// --> src/main.rs:10:21
404/// |
405/// 10 | static ref PTR: *const () = &();
406/// | ^^^^^^^^^ `*const ()` cannot be shared between threads safely
407/// ```
408///
409/// In this example it is important for the where-clause to be spanned with the
410/// line/column information of the user's input type so that error messages are
411/// placed appropriately by the compiler. But it is also incredibly important
412/// that `Sync` resolves at the macro definition site and not the macro call
413/// site. If we resolve `Sync` at the same span that the user's type is going to
414/// be resolved, then they could bypass our check by defining their own trait
415/// named `Sync` that is implemented for their type.
416#[proc_macro_hack]
417pub use proc_quote_impl::quote_spanned;
418
419// Not public API.
420#[doc(hidden)]
421pub mod __rt {
422 use super::*;
423 pub use proc_macro2::*;
424
425 pub fn append_ident(stream: &mut TokenStream, ident: &str, span: Span) {
426 // TODO(blocked on rust-lang/rust#54723)
427 // https://github.com/rust-lang/rust/issues/54723
428 // Use `new_raw` once it's stabilized
429 // stream.append(Ident::new_raw(ident, span));
430 match syn::parse_str::<Ident>(ident) {
431 Ok(mut ident) => {
432 ident.set_span(span);
433 stream.append(ident);
434 }
435 Err(_) => stream.append(Ident::new(ident, span)),
436 }
437 }
438
439 pub fn append_punct(stream: &mut TokenStream, punct: char, spacing: Spacing, span: Span) {
440 let mut punct = Punct::new(punct, spacing);
441 punct.set_span(span);
442 stream.append(punct);
443 }
444
445 pub fn append_stringified_tokens(stream: &mut TokenStream, s: &str, span: Span) {
446 let s: TokenStream = s.parse().expect("invalid token stream");
447 stream.extend(s.into_iter().map(|mut t| {
448 t.set_span(span);
449 t
450 }));
451 }
452
453 pub fn append_to_tokens<T: ToTokens>(stream: &mut TokenStream, to_tokens: &T) {
454 to_tokens.to_tokens(stream);
455 }
456
457 pub fn append_group(
458 stream: &mut TokenStream,
459 inner: TokenStream,
460 delimiter: Delimiter,
461 span: Span,
462 ) {
463 let mut group = Group::new(delimiter, inner);
464 group.set_span(span);
465 stream.append(group);
466 }
467}