Skip to content

Commit dfaaa77

Browse files
authored
Merge pull request #1888 from ehuss/proc_macro_derive
Update `proc_macro_derive` to use the attribute template
2 parents 0c4439d + 89789f6 commit dfaaa77

File tree

5 files changed

+96
-75
lines changed

5 files changed

+96
-75
lines changed

src/attributes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ The following is an index of all built-in attributes.
373373
[`panic_handler`]: panic.md#the-panic_handler-attribute
374374
[`path`]: items/modules.md#the-path-attribute
375375
[`proc_macro_attribute`]: procedural-macros.md#attribute-macros
376-
[`proc_macro_derive`]: procedural-macros.md#derive-macros
376+
[`proc_macro_derive`]: macro.proc.derive
377377
[`proc_macro`]: procedural-macros.md#function-like-procedural-macros
378378
[`recursion_limit`]: attributes/limits.md#the-recursion_limit-attribute
379379
[`repr`]: type-layout.md#representations

src/attributes/derive.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ The `automatically_derived` attribute has no behavior.
103103
104104
[items]: ../items.md
105105
[derive macro]: macro.proc.derive
106-
[derive macros]: ../procedural-macros.md#derive-macros
106+
[derive macros]: macro.proc.derive
107107
[implementation]: ../items/implementations.md
108108
[items]: ../items.md
109-
[procedural macros]: ../procedural-macros.md#derive-macros
109+
[procedural macros]: macro.proc.derive

src/items/use-declarations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ fn main() {
448448
[associated items]: associated-items.md
449449
[Attributes]: ../attributes.md
450450
[Built-in types]: ../types.md
451-
[Derive macros]: ../procedural-macros.md#derive-macros
451+
[Derive macros]: macro.proc.derive
452452
[Enum variants]: enumerations.md
453453
[extern prelude]: ../names/preludes.md#extern-prelude
454454
[generic parameters]: generics.md

src/names/namespaces.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ It is still an error for a [`use` import] to shadow another macro, regardless of
144144
[closure]: ../expressions/closure-expr.md
145145
[Constant item declarations]: ../items/constant-items.md
146146
[Derive macro helpers]: ../procedural-macros.md#derive-macro-helper-attributes
147-
[Derive macros]: ../procedural-macros.md#derive-macros
147+
[Derive macros]: macro.proc.derive
148148
[entity]: ../glossary.md#entity
149149
[Enum variant constructors]: ../items/enumerations.md
150150
[enum]: ../items/enumerations.md

src/procedural-macros.md

Lines changed: 91 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -131,94 +131,101 @@ expressions], [item] positions, including items in [`extern` blocks], inherent
131131
and trait [implementations], and [trait definitions].
132132

133133
r[macro.proc.derive]
134-
## Derive macros
134+
## The `proc_macro_derive` attribute
135135

136136
r[macro.proc.derive.intro]
137-
*Derive macros* define new inputs for the [`derive` attribute]. These macros
138-
can create new [items] given the token stream of a [struct], [enum], or [union].
139-
They can also define [derive macro helper attributes].
137+
Applying the *`proc_macro_derive` [attribute]* to a function defines a *derive macro* that can be invoked by the [`derive` attribute]. These macros are given the token stream of a [struct], [enum], or [union] definition and can emit new [items] after it. They can also declare and use [derive macro helper attributes].
140138

141-
r[macro.proc.derive.def]
142-
Custom derive macros are defined by a [public] [function] with the
143-
`proc_macro_derive` attribute and a signature of `(TokenStream) -> TokenStream`.
144-
145-
r[macro.proc.derive.namespace]
146-
The `proc_macro_derive` attribute defines the custom derive in the [macro namespace] in the root of the crate.
139+
> [!EXAMPLE]
140+
> This derive macro ignores its input and appends tokens that define a function.
141+
>
142+
> <!-- ignore: test doesn't support proc-macro -->
143+
> ```rust,ignore
144+
> # #![crate_type = "proc-macro"]
145+
> extern crate proc_macro;
146+
> use proc_macro::TokenStream;
147+
>
148+
> #[proc_macro_derive(AnswerFn)]
149+
> pub fn derive_answer_fn(_item: TokenStream) -> TokenStream {
150+
> "fn answer() -> u32 { 42 }".parse().unwrap()
151+
> }
152+
> ```
153+
>
154+
> To use it, we might write:
155+
>
156+
> <!-- ignore: requires external crates -->
157+
> ```rust,ignore
158+
> extern crate proc_macro_examples;
159+
> use proc_macro_examples::AnswerFn;
160+
>
161+
> #[derive(AnswerFn)]
162+
> struct Struct;
163+
>
164+
> fn main() {
165+
> assert_eq!(42, answer());
166+
> }
167+
> ```
147168
148-
r[macro.proc.derive.output]
149-
The input [`TokenStream`] is the token stream of the item that has the `derive`
150-
attribute on it. The output [`TokenStream`] must be a set of items that are
151-
then appended to the [module] or [block] that the item from the input
152-
[`TokenStream`] is in.
169+
r[macro.proc.derive.syntax]
170+
The syntax for the `proc_macro_derive` attribute is:
153171
154-
The following is an example of a derive macro. Instead of doing anything
155-
useful with its input, it just appends a function `answer`.
172+
```grammar,attributes
173+
@root ProcMacroDeriveAttribute ->
174+
`proc_macro_derive` `(` DeriveMacroName ( `,` DeriveMacroAttributes )? `,`? `)`
156175
157-
<!-- ignore: test doesn't support proc-macro -->
158-
```rust,ignore
159-
# #![crate_type = "proc-macro"]
160-
extern crate proc_macro;
161-
use proc_macro::TokenStream;
176+
DeriveMacroName -> IDENTIFIER
162177
163-
#[proc_macro_derive(AnswerFn)]
164-
pub fn derive_answer_fn(_item: TokenStream) -> TokenStream {
165-
"fn answer() -> u32 { 42 }".parse().unwrap()
166-
}
178+
DeriveMacroAttributes ->
179+
`attributes` `(` ( IDENTIFIER (`,` IDENTIFIER)* `,`?)? `)`
167180
```
168181
169-
And then using said derive macro:
182+
The name of the derive macro is given by [DeriveMacroName]. The optional `attributes` argument is described in [macro.proc.derive.attributes].
170183

171-
<!-- ignore: requires external crates -->
172-
```rust,ignore
173-
extern crate proc_macro_examples;
174-
use proc_macro_examples::AnswerFn;
184+
r[macro.proc.derive.allowed-positions]
185+
The `proc_macro_derive` attribute may only be applied to a `pub` function with the [Rust ABI][items.fn.extern] defined in the root of the crate with a type of `fn(TokenStream) -> TokenStream` where [`TokenStream`] comes from the [`proc_macro` crate]. The function may be `const` and may use `extern` to explicitly specify the Rust ABI, but it may not use any other [qualifiers][FunctionQualifiers] (e.g. it may not be `async` or `unsafe`).
175186

176-
#[derive(AnswerFn)]
177-
struct Struct;
187+
r[macro.proc.derive.duplicates]
188+
The `proc_macro_derive` attribute may be specified only once on a function.
178189

179-
fn main() {
180-
assert_eq!(42, answer());
181-
}
182-
```
190+
r[macro.proc.derive.namespace]
191+
The `proc_macro_derive` attribute publicly defines the derive macro in the [macro namespace] in the root of the crate.
192+
193+
r[macro.proc.derive.output]
194+
The input [`TokenStream`] is the token stream of the item to which the `derive` attribute is applied. The output [`TokenStream`] must be a (possibly empty) set of items. These items are appended following the input item within the same [module] or [block].
183195

184196
r[macro.proc.derive.attributes]
185197
### Derive macro helper attributes
186198

187199
r[macro.proc.derive.attributes.intro]
188-
Derive macros can add additional [attributes] into the scope of the [item]
189-
they are on. Said attributes are called *derive macro helper attributes*. These
190-
attributes are [inert], and their only purpose is to be fed into the derive
191-
macro that defined them. That said, they can be seen by all macros.
192-
193-
r[macro.proc.derive.attributes.def]
194-
The way to define helper attributes is to put an `attributes` key in the
195-
`proc_macro_derive` macro with a comma separated list of identifiers that are
196-
the names of the helper attributes.
197-
198-
For example, the following derive macro defines a helper attribute
199-
`helper`, but ultimately doesn't do anything with it.
200-
201-
<!-- ignore: test doesn't support proc-macro -->
202-
```rust,ignore
203-
# #![crate_type="proc-macro"]
204-
# extern crate proc_macro;
205-
# use proc_macro::TokenStream;
200+
Derive macros can declare *derive macro helper attributes* to be used within the scope of the [item] to which the derive macro is applied. These [attributes] are [inert]. While their purpose is to be used by the macro that declared them, they can be seen by any macro.
206201

207-
#[proc_macro_derive(HelperAttr, attributes(helper))]
208-
pub fn derive_helper_attr(_item: TokenStream) -> TokenStream {
209-
TokenStream::new()
210-
}
211-
```
202+
r[macro.proc.derive.attributes.decl]
203+
A helper attribute for a derive macro is declared by adding its identifier to the `attributes` list in the `proc_macro_derive` attribute.
212204

213-
And then usage on the derive macro on a struct:
214-
215-
<!-- ignore: requires external crates -->
216-
```rust,ignore
217-
#[derive(HelperAttr)]
218-
struct Struct {
219-
#[helper] field: ()
220-
}
221-
```
205+
> [!EXAMPLE]
206+
> This declares a helper attribute and then ignores it.
207+
>
208+
> <!-- ignore: test doesn't support proc-macro -->
209+
> ```rust,ignore
210+
> # #![crate_type="proc-macro"]
211+
> # extern crate proc_macro;
212+
> # use proc_macro::TokenStream;
213+
> #
214+
> #[proc_macro_derive(WithHelperAttr, attributes(helper))]
215+
> pub fn derive_with_helper_attr(_item: TokenStream) -> TokenStream {
216+
> TokenStream::new()
217+
> }
218+
> ```
219+
>
220+
> To use it, we might write:
221+
>
222+
> <!-- ignore: requires external crates -->
223+
> ```rust,ignore
224+
> #[derive(WithHelperAttr)]
225+
> struct Struct {
226+
> #[helper] field: (),
227+
> }
228+
> ```
222229
223230
r[macro.proc.attribute]
224231
## Attribute macros
@@ -375,7 +382,7 @@ their equivalent `#[doc = r"str"]` attributes when passed to macros.
375382

376383
[Attribute macros]: #attribute-macros
377384
[Cargo's build scripts]: ../cargo/reference/build-scripts.html
378-
[Derive macros]: #derive-macros
385+
[Derive macros]: macro.proc.derive
379386
[Function-like macros]: #function-like-procedural-macros
380387
[`$crate`]: macro.decl.hygiene.crate
381388
[`Delimiter::None`]: proc_macro::Delimiter::None
@@ -409,3 +416,17 @@ their equivalent `#[doc = r"str"]` attributes when passed to macros.
409416
[type expressions]: types.md#type-expressions
410417
[type]: types.md
411418
[union]: items/unions.md
419+
420+
<script>
421+
(function() {
422+
var fragments = {
423+
"#derive-macros": "procedural-macros.html#the-proc_macro_derive-attribute",
424+
};
425+
var target = fragments[window.location.hash];
426+
if (target) {
427+
var url = window.location.toString();
428+
var base = url.substring(0, url.lastIndexOf('/'));
429+
window.location.replace(base + "/" + target);
430+
}
431+
})();
432+
</script>

0 commit comments

Comments
 (0)