README.md
1Rust Quasi-Quoting
2==================
3
4[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/quote-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/quote)
5[<img alt="crates.io" src="https://img.shields.io/crates/v/quote.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/quote)
6[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-quote-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/quote)
7[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/quote/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/quote/actions?query=branch%3Amaster)
8
9This crate provides the [`quote!`] macro for turning Rust syntax tree data
10structures into tokens of source code.
11
12[`quote!`]: https://docs.rs/quote/1.0/quote/macro.quote.html
13
14Procedural macros in Rust receive a stream of tokens as input, execute arbitrary
15Rust code to determine how to manipulate those tokens, and produce a stream of
16tokens to hand back to the compiler to compile into the caller's crate.
17Quasi-quoting is a solution to one piece of that — producing tokens to
18return to the compiler.
19
20The idea of quasi-quoting is that we write *code* that we treat as *data*.
21Within the `quote!` macro, we can write what looks like code to our text editor
22or IDE. We get all the benefits of the editor's brace matching, syntax
23highlighting, indentation, and maybe autocompletion. But rather than compiling
24that as code into the current crate, we can treat it as data, pass it around,
25mutate it, and eventually hand it back to the compiler as tokens to compile into
26the macro caller's crate.
27
28This crate is motivated by the procedural macro use case, but is a
29general-purpose Rust quasi-quoting library and is not specific to procedural
30macros.
31
32```toml
33[dependencies]
34quote = "1.0"
35```
36
37*Version requirement: Quote supports rustc 1.56 and up.*<br>
38[*Release notes*](https://github.com/dtolnay/quote/releases)
39
40<br>
41
42## Syntax
43
44The quote crate provides a [`quote!`] macro within which you can write Rust code
45that gets packaged into a [`TokenStream`] and can be treated as data. You should
46think of `TokenStream` as representing a fragment of Rust source code.
47
48[`TokenStream`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.TokenStream.html
49
50Within the `quote!` macro, interpolation is done with `#var`. Any type
51implementing the [`quote::ToTokens`] trait can be interpolated. This includes
52most Rust primitive types as well as most of the syntax tree types from [`syn`].
53
54[`quote::ToTokens`]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html
55[`syn`]: https://github.com/dtolnay/syn
56
57```rust
58let tokens = quote! {
59 struct SerializeWith #generics #where_clause {
60 value: &'a #field_ty,
61 phantom: core::marker::PhantomData<#item_ty>,
62 }
63
64 impl #generics serde::Serialize for SerializeWith #generics #where_clause {
65 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
66 where
67 S: serde::Serializer,
68 {
69 #path(self.value, serializer)
70 }
71 }
72
73 SerializeWith {
74 value: #value,
75 phantom: core::marker::PhantomData::<#item_ty>,
76 }
77};
78```
79
80<br>
81
82## Repetition
83
84Repetition is done using `#(...)*` or `#(...),*` similar to `macro_rules!`. This
85iterates through the elements of any variable interpolated within the repetition
86and inserts a copy of the repetition body for each one. The variables in an
87interpolation may be a `Vec`, slice, `BTreeSet`, or any `Iterator`.
88
89- `#(#var)*` — no separators
90- `#(#var),*` — the character before the asterisk is used as a separator
91- `#( struct #var; )*` — the repetition can contain other things
92- `#( #k => println!("{}", #v), )*` — even multiple interpolations
93
94Note that there is a difference between `#(#var ,)*` and `#(#var),*`—the latter
95does not produce a trailing comma. This matches the behavior of delimiters in
96`macro_rules!`.
97
98<br>
99
100## Returning tokens to the compiler
101
102The `quote!` macro evaluates to an expression of type
103`proc_macro2::TokenStream`. Meanwhile Rust procedural macros are expected to
104return the type `proc_macro::TokenStream`.
105
106The difference between the two types is that `proc_macro` types are entirely
107specific to procedural macros and cannot ever exist in code outside of a
108procedural macro, while `proc_macro2` types may exist anywhere including tests
109and non-macro code like main.rs and build.rs. This is why even the procedural
110macro ecosystem is largely built around `proc_macro2`, because that ensures the
111libraries are unit testable and accessible in non-macro contexts.
112
113There is a [`From`]-conversion in both directions so returning the output of
114`quote!` from a procedural macro usually looks like `tokens.into()` or
115`proc_macro::TokenStream::from(tokens)`.
116
117[`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
118
119<br>
120
121## Examples
122
123### Combining quoted fragments
124
125Usually you don't end up constructing an entire final `TokenStream` in one
126piece. Different parts may come from different helper functions. The tokens
127produced by `quote!` themselves implement `ToTokens` and so can be interpolated
128into later `quote!` invocations to build up a final result.
129
130```rust
131let type_definition = quote! {...};
132let methods = quote! {...};
133
134let tokens = quote! {
135 #type_definition
136 #methods
137};
138```
139
140### Constructing identifiers
141
142Suppose we have an identifier `ident` which came from somewhere in a macro
143input and we need to modify it in some way for the macro output. Let's consider
144prepending the identifier with an underscore.
145
146Simply interpolating the identifier next to an underscore will not have the
147behavior of concatenating them. The underscore and the identifier will continue
148to be two separate tokens as if you had written `_ x`.
149
150```rust
151// incorrect
152quote! {
153 let mut _#ident = 0;
154}
155```
156
157The solution is to build a new identifier token with the correct value. As this
158is such a common case, the `format_ident!` macro provides a convenient utility
159for doing so correctly.
160
161```rust
162let varname = format_ident!("_{}", ident);
163quote! {
164 let mut #varname = 0;
165}
166```
167
168Alternatively, the APIs provided by Syn and proc-macro2 can be used to directly
169build the identifier. This is roughly equivalent to the above, but will not
170handle `ident` being a raw identifier.
171
172```rust
173let concatenated = format!("_{}", ident);
174let varname = syn::Ident::new(&concatenated, ident.span());
175quote! {
176 let mut #varname = 0;
177}
178```
179
180### Making method calls
181
182Let's say our macro requires some type specified in the macro input to have a
183constructor called `new`. We have the type in a variable called `field_type` of
184type `syn::Type` and want to invoke the constructor.
185
186```rust
187// incorrect
188quote! {
189 let value = #field_type::new();
190}
191```
192
193This works only sometimes. If `field_type` is `String`, the expanded code
194contains `String::new()` which is fine. But if `field_type` is something like
195`Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid syntax.
196Ordinarily in handwritten Rust we would write `Vec::<i32>::new()` but for macros
197often the following is more convenient.
198
199```rust
200quote! {
201 let value = <#field_type>::new();
202}
203```
204
205This expands to `<Vec<i32>>::new()` which behaves correctly.
206
207A similar pattern is appropriate for trait methods.
208
209```rust
210quote! {
211 let value = <#field_type as core::default::Default>::default();
212}
213```
214
215<br>
216
217## Hygiene
218
219Any interpolated tokens preserve the `Span` information provided by their
220`ToTokens` implementation. Tokens that originate within a `quote!` invocation
221are spanned with [`Span::call_site()`].
222
223[`Span::call_site()`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html#method.call_site
224
225A different span can be provided explicitly through the [`quote_spanned!`]
226macro.
227
228[`quote_spanned!`]: https://docs.rs/quote/1.0/quote/macro.quote_spanned.html
229
230<br>
231
232## Non-macro code generators
233
234When using `quote` in a build.rs or main.rs and writing the output out to a
235file, consider having the code generator pass the tokens through [prettyplease]
236before writing. This way if an error occurs in the generated code it is
237convenient for a human to read and debug.
238
239Be aware that no kind of hygiene or span information is retained when tokens are
240written to a file; the conversion from tokens to source code is lossy.
241
242Example usage in build.rs:
243
244```rust
245let output = quote! { ... };
246let syntax_tree = syn::parse2(output).unwrap();
247let formatted = prettyplease::unparse(&syntax_tree);
248
249let out_dir = env::var_os("OUT_DIR").unwrap();
250let dest_path = Path::new(&out_dir).join("out.rs");
251fs::write(dest_path, formatted).unwrap();
252```
253
254[prettyplease]: https://github.com/dtolnay/prettyplease
255
256<br>
257
258#### License
259
260<sup>
261Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2622.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
263</sup>
264
265<br>
266
267<sub>
268Unless you explicitly state otherwise, any contribution intentionally submitted
269for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
270be dual licensed as above, without any additional terms or conditions.
271</sub>
272