Skip to content

Commit 2b96704

Browse files
committed
Function-like proc macros
1 parent eb8ecf2 commit 2b96704

File tree

1 file changed

+28
-57
lines changed

1 file changed

+28
-57
lines changed

src/procedural-macros.md

Lines changed: 28 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*Procedural macros* allow creating syntax extensions as execution of a function.
44
Procedural macros come in one of three flavors:
55

6-
* Bang macros - `custom_bang!(...)`
6+
* Function-like macros - `custom!(...)`
77
* Derive mode macros - `#[derive(CustomMode)]`
88
* Attribute macros - `#[CustomAttribute]`
99

@@ -89,87 +89,56 @@ in certain respects. These limitations include:
8989
exists on stable your only option is to `panic!` or to in some cases expand to
9090
an invocation of the `compile_error!` macro with a custom message.
9191
92-
### Bang Macros
92+
## Function-like procedural macros
9393
94-
This flavor of procedural macro is like writing `macro_rules!` only you get to
95-
execute arbitrary code over the input tokens instead of being limited to
96-
`macro_rules!` syntax.
94+
Function-like procedural macros define new invokable macros.
9795
98-
Procedural bang macros are defined with the `#[proc_macro]` attribute and have
99-
the following signature:
96+
These macros are defined by a [public] [function] with the `proc_maco`
97+
[attribute] and a signature of `(TokenStream) -> TokenStream`. The input
98+
[`TokenStream`] is what is inside the delimiters of the macro invocation and the
99+
output [`TokenStream`] replaces the entire macro invocation. It may contain an
100+
arbitrary number of items.
100101
101-
```rust,ignore
102-
#[proc_macro]
103-
pub fn foo(input: TokenStream) -> TokenStream {
104-
// ...
105-
}
106-
```
107-
108-
This item is defining a procedural bang macro (`#[proc_macro]`) which is called
109-
`foo`. The first argument is the input to the macro which explore in a second,
110-
and the return value is the tokens that it should expand to.
102+
For example, the following macro definition ignores its input and outputs a
103+
function `answer` into its scope.
111104
112105
```rust,ignore
113-
// my-macro/src/lib.rs
114106
extern crate proc_macro;
115-
116-
use proc_macro::*;
107+
use proc_macro::TokenStream;
117108
118109
#[proc_macro]
119-
pub fn foo(input: TokenStream) -> TokenStream {
120-
input
110+
pub fn make_answer(_item: TokenStream) -> TokenStream {
111+
"fn answer() -> u32 { 42 }".parse().unwrap()
121112
}
122113
```
123114
124-
And now let's invoke it:
115+
And then we use it a binary crate to print "42" to standard output.
125116

126117
```rust,ignore
127-
// src/main.rs
128-
extern crate my_macro;
118+
extern crate proc_macro_examples;
119+
use proc_macro_examples::make_answer;
129120
130-
my_macro::foo!(fn answer() -> u32 { 3 });
121+
make_answer!();
131122
132123
fn main() {
133-
println!("the answer was: {}", answer());
124+
println!("{}", answer());
134125
}
135126
```
136127

137-
First up, let's see what the input to our macro looks like by modifying our
138-
macro:
139-
140-
```rust,ignore
141-
// my-macro/src/lib.rs
142-
#[proc_macro]
143-
pub fn foo(input: TokenStream) -> TokenStream {
144-
println!("{:#?}", input);
145-
input
146-
}
147-
```
148-
149-
The macro invocation is effectively replaced by
150-
the return value of the macro, creating the function that we provided as input.
151-
We can see another example of this where we simply ignore the input:
152-
153-
```rust,ignore
154-
// my-macro/src/lib.rs
155-
#[proc_macro]
156-
pub fn foo(_input: TokenStream) -> TokenStream {
157-
"fn answer() -> u32 { 4 }".parse().unwrap()
158-
}
159-
```
160-
161-
```
162-
the answer was: 4
163-
```
128+
These macros are only invokable in [modules]. They cannot even be invoked to
129+
make [item declaration statements]. Furthermore, they must either be invoked
130+
with curly braces and no semicolon or a different delimiter followed by a
131+
semicolon. For example, `make_answer` from the previous example can be invoked
132+
as `make_answer!{}`, `make_answer!();` or `make_answer![];`.
164133

165134
### Derive mode macros
166135

167136
*Derive mode macros* define new modes for the `derive` attribute. The macros
168137
define new items given the token stream of a [struct], [enum], or [union]. They
169138
also define derive mode helper attributes.
170139

171-
Custom derivers are defined by a [public] [function] with the `proc_maco_derive`
172-
attribute and a signature of `(TokenStream) -> TokenStream`.
140+
Custom deriver modes are defined by a [public] [function] with the
141+
`proc_maco_derive` attribute and a signature of `(TokenStream) -> TokenStream`.
173142

174143
The input [`TokenStream`] is the token stream of the item that has the `derive`
175144
attribute on it. The output [`TokenStream`] must be a set of items that are
@@ -184,7 +153,7 @@ extern crate proc_macro;
184153
use proc_macro::TokenStream;
185154
186155
#[proc_macro_derive(AnswerFn)]
187-
pub fn foo(_item: TokenStream) -> TokenStream {
156+
pub fn derive_answer_fn(_item: TokenStream) -> TokenStream {
188157
"fn answer() -> u32 { 42 }".parse().unwrap()
189158
}
190159
```
@@ -326,8 +295,10 @@ fn invoke4() {}
326295
[custom attributes]: attributes.html
327296
[crate type]: linkage.html
328297
[item]: items.html
298+
[item declaration statements]: statements.html#item-declarations
329299
[function]: items/functions.html
330300
[macro]: macros.html
331301
[module]: items/modules.html
302+
[modules]: items/modules.html
332303
[procedural macro tutorial]: ../book/2018-edition/appendix-04-macros.html#procedural-macros-for-custom-derive
333304
[public]: visibility-and-privacy.html

0 commit comments

Comments
 (0)