diff --git a/src/attributes.md b/src/attributes.md index 7179401c9f..d0b311ea8d 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -373,7 +373,7 @@ The following is an index of all built-in attributes. [`panic_handler`]: panic.md#the-panic_handler-attribute [`path`]: items/modules.md#the-path-attribute [`proc_macro_attribute`]: procedural-macros.md#attribute-macros -[`proc_macro_derive`]: procedural-macros.md#derive-macros +[`proc_macro_derive`]: macro.proc.derive [`proc_macro`]: procedural-macros.md#function-like-procedural-macros [`recursion_limit`]: attributes/limits.md#the-recursion_limit-attribute [`repr`]: type-layout.md#representations diff --git a/src/attributes/derive.md b/src/attributes/derive.md index d65431bc01..aece0484b0 100644 --- a/src/attributes/derive.md +++ b/src/attributes/derive.md @@ -103,7 +103,7 @@ The `automatically_derived` attribute has no behavior. [items]: ../items.md [derive macro]: macro.proc.derive -[derive macros]: ../procedural-macros.md#derive-macros +[derive macros]: macro.proc.derive [implementation]: ../items/implementations.md [items]: ../items.md -[procedural macros]: ../procedural-macros.md#derive-macros +[procedural macros]: macro.proc.derive diff --git a/src/items/use-declarations.md b/src/items/use-declarations.md index ec993d737b..3df3e23879 100644 --- a/src/items/use-declarations.md +++ b/src/items/use-declarations.md @@ -448,7 +448,7 @@ fn main() { [associated items]: associated-items.md [Attributes]: ../attributes.md [Built-in types]: ../types.md -[Derive macros]: ../procedural-macros.md#derive-macros +[Derive macros]: macro.proc.derive [Enum variants]: enumerations.md [extern prelude]: ../names/preludes.md#extern-prelude [generic parameters]: generics.md diff --git a/src/names/namespaces.md b/src/names/namespaces.md index feb0e97710..1794b0fd82 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -144,7 +144,7 @@ It is still an error for a [`use` import] to shadow another macro, regardless of [closure]: ../expressions/closure-expr.md [Constant item declarations]: ../items/constant-items.md [Derive macro helpers]: ../procedural-macros.md#derive-macro-helper-attributes -[Derive macros]: ../procedural-macros.md#derive-macros +[Derive macros]: macro.proc.derive [entity]: ../glossary.md#entity [Enum variant constructors]: ../items/enumerations.md [enum]: ../items/enumerations.md diff --git a/src/procedural-macros.md b/src/procedural-macros.md index 545b48cc95..a26a57eb2e 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -131,94 +131,101 @@ expressions], [item] positions, including items in [`extern` blocks], inherent and trait [implementations], and [trait definitions]. r[macro.proc.derive] -## Derive macros +## The `proc_macro_derive` attribute r[macro.proc.derive.intro] -*Derive macros* define new inputs for the [`derive` attribute]. These macros -can create new [items] given the token stream of a [struct], [enum], or [union]. -They can also define [derive macro helper attributes]. +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]. -r[macro.proc.derive.def] -Custom derive macros are defined by a [public] [function] with the -`proc_macro_derive` attribute and a signature of `(TokenStream) -> TokenStream`. - -r[macro.proc.derive.namespace] -The `proc_macro_derive` attribute defines the custom derive in the [macro namespace] in the root of the crate. +> [!EXAMPLE] +> This derive macro ignores its input and appends tokens that define a function. +> +> +> ```rust,ignore +> # #![crate_type = "proc-macro"] +> extern crate proc_macro; +> use proc_macro::TokenStream; +> +> #[proc_macro_derive(AnswerFn)] +> pub fn derive_answer_fn(_item: TokenStream) -> TokenStream { +> "fn answer() -> u32 { 42 }".parse().unwrap() +> } +> ``` +> +> To use it, we might write: +> +> +> ```rust,ignore +> extern crate proc_macro_examples; +> use proc_macro_examples::AnswerFn; +> +> #[derive(AnswerFn)] +> struct Struct; +> +> fn main() { +> assert_eq!(42, answer()); +> } +> ``` -r[macro.proc.derive.output] -The input [`TokenStream`] is the token stream of the item that has the `derive` -attribute on it. The output [`TokenStream`] must be a set of items that are -then appended to the [module] or [block] that the item from the input -[`TokenStream`] is in. +r[macro.proc.derive.syntax] +The syntax for the `proc_macro_derive` attribute is: -The following is an example of a derive macro. Instead of doing anything -useful with its input, it just appends a function `answer`. +```grammar,attributes +@root ProcMacroDeriveAttribute -> + `proc_macro_derive` `(` DeriveMacroName ( `,` DeriveMacroAttributes )? `,`? `)` - -```rust,ignore -# #![crate_type = "proc-macro"] -extern crate proc_macro; -use proc_macro::TokenStream; +DeriveMacroName -> IDENTIFIER -#[proc_macro_derive(AnswerFn)] -pub fn derive_answer_fn(_item: TokenStream) -> TokenStream { - "fn answer() -> u32 { 42 }".parse().unwrap() -} +DeriveMacroAttributes -> + `attributes` `(` ( IDENTIFIER (`,` IDENTIFIER)* `,`?)? `)` ``` -And then using said derive macro: +The name of the derive macro is given by [DeriveMacroName]. The optional `attributes` argument is described in [macro.proc.derive.attributes]. - -```rust,ignore -extern crate proc_macro_examples; -use proc_macro_examples::AnswerFn; +r[macro.proc.derive.allowed-positions] +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`). -#[derive(AnswerFn)] -struct Struct; +r[macro.proc.derive.duplicates] +The `proc_macro_derive` attribute may be specified only once on a function. -fn main() { - assert_eq!(42, answer()); -} -``` +r[macro.proc.derive.namespace] +The `proc_macro_derive` attribute publicly defines the derive macro in the [macro namespace] in the root of the crate. + +r[macro.proc.derive.output] +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]. r[macro.proc.derive.attributes] ### Derive macro helper attributes r[macro.proc.derive.attributes.intro] -Derive macros can add additional [attributes] into the scope of the [item] -they are on. Said attributes are called *derive macro helper attributes*. These -attributes are [inert], and their only purpose is to be fed into the derive -macro that defined them. That said, they can be seen by all macros. - -r[macro.proc.derive.attributes.def] -The way to define helper attributes is to put an `attributes` key in the -`proc_macro_derive` macro with a comma separated list of identifiers that are -the names of the helper attributes. - -For example, the following derive macro defines a helper attribute -`helper`, but ultimately doesn't do anything with it. - - -```rust,ignore -# #![crate_type="proc-macro"] -# extern crate proc_macro; -# use proc_macro::TokenStream; +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. -#[proc_macro_derive(HelperAttr, attributes(helper))] -pub fn derive_helper_attr(_item: TokenStream) -> TokenStream { - TokenStream::new() -} -``` +r[macro.proc.derive.attributes.decl] +A helper attribute for a derive macro is declared by adding its identifier to the `attributes` list in the `proc_macro_derive` attribute. -And then usage on the derive macro on a struct: - - -```rust,ignore -#[derive(HelperAttr)] -struct Struct { - #[helper] field: () -} -``` +> [!EXAMPLE] +> This declares a helper attribute and then ignores it. +> +> +> ```rust,ignore +> # #![crate_type="proc-macro"] +> # extern crate proc_macro; +> # use proc_macro::TokenStream; +> # +> #[proc_macro_derive(WithHelperAttr, attributes(helper))] +> pub fn derive_with_helper_attr(_item: TokenStream) -> TokenStream { +> TokenStream::new() +> } +> ``` +> +> To use it, we might write: +> +> +> ```rust,ignore +> #[derive(WithHelperAttr)] +> struct Struct { +> #[helper] field: (), +> } +> ``` r[macro.proc.attribute] ## Attribute macros @@ -375,7 +382,7 @@ their equivalent `#[doc = r"str"]` attributes when passed to macros. [Attribute macros]: #attribute-macros [Cargo's build scripts]: ../cargo/reference/build-scripts.html -[Derive macros]: #derive-macros +[Derive macros]: macro.proc.derive [Function-like macros]: #function-like-procedural-macros [`$crate`]: macro.decl.hygiene.crate [`Delimiter::None`]: proc_macro::Delimiter::None @@ -409,3 +416,17 @@ their equivalent `#[doc = r"str"]` attributes when passed to macros. [type expressions]: types.md#type-expressions [type]: types.md [union]: items/unions.md + +