]> git.proxmox.com Git - cargo.git/blob - vendor/quote/README.md
New upstream version 0.33.0
[cargo.git] / vendor / quote / README.md
1 Rust Quasi-Quoting
2 ==================
3
4 [![Build Status](https://api.travis-ci.org/dtolnay/quote.svg?branch=master)](https://travis-ci.org/dtolnay/quote)
5 [![Latest Version](https://img.shields.io/crates/v/quote.svg)](https://crates.io/crates/quote)
6 [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/quote/)
7
8 This crate provides the [`quote!`] macro for turning Rust syntax tree data
9 structures into tokens of source code.
10
11 [`quote!`]: https://docs.rs/quote/0.6/quote/macro.quote.html
12
13 Procedural macros in Rust receive a stream of tokens as input, execute arbitrary
14 Rust code to determine how to manipulate those tokens, and produce a stream of
15 tokens to hand back to the compiler to compile into the caller's crate.
16 Quasi-quoting is a solution to one piece of that -- producing tokens to return
17 to the compiler.
18
19 The idea of quasi-quoting is that we write *code* that we treat as *data*.
20 Within the `quote!` macro, we can write what looks like code to our text editor
21 or IDE. We get all the benefits of the editor's brace matching, syntax
22 highlighting, indentation, and maybe autocompletion. But rather than compiling
23 that as code into the current crate, we can treat it as data, pass it around,
24 mutate it, and eventually hand it back to the compiler as tokens to compile into
25 the macro caller's crate.
26
27 This crate is motivated by the procedural macro use case, but is a
28 general-purpose Rust quasi-quoting library and is not specific to procedural
29 macros.
30
31 *Version requirement: Quote supports any compiler version back to Rust's very
32 first support for procedural macros in Rust 1.15.0.*
33
34 [*Release notes*](https://github.com/dtolnay/quote/releases)
35
36 ```toml
37 [dependencies]
38 quote = "0.6"
39 ```
40
41 ## Syntax
42
43 The quote crate provides a [`quote!`] macro within which you can write Rust code
44 that gets packaged into a [`TokenStream`] and can be treated as data. You should
45 think of `TokenStream` as representing a fragment of Rust source code.
46
47 [`TokenStream`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.TokenStream.html
48
49 Within the `quote!` macro, interpolation is done with `#var`. Any type
50 implementing the [`quote::ToTokens`] trait can be interpolated. This includes
51 most Rust primitive types as well as most of the syntax tree types from [`syn`].
52
53 [`quote::ToTokens`]: https://docs.rs/quote/0.6/quote/trait.ToTokens.html
54 [`syn`]: https://github.com/dtolnay/syn
55
56 ```rust
57 let tokens = quote! {
58 struct SerializeWith #generics #where_clause {
59 value: &'a #field_ty,
60 phantom: core::marker::PhantomData<#item_ty>,
61 }
62
63 impl #generics serde::Serialize for SerializeWith #generics #where_clause {
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: serde::Serializer,
67 {
68 #path(self.value, serializer)
69 }
70 }
71
72 SerializeWith {
73 value: #value,
74 phantom: core::marker::PhantomData::<#item_ty>,
75 }
76 };
77 ```
78
79 ## Repetition
80
81 Repetition is done using `#(...)*` or `#(...),*` similar to `macro_rules!`. This
82 iterates through the elements of any variable interpolated within the repetition
83 and inserts a copy of the repetition body for each one. The variables in an
84 interpolation may be anything that implements `IntoIterator`, including `Vec` or
85 a pre-existing iterator.
86
87 - `#(#var)*` — no separators
88 - `#(#var),*` — the character before the asterisk is used as a separator
89 - `#( struct #var; )*` — the repetition can contain other things
90 - `#( #k => println!("{}", #v), )*` — even multiple interpolations
91
92 Note that there is a difference between `#(#var ,)*` and `#(#var),*`—the latter
93 does not produce a trailing comma. This matches the behavior of delimiters in
94 `macro_rules!`.
95
96 ## Returning tokens to the compiler
97
98 The `quote!` macro evaluates to an expression of type
99 `proc_macro2::TokenStream`. Meanwhile Rust procedural macros are expected to
100 return the type `proc_macro::TokenStream`.
101
102 The difference between the two types is that `proc_macro` types are entirely
103 specific to procedural macros and cannot ever exist in code outside of a
104 procedural macro, while `proc_macro2` types may exist anywhere including tests
105 and non-macro code like main.rs and build.rs. This is why even the procedural
106 macro ecosystem is largely built around `proc_macro2`, because that ensures the
107 libraries are unit testable and accessible in non-macro contexts.
108
109 There is a [`From`]-conversion in both directions so returning the output of
110 `quote!` from a procedural macro usually looks like `tokens.into()` or
111 `proc_macro::TokenStream::from(tokens)`.
112
113 [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
114
115 ## Examples
116
117 ### Combining quoted fragments
118
119 Usually you don't end up constructing an entire final `TokenStream` in one
120 piece. Different parts may come from different helper functions. The tokens
121 produced by `quote!` themselves implement `ToTokens` and so can be interpolated
122 into later `quote!` invocations to build up a final result.
123
124 ```rust
125 let type_definition = quote! {...};
126 let methods = quote! {...};
127
128 let tokens = quote! {
129 #type_definition
130 #methods
131 };
132 ```
133
134 ### Constructing identifiers
135
136 Suppose we have an identifier `ident` which came from somewhere in a macro
137 input and we need to modify it in some way for the macro output. Let's consider
138 prepending the identifier with an underscore.
139
140 Simply interpolating the identifier next to an underscore will not have the
141 behavior of concatenating them. The underscore and the identifier will continue
142 to be two separate tokens as if you had written `_ x`.
143
144 ```rust
145 // incorrect
146 quote! {
147 let mut _#ident = 0;
148 }
149 ```
150
151 The solution is to perform token-level manipulations using the APIs provided by
152 Syn and proc-macro2.
153
154 ```rust
155 let concatenated = format!("_{}", ident);
156 let varname = syn::Ident::new(&concatenated, ident.span());
157 quote! {
158 let mut #varname = 0;
159 }
160 ```
161
162 ### Making method calls
163
164 Let's say our macro requires some type specified in the macro input to have a
165 constructor called `new`. We have the type in a variable called `field_type` of
166 type `syn::Type` and want to invoke the constructor.
167
168 ```rust
169 // incorrect
170 quote! {
171 let value = #field_type::new();
172 }
173 ```
174
175 This works only sometimes. If `field_type` is `String`, the expanded code
176 contains `String::new()` which is fine. But if `field_type` is something like
177 `Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid syntax.
178 Ordinarily in handwritten Rust we would write `Vec::<i32>::new()` but for macros
179 often the following is more convenient.
180
181 ```rust
182 quote! {
183 let value = <#field_type>::new();
184 }
185 ```
186
187 This expands to `<Vec<i32>>::new()` which behaves correctly.
188
189 A similar pattern is appropriate for trait methods.
190
191 ```rust
192 quote! {
193 let value = <#field_type as core::default::Default>::default();
194 }
195 ```
196
197 ## Hygiene
198
199 Any interpolated tokens preserve the `Span` information provided by their
200 `ToTokens` implementation. Tokens that originate within a `quote!` invocation
201 are spanned with [`Span::call_site()`].
202
203 [`Span::call_site()`]: https://docs.rs/proc-macro2/0.4/proc_macro2/struct.Span.html#method.call_site
204
205 A different span can be provided explicitly through the [`quote_spanned!`]
206 macro.
207
208 [`quote_spanned!`]: https://docs.rs/quote/0.6/quote/macro.quote_spanned.html
209
210 ### Limitations
211
212 - A non-repeating variable may not be interpolated inside of a repeating block
213 ([#7]).
214 - The same variable may not be interpolated more than once inside of a repeating
215 block ([#8]).
216
217 [#7]: https://github.com/dtolnay/quote/issues/7
218 [#8]: https://github.com/dtolnay/quote/issues/8
219
220 ### Recursion limit
221
222 The `quote!` macro relies on deep recursion so some large invocations may fail
223 with "recursion limit reached" when you compile. If it fails, bump up the
224 recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even
225 higher limit may be necessary for especially large invocations. You don't need
226 this unless the compiler tells you that you need it.
227
228 ## License
229
230 Licensed under either of
231
232 * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
233 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
234
235 at your option.
236
237 ### Contribution
238
239 Unless you explicitly state otherwise, any contribution intentionally submitted
240 for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
241 be dual licensed as above, without any additional terms or conditions.