]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
1 | ## Procedural Macros |
2 | ||
abe05a73 | 3 | *Procedural macros* allow creating syntax extensions as execution of a function. |
b7449926 | 4 | Procedural macros come in one of three flavors: |
8bb4bdeb | 5 | |
b7449926 | 6 | * [Function-like macros] - `custom!(...)` |
532ac7d7 | 7 | * [Derive macros] - `#[derive(CustomDerive)]` |
b7449926 XL |
8 | * [Attribute macros] - `#[CustomAttribute]` |
9 | ||
10 | Procedural macros allow you to run code at compile time that operates over Rust | |
11 | syntax, both consuming and producing Rust syntax. You can sort of think of | |
12 | procedural macros as functions from an AST to another AST. | |
13 | ||
14 | Procedural macros must be defined in a crate with the [crate type] of | |
15 | `proc-macro`. | |
16 | ||
17 | > **Note**: When using Cargo, Procedural macro crates are defined with the | |
0bf4aa26 | 18 | > `proc-macro` key in your manifest: |
b7449926 XL |
19 | > |
20 | > ```toml | |
21 | > [lib] | |
22 | > proc-macro = true | |
23 | > ``` | |
24 | ||
25 | As functions, they must either return syntax, panic, or loop endlessly. Returned | |
26 | syntax either replaces or adds the syntax depending on the kind of procedural | |
27 | macro. Panics are caught by the compiler and are turned into a compiler error. | |
28 | Endless loops are not caught by the compiler which hangs the compiler. | |
29 | ||
30 | Procedural macros run during compilation, and thus have the same resources that | |
31 | the compiler has. For example, standard input, error, and output are the same | |
32 | that the compiler has access to. Similarly, file access is the same. Because | |
33 | of this, procedural macros have the same security concerns that [Cargo's | |
34 | build scripts] have. | |
35 | ||
36 | Procedural macros have two ways of reporting errors. The first is to panic. The | |
37 | second is to emit a [`compile_error`] macro invocation. | |
38 | ||
39 | ### The `proc_macro` crate | |
40 | ||
13cf67c4 | 41 | Procedural macro crates almost always will link to the compiler-provided |
b7449926 XL |
42 | [`proc_macro` crate]. The `proc_macro` crate provides types required for |
43 | writing procedural macros and facilities to make it easier. | |
44 | ||
45 | This crate primarily contains a [`TokenStream`] type. Procedural macros operate | |
46 | over *token streams* instead of AST nodes, which is a far more stable interface | |
47 | over time for both the compiler and for procedural macros to target. A | |
48 | *token stream* is roughly equivalent to `Vec<TokenTree>` where a `TokenTree` | |
49 | can roughly be thought of as lexical token. For example `foo` is an `Ident` | |
50 | token, `.` is a `Punct` token, and `1.2` is a `Literal` token. The `TokenStream` | |
51 | type, unlike `Vec<TokenTree>`, is cheap to clone. | |
52 | ||
53 | All tokens have an associated `Span`. A `Span` is an opaque value that cannot | |
54 | be modified but can be manufactured. `Span`s represent an extent of source | |
55 | code within a program and are primarily used for error reporting. You can modify | |
56 | the `Span` of any token. | |
57 | ||
58 | ### Procedural macro hygiene | |
59 | ||
60 | Procedural macros are *unhygienic*. This means they behave as if the output | |
61 | token stream was simply written inline to the code it's next to. This means that | |
62 | it's affected by external items and also affects external imports. | |
63 | ||
64 | Macro authors need to be careful to ensure their macros work in as many contexts | |
65 | as possible given this limitation. This often includes using absolute paths to | |
66 | items in libraries (for example, `::std::option::Option` instead of `Option`) or | |
67 | by ensuring that generated functions have names that are unlikely to clash with | |
68 | other functions (like `__internal_foo` instead of `foo`). | |
69 | ||
70 | ### Function-like procedural macros | |
71 | ||
72 | *Function-like procedural macros* are procedural macros that are invoked using | |
73 | the macro invocation operator (`!`). | |
74 | ||
75 | These macros are defined by a [public] [function] with the `proc_macro` | |
76 | [attribute] and a signature of `(TokenStream) -> TokenStream`. The input | |
77 | [`TokenStream`] is what is inside the delimiters of the macro invocation and the | |
78 | output [`TokenStream`] replaces the entire macro invocation. It may contain an | |
79 | arbitrary number of [items]. These macros cannot expand to syntax that defines | |
532ac7d7 | 80 | new `macro_rules` style macros. |
b7449926 XL |
81 | |
82 | For example, the following macro definition ignores its input and outputs a | |
83 | function `answer` into its scope. | |
8bb4bdeb XL |
84 | |
85 | ```rust,ignore | |
b7449926 | 86 | extern crate proc_macro; |
8bb4bdeb XL |
87 | use proc_macro::TokenStream; |
88 | ||
b7449926 XL |
89 | #[proc_macro] |
90 | pub fn make_answer(_item: TokenStream) -> TokenStream { | |
91 | "fn answer() -> u32 { 42 }".parse().unwrap() | |
92 | } | |
8bb4bdeb XL |
93 | ``` |
94 | ||
b7449926 XL |
95 | And then we use it a binary crate to print "42" to standard output. |
96 | ||
97 | ```rust,ignore | |
98 | extern crate proc_macro_examples; | |
99 | use proc_macro_examples::make_answer; | |
100 | ||
101 | make_answer!(); | |
102 | ||
103 | fn main() { | |
104 | println!("{}", answer()); | |
105 | } | |
106 | ``` | |
107 | ||
108 | These macros are only invokable in [modules]. They cannot even be invoked to | |
109 | create [item declaration statements]. Furthermore, they must either be invoked | |
110 | with curly braces and no semicolon or a different delimiter followed by a | |
111 | semicolon. For example, `make_answer` from the previous example can be invoked | |
112 | as `make_answer!{}`, `make_answer!();` or `make_answer![];`. | |
113 | ||
532ac7d7 | 114 | ### Derive macros |
b7449926 | 115 | |
532ac7d7 XL |
116 | *Derive macros* define new inputs for the [`derive` attribute]. These macros |
117 | can create new [items] given the token stream of a [struct], [enum], or [union]. | |
118 | They can also define [derive macro helper attributes]. | |
b7449926 | 119 | |
532ac7d7 | 120 | Custom derive macros are defined by a [public] [function] with the |
b7449926 XL |
121 | `proc_macro_derive` attribute and a signature of `(TokenStream) -> TokenStream`. |
122 | ||
123 | The input [`TokenStream`] is the token stream of the item that has the `derive` | |
124 | attribute on it. The output [`TokenStream`] must be a set of items that are | |
125 | then appended to the [module] or [block] that the item from the input | |
126 | [`TokenStream`] is in. | |
127 | ||
532ac7d7 | 128 | The following is an example of a derive macro. Instead of doing anything |
b7449926 XL |
129 | useful with its input, it just appends a function `answer`. |
130 | ||
131 | ```rust,ignore | |
132 | extern crate proc_macro; | |
133 | use proc_macro::TokenStream; | |
134 | ||
135 | #[proc_macro_derive(AnswerFn)] | |
136 | pub fn derive_answer_fn(_item: TokenStream) -> TokenStream { | |
137 | "fn answer() -> u32 { 42 }".parse().unwrap() | |
138 | } | |
139 | ``` | |
140 | ||
532ac7d7 | 141 | And then using said derive macro: |
b7449926 XL |
142 | |
143 | ```rust,ignore | |
144 | extern crate proc_macro_examples; | |
145 | use proc_macro_examples::AnswerFn; | |
146 | ||
147 | #[derive(AnswerFn)] | |
148 | struct Struct; | |
149 | ||
150 | fn main() { | |
151 | assert_eq!(42, answer()); | |
152 | } | |
153 | ``` | |
154 | ||
532ac7d7 | 155 | #### Derive macro helper attributes |
b7449926 | 156 | |
532ac7d7 XL |
157 | Derive macros can add additional [attributes] into the scope of the [item] |
158 | they are on. Said attributes are called *derive macro helper attributes*. These | |
b7449926 | 159 | attributes are [inert], and their only purpose is to be fed into the derive |
532ac7d7 | 160 | macro that defined them. That said, they can be seen by all macros. |
b7449926 XL |
161 | |
162 | The way to define helper attributes is to put an `attributes` key in the | |
163 | `proc_macro_derive` macro with a comma separated list of identifiers that are | |
164 | the names of the helper attributes. | |
165 | ||
532ac7d7 | 166 | For example, the following derive macro defines a helper attribute |
b7449926 XL |
167 | `helper`, but ultimately doesn't do anything with it. |
168 | ||
169 | ```rust,ignore | |
170 | # #[crate_type="proc-macro"] | |
171 | # extern crate proc_macro; | |
172 | # use proc_macro::TokenStream; | |
173 | ||
174 | #[proc_macro_derive(HelperAttr, attributes(helper))] | |
175 | pub fn derive_helper_attr(_item: TokenStream) -> TokenStream { | |
dc9dc135 | 176 | TokenStream::new() |
b7449926 XL |
177 | } |
178 | ``` | |
179 | ||
532ac7d7 | 180 | And then usage on the derive macro on a struct: |
b7449926 XL |
181 | |
182 | ```rust,ignore | |
183 | # #![crate_type="proc-macro"] | |
184 | # extern crate proc_macro_examples; | |
185 | # use proc_macro_examples::HelperAttr; | |
186 | ||
187 | #[derive(HelperAttr)] | |
188 | struct Struct { | |
189 | #[helper] field: () | |
190 | } | |
191 | ``` | |
192 | ||
193 | ### Attribute macros | |
194 | ||
195 | *Attribute macros* define new [attributes] which can be attached to [items]. | |
196 | ||
197 | Attribute macros are defined by a [public] [function] with the | |
532ac7d7 XL |
198 | `proc_macro_attribute` [attribute] that has a signature of `(TokenStream, |
199 | TokenStream) -> TokenStream`. The first [`TokenStream`] is the delimited token | |
200 | tree following the attribute's name, not including the outer delimiters. If | |
201 | the attribute is written as a bare attribute name, the attribute | |
202 | [`TokenStream`] is empty. The second [`TokenStream`] is the rest of the [item] | |
203 | including other [attributes] on the [item]. The returned [`TokenStream`] | |
204 | replaces the [item] with an arbitrary number of [items]. These macros cannot | |
205 | expand to syntax that defines new `macro_rules` style macros. | |
b7449926 XL |
206 | |
207 | For example, this attribute macro takes the input stream and returns it as is, | |
208 | effectively being the no-op of attributes. | |
209 | ||
210 | ```rust,ignore | |
211 | # #![crate_type = "proc-macro"] | |
212 | # extern crate proc_macro; | |
213 | # use proc_macro::TokenStream; | |
214 | ||
215 | #[proc_macro_attribute] | |
216 | pub fn return_as_is(_attr: TokenStream, item: TokenStream) -> TokenStream { | |
217 | item | |
218 | } | |
219 | ``` | |
220 | ||
221 | This following example shows the stringified [`TokenStream`s] that the attribute | |
222 | macros see. The output will show in the output of the compiler. The output is | |
223 | shown in the comments after the function prefixed with "out:". | |
224 | ||
225 | ```rust,ignore | |
226 | // my-macro/src/lib.rs | |
227 | # extern crate proc_macro; | |
228 | # use proc_macro::TokenStream; | |
229 | ||
230 | #[proc_macro_attribute] | |
13cf67c4 | 231 | pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream { |
b7449926 | 232 | println!("attr: \"{}\"", attr.to_string()); |
13cf67c4 | 233 | println!("item: \"{}\"", item.to_string()); |
b7449926 XL |
234 | item |
235 | } | |
236 | ``` | |
237 | ||
238 | ```rust,ignore | |
239 | // src/lib.rs | |
240 | extern crate my_macro; | |
241 | ||
242 | use my_macro::show_streams; | |
243 | ||
244 | // Example: Basic function | |
245 | #[show_streams] | |
246 | fn invoke1() {} | |
247 | // out: attr: "" | |
248 | // out: item: "fn invoke1() { }" | |
249 | ||
532ac7d7 | 250 | // Example: Attribute with input |
b7449926 XL |
251 | #[show_streams(bar)] |
252 | fn invoke2() {} | |
253 | // out: attr: "bar" | |
254 | // out: item: "fn invoke2() {}" | |
255 | ||
532ac7d7 XL |
256 | // Example: Multiple tokens in the input |
257 | #[show_streams(multiple => tokens)] | |
b7449926 | 258 | fn invoke3() {} |
532ac7d7 | 259 | // out: attr: "multiple => tokens" |
b7449926 XL |
260 | // out: item: "fn invoke3() {}" |
261 | ||
13cf67c4 | 262 | // Example: |
b7449926 XL |
263 | #[show_streams { delimiters }] |
264 | fn invoke4() {} | |
532ac7d7 XL |
265 | // out: attr: "delimiters" |
266 | // out: item: "fn invoke4() {}" | |
b7449926 | 267 | ``` |
abe05a73 | 268 | |
b7449926 XL |
269 | [`TokenStream`]: ../proc_macro/struct.TokenStream.html |
270 | [`TokenStream`s]: ../proc_macro/struct.TokenStream.html | |
271 | [`compile_error`]: ../std/macro.compile_error.html | |
532ac7d7 | 272 | [`derive` attribute]: attributes/derive.html |
b7449926 XL |
273 | [`proc_macro` crate]: ../proc_macro/index.html |
274 | [Cargo's build scripts]: ../cargo/reference/build-scripts.html | |
532ac7d7 | 275 | [Derive macros]: #derive-macros |
b7449926 XL |
276 | [Attribute macros]: #attribute-macros |
277 | [Function-like macros]: #function-like-procedural-macros | |
278 | [attribute]: attributes.html | |
279 | [attributes]: attributes.html | |
13cf67c4 | 280 | [block]: expressions/block-expr.html |
b7449926 | 281 | [crate type]: linkage.html |
532ac7d7 | 282 | [derive macro helper attributes]: #derive-macro-helper-attributes |
b7449926 XL |
283 | [enum]: items/enumerations.html |
284 | [inert]: attributes.html#active-and-inert-attributes | |
285 | [item]: items.html | |
286 | [item declaration statements]: statements.html#item-declarations | |
287 | [items]: items.html | |
288 | [function]: items/functions.html | |
b7449926 XL |
289 | [module]: items/modules.html |
290 | [modules]: items/modules.html | |
b7449926 XL |
291 | [public]: visibility-and-privacy.html |
292 | [struct]: items/structs.html | |
13cf67c4 | 293 | [union]: items/unions.html |