@@ -25,10 +25,10 @@ three flavors:
25
25
and bring all the goodness and ease of use of ` #[derive(Debug)] ` to
26
26
user-defined traits as well, such as [ Serde] 's ` #[derive(Deserialize)] ` .
27
27
28
- * ** Function-like macros** are new to the 2018 edition and allow defining
29
- macros like ` env!("FOO") ` or ` format_args!("...") ` in a crate.io-based
30
- library. You can think of these as sort of "` macro_rules! ` macros" on
31
- steroids.
28
+ * ** Function-like macros** are newly stable to the 2018 edition and allow
29
+ defining macros like ` env!("FOO") ` or ` format_args!("...") ` in a
30
+ crate.io-based library. You can think of these as sort of "` macro_rules! `
31
+ macros" on steroids.
32
32
33
33
* ** Attribute macros** , my favorite, are also new in the 2018 edition
34
34
and allow you to provide lightweight annotations on Rust functions which
@@ -87,7 +87,7 @@ Right off the bat we can see a few important properties of procedural macros:
87
87
* We're * executing aribtrary code* at compile time, which means we can do just
88
88
about anything!
89
89
* Procedural macros are incorporated with the module system, meaning no more
90
- janky ` #[macro_use] `
90
+ they can be imported just like any other name.
91
91
92
92
Before we take a look at implementing a procedural macro, let's first dive into
93
93
some of these points.
@@ -148,6 +148,12 @@ struct Foo {
148
148
```
149
149
150
150
and you don't even need to explicitly depend on ` serde_derive ` in ` Cargo.toml ` !
151
+ All you need is:
152
+
153
+ ``` toml
154
+ [dependencies ]
155
+ serde = { version = ' 1.0.82' , features = [' derive' ] }
156
+ ```
151
157
152
158
### What's inside a ` TokenStream ` ?
153
159
@@ -156,9 +162,9 @@ This mysterious `TokenStream` type comes from the [compiler-provided
156
162
[ ` TokenStream ` ] was call convert it to or from a string using ` to_string() ` or ` parse() ` .
157
163
As of Rust 2018, you can act on the tokens in a [ ` TokenStream ` ] directly.
158
164
159
- As its name might imply, a ` TokenStream ` can be thought of as a stream of
160
- tokens, or a list of tokens. Each token is called a [ ` TokenTree ` ] and represents
161
- one of four kinds of tokens :
165
+ A [ ` TokenStream ` ] is effectively "just" an iterator over [ ` TokenTree ` ] . All
166
+ syntax in Rust falls into one of these four categories, the four variants of
167
+ [ ` TokenTree ` ] :
162
168
163
169
* ` Ident ` is any identifier like ` foo ` or ` bar ` . This also contains keywords
164
170
such as ` self ` and ` super ` .
@@ -173,9 +179,6 @@ one of four kinds of tokens:
173
179
delimited sub-token-stream. For example ` (a, b) ` is a ` Group ` with parentheses
174
180
as delimiters, and the internal token stream is ` a, b ` .
175
181
176
- All syntax in Rust falls into one of the above four categories. A ` TokenStream `
177
- is effectively "just" an iterator over ` TokenTree ` .
178
-
179
182
While this is conceptually simple, this may sound like there's not much we can
180
183
do with this! It's unclear, for example, how we might parse a function from a
181
184
` TokenStream ` . The minimality of ` TokenTree ` is crucial, however, for
@@ -251,11 +254,31 @@ together various pieces of syntax into one return value.
251
254
### Tokens and ` Span `
252
255
253
256
Perhaps the greatest feature of procedural macros in Rust 2018 is the ability to
254
- customize and use [ ` Span ` ] information on each token. A [ ` Span ` ] can be thought
255
- of as a pointer back into an original source file, typically saying something
256
- like "the ` Ident ` token` foo ` came from file ` bar.rs ` , line 4, column 5, and was
257
- 3 bytes long". This information is primarily used by the compiler's diagnostics
258
- with warnings and error messages.
257
+ customize and use [ ` Span ` ] information on each token, giving us the ability for
258
+ amazing syntactical error messages from procedural macros:
259
+
260
+ ```
261
+ error: expected `fn`
262
+ --> src/main.rs:3:14
263
+ |
264
+ 3 | my_annotate!(not_fn foo() {});
265
+ | ^^^^^^
266
+ ```
267
+
268
+ as well as completely custom error messages:
269
+
270
+ ```
271
+ error: imported methods must have at least one argument
272
+ --> invalid-imports.rs:12:5
273
+ |
274
+ 12 | fn f1();
275
+ | ^^^^^^^^
276
+ ```
277
+
278
+ A [ ` Span ` ] can be thought of as a pointer back into an original source file,
279
+ typically saying something like "the ` Ident ` token` foo ` came from file
280
+ ` bar.rs ` , line 4, column 5, and was 3 bytes long". This information is
281
+ primarily used by the compiler's diagnostics with warnings and error messages.
259
282
260
283
In Rust 2018 each [ ` TokenTree ` ] has a [ ` Span ` ] associated with it. This means that
261
284
if you preserve the [ ` Span ` ] of all input tokens into the output then even
0 commit comments