From 5bf7161636b94cc2d1d60871ebb41ef7a4156def Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 16:50:05 -0700 Subject: [PATCH 1/5] Unwrap proc_macro_attribute --- src/procedural-macros.md | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index be6ff36111..bf212cc9b1 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -244,25 +244,15 @@ r[macro.proc.attribute] ## Attribute macros r[macro.proc.attribute.intro] -*Attribute macros* define new [outer attributes][attributes] which can be -attached to [items], including items in [`extern` blocks], inherent and trait -[implementations], and [trait definitions]. +*Attribute macros* define new [outer attributes][attributes] which can be attached to [items], including items in [`extern` blocks], inherent and trait [implementations], and [trait definitions]. r[macro.proc.attribute.def] -Attribute macros are defined by a [public] [function] with the -`proc_macro_attribute` [attribute] that has a signature of `(TokenStream, -TokenStream) -> TokenStream`. The first [`TokenStream`] is the delimited token -tree following the attribute's name, not including the outer delimiters. If -the attribute is written as a bare attribute name, the attribute -[`TokenStream`] is empty. The second [`TokenStream`] is the rest of the [item] -including other [attributes] on the [item]. The returned [`TokenStream`] -replaces the [item] with an arbitrary number of [items]. +Attribute macros are defined by a [public] [function] with the `proc_macro_attribute` [attribute] that has a signature of `(TokenStream, TokenStream) -> TokenStream`. The first [`TokenStream`] is the delimited token tree following the attribute's name, not including the outer delimiters. If the attribute is written as a bare attribute name, the attribute [`TokenStream`] is empty. The second [`TokenStream`] is the rest of the [item] including other [attributes] on the [item]. The returned [`TokenStream`] replaces the [item] with an arbitrary number of [items]. r[macro.proc.attribute.namespace] The `proc_macro_attribute` attribute defines the attribute in the [macro namespace] in the root of the crate. -For example, this attribute macro takes the input stream and returns it as is, -effectively being the no-op of attributes. +For example, this attribute macro takes the input stream and returns it as is, effectively being the no-op of attributes. ```rust,ignore @@ -276,9 +266,7 @@ pub fn return_as_is(_attr: TokenStream, item: TokenStream) -> TokenStream { } ``` -This following example shows the stringified [`TokenStream`s] that the attribute -macros see. The output will show in the output of the compiler. The output is -shown in the comments after the function prefixed with "out:". +This following example shows the stringified [`TokenStream`s] that the attribute macros see. The output will show in the output of the compiler. The output is shown in the comments after the function prefixed with "out:". ```rust,ignore From c6d588b2c02eeb9bae0a05ff11c1dbde9022b4aa Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 17:10:22 -0700 Subject: [PATCH 2/5] Rename "Attribute macros" section This renames this section to follow the attribute template. Although I like the old title, since it describes what it does, I would prefer to not make exceptions and stay consistent. --- book.toml | 1 + src/attributes.md | 4 ++-- src/items/functions.md | 2 +- src/names/namespaces.md | 2 +- src/procedural-macros.md | 4 ++-- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/book.toml b/book.toml index fe4b86f1f2..8e85b4a787 100644 --- a/book.toml +++ b/book.toml @@ -34,6 +34,7 @@ use-boolean-and = true "/items/traits.html#object-safety" = "traits.html#dyn-compatibility" "/lifetime-elision.html#static-lifetime-elision" = "lifetime-elision.html#const-and-static-elision" "/macros-by-example.html#path-based-scope" = "macros-by-example.html#the-macro_export-attribute" +"/procedural-macros.html#attribute-macros" = "procedural-macros.html#the-proc_macro_attribute-attribute" "/procedural-macros.html#derive-macros" = "procedural-macros.html#the-proc_macro_derive-attribute" "/procedural-macros.html#function-like-procedural-macros" = "procedural-macros.html#the-proc_macro-attribute" "/runtime.html#the-panic_handler-attribute" = "panic.html#the-panic_handler-attribute" diff --git a/src/attributes.md b/src/attributes.md index 6d9115b43b..26fa10cc42 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -372,7 +372,7 @@ The following is an index of all built-in attributes. [`non_exhaustive`]: attributes/type_system.md#the-non_exhaustive-attribute [`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_attribute`]: procedural-macros.md#the-proc_macro_attribute-attribute [`proc_macro_derive`]: macro.proc.derive [`proc_macro`]: procedural-macros.md#the-proc_macro-attribute [`recursion_limit`]: attributes/limits.md#the-recursion_limit-attribute @@ -385,7 +385,7 @@ The following is an index of all built-in attributes. [`used`]: abi.md#the-used-attribute [`warn`]: attributes/diagnostics.md#lint-check-attributes [`windows_subsystem`]: runtime.md#the-windows_subsystem-attribute -[attribute macros]: procedural-macros.md#attribute-macros +[attribute macros]: procedural-macros.md#the-proc_macro_attribute-attribute [block expressions]: expressions/block-expr.md [built-in attributes]: #built-in-attributes-index [derive macro helper attributes]: procedural-macros.md#derive-macro-helper-attributes diff --git a/src/items/functions.md b/src/items/functions.md index 9819db5ced..468c50574f 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -472,7 +472,7 @@ fn foo_oof(#[some_inert_attribute] arg: u8) { [`cfg`]: ../conditional-compilation.md#the-cfg-attribute [`cfg_attr`]: ../conditional-compilation.md#the-cfg_attr-attribute [lint check attributes]: ../attributes/diagnostics.md#lint-check-attributes -[procedural macro attributes]: ../procedural-macros.md#attribute-macros +[procedural macro attributes]: macro.proc.attribute [testing attributes]: ../attributes/testing.md [`cold`]: ../attributes/codegen.md#the-cold-attribute [`inline`]: ../attributes/codegen.md#the-inline-attribute diff --git a/src/names/namespaces.md b/src/names/namespaces.md index 116c7a1fe6..072cb640d2 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -134,7 +134,7 @@ It is still an error for a [`use` import] to shadow another macro, regardless of [Associated const declarations]: ../items/associated-items.md#associated-constants [Associated function declarations]: ../items/associated-items.md#associated-functions-and-methods [Associated type declarations]: ../items/associated-items.md#associated-types -[Attribute macros]: ../procedural-macros.md#attribute-macros +[Attribute macros]: ../procedural-macros.md#the-proc_macro_attribute-attribute [attributes]: ../attributes.md [bang-style macros]: ../macros.md [Block labels]: ../expressions/loop-expr.md#labelled-block-expressions diff --git a/src/procedural-macros.md b/src/procedural-macros.md index bf212cc9b1..52dc32a76f 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -241,7 +241,7 @@ A helper attribute for a derive macro is declared by adding its identifier to th > ``` r[macro.proc.attribute] -## Attribute macros +## The `proc_macro_attribute` attribute r[macro.proc.attribute.intro] *Attribute macros* define new [outer attributes][attributes] which can be attached to [items], including items in [`extern` blocks], inherent and trait [implementations], and [trait definitions]. @@ -381,7 +381,7 @@ Note that neither declarative nor procedural macros support doc comment tokens (e.g. `/// Doc`), so they are always converted to token streams representing their equivalent `#[doc = r"str"]` attributes when passed to macros. -[Attribute macros]: #attribute-macros +[Attribute macros]: #the-proc_macro_attribute-attribute [Cargo's build scripts]: ../cargo/reference/build-scripts.html [Derive macros]: macro.proc.derive [Function-like macros]: #the-proc_macro-attribute From f45633d9a48332ecfecd85f17b9cade518aaa485 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 17:49:18 -0700 Subject: [PATCH 3/5] Move proc_macro_attribute example to an example block --- src/procedural-macros.md | 117 +++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index 52dc32a76f..ffe5c44f3e 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -248,71 +248,78 @@ r[macro.proc.attribute.intro] r[macro.proc.attribute.def] Attribute macros are defined by a [public] [function] with the `proc_macro_attribute` [attribute] that has a signature of `(TokenStream, TokenStream) -> TokenStream`. The first [`TokenStream`] is the delimited token tree following the attribute's name, not including the outer delimiters. If the attribute is written as a bare attribute name, the attribute [`TokenStream`] is empty. The second [`TokenStream`] is the rest of the [item] including other [attributes] on the [item]. The returned [`TokenStream`] replaces the [item] with an arbitrary number of [items]. +> [!EXAMPLE] +> The following attribute macro takes the input stream and returns it as is, effectively being the no-op of attributes. +> +> +> ```rust,ignore +> # #![crate_type = "proc-macro"] +> # extern crate proc_macro; +> # use proc_macro::TokenStream; +> +> #[proc_macro_attribute] +> pub fn return_as_is(_attr: TokenStream, item: TokenStream) -> TokenStream { +> item +> } +> ``` r[macro.proc.attribute.namespace] The `proc_macro_attribute` attribute defines the attribute in the [macro namespace] in the root of the crate. +> [!EXAMPLE] +> This following example shows the stringified [`TokenStream`s] that the attribute macros see. The output will show in the output of the compiler. The output is shown in the comments after the function prefixed with "out:". +> +> +> ```rust,ignore +> // my-macro/src/lib.rs +> # extern crate proc_macro; +> # use proc_macro::TokenStream; +> +> #[proc_macro_attribute] +> pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream { +> println!("attr: \"{attr}\""); +> println!("item: \"{item}\""); +> item +> } +> ``` +> +> +> ```rust,ignore +> // src/lib.rs +> extern crate my_macro; +> +> use my_macro::show_streams; +> +> // Example: Basic function +> #[show_streams] +> fn invoke1() {} +> // out: attr: "" +> // out: item: "fn invoke1() {}" +> +> // Example: Attribute with input +> #[show_streams(bar)] +> fn invoke2() {} +> // out: attr: "bar" +> // out: item: "fn invoke2() {}" +> +> // Example: Multiple tokens in the input +> #[show_streams(multiple => tokens)] +> fn invoke3() {} +> // out: attr: "multiple => tokens" +> // out: item: "fn invoke3() {}" +> +> // Example: +> #[show_streams { delimiters }] +> fn invoke4() {} +> // out: attr: "delimiters" +> // out: item: "fn invoke4() {}" +> ``` -For example, this attribute macro takes the input stream and returns it as is, effectively being the no-op of attributes. - -```rust,ignore -# #![crate_type = "proc-macro"] -# extern crate proc_macro; -# use proc_macro::TokenStream; -#[proc_macro_attribute] -pub fn return_as_is(_attr: TokenStream, item: TokenStream) -> TokenStream { - item -} -``` -This following example shows the stringified [`TokenStream`s] that the attribute macros see. The output will show in the output of the compiler. The output is shown in the comments after the function prefixed with "out:". - -```rust,ignore -// my-macro/src/lib.rs -# extern crate proc_macro; -# use proc_macro::TokenStream; -#[proc_macro_attribute] -pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream { - println!("attr: \"{attr}\""); - println!("item: \"{item}\""); - item -} -``` - -```rust,ignore -// src/lib.rs -extern crate my_macro; - -use my_macro::show_streams; - -// Example: Basic function -#[show_streams] -fn invoke1() {} -// out: attr: "" -// out: item: "fn invoke1() {}" - -// Example: Attribute with input -#[show_streams(bar)] -fn invoke2() {} -// out: attr: "bar" -// out: item: "fn invoke2() {}" - -// Example: Multiple tokens in the input -#[show_streams(multiple => tokens)] -fn invoke3() {} -// out: attr: "multiple => tokens" -// out: item: "fn invoke3() {}" - -// Example: -#[show_streams { delimiters }] -fn invoke4() {} -// out: attr: "delimiters" -// out: item: "fn invoke4() {}" -``` r[macro.proc.token] ## Declarative macro tokens and procedural macro tokens From fe72d24dfa57a6b6303144ce4bc0245676cf3c11 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 15 Jun 2025 17:49:59 -0700 Subject: [PATCH 4/5] Update proc_macro_attribute to the attribute template --- src/procedural-macros.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index ffe5c44f3e..ab0aa9e51c 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -244,10 +244,8 @@ r[macro.proc.attribute] ## The `proc_macro_attribute` attribute r[macro.proc.attribute.intro] -*Attribute macros* define new [outer attributes][attributes] which can be attached to [items], including items in [`extern` blocks], inherent and trait [implementations], and [trait definitions]. +The *`proc_macro_attribute` [attribute][attributes]* defines an *attribute macro* which can be used as an [outer attribute][attributes]. -r[macro.proc.attribute.def] -Attribute macros are defined by a [public] [function] with the `proc_macro_attribute` [attribute] that has a signature of `(TokenStream, TokenStream) -> TokenStream`. The first [`TokenStream`] is the delimited token tree following the attribute's name, not including the outer delimiters. If the attribute is written as a bare attribute name, the attribute [`TokenStream`] is empty. The second [`TokenStream`] is the rest of the [item] including other [attributes] on the [item]. The returned [`TokenStream`] replaces the [item] with an arbitrary number of [items]. > [!EXAMPLE] > The following attribute macro takes the input stream and returns it as is, effectively being the no-op of attributes. > @@ -263,8 +261,6 @@ Attribute macros are defined by a [public] [function] with the `proc_macro_a > } > ``` -r[macro.proc.attribute.namespace] -The `proc_macro_attribute` attribute defines the attribute in the [macro namespace] in the root of the crate. > [!EXAMPLE] > This following example shows the stringified [`TokenStream`s] that the attribute macros see. The output will show in the output of the compiler. The output is shown in the comments after the function prefixed with "out:". > @@ -314,12 +310,32 @@ The `proc_macro_attribute` attribute defines the attribute in the [macro namespa > // out: item: "fn invoke4() {}" > ``` +r[macro.proc.attribute.syntax] +The `proc_macro_attribute` attribute uses the [MetaWord] syntax and thus does not take any inputs. + +r[macro.proc.attribute.allowed-positions] +The `proc_macro_attribute` attribute may only be applied to a function with the signature of `pub fn(TokenStream, TokenStream) -> TokenStream` where [`TokenStream`] comes from the [`proc_macro` crate]. It must have the ["Rust" ABI][items.fn.extern]. No other function qualifiers are allowed. +r[macro.proc.attribute.duplicates] +The `proc_macro_attribute` attribute may only be specified once on a function. + +r[macro.proc.attribute.namespace] +The `proc_macro_attribute` attribute defines the attribute in the [macro namespace] in the root of the crate with the same name as the function. +r[macro.proc.attribute.use-positions] +Attribute macros can only be used on: +- [items] +- items in [`extern` blocks] +- inherent and trait [implementations] +- [trait definitions] +r[macro.proc.attribute.behavior] +The first [`TokenStream`] parameter is the delimited token tree following the attribute's name, not including the outer delimiters. If the attribute is written as a bare attribute name, the [`TokenStream`] is empty. +The second [`TokenStream`] is the rest of the [item] including other [attributes] on the [item]. +The returned [`TokenStream`] replaces the [item] with an arbitrary number of [items]. r[macro.proc.token] ## Declarative macro tokens and procedural macro tokens From dd41f1fc4d32ca3a357b8b521e3226f2a21f392a Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 21 Oct 2025 20:16:24 +0000 Subject: [PATCH 5/5] Revise `proc_macro_attribute` text --- src/procedural-macros.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index ab0aa9e51c..4395e3db95 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -240,6 +240,7 @@ A helper attribute for a derive macro is declared by adding its identifier to th > } > ``` + r[macro.proc.attribute] ## The `proc_macro_attribute` attribute @@ -247,7 +248,7 @@ r[macro.proc.attribute.intro] The *`proc_macro_attribute` [attribute][attributes]* defines an *attribute macro* which can be used as an [outer attribute][attributes]. > [!EXAMPLE] -> The following attribute macro takes the input stream and returns it as is, effectively being the no-op of attributes. +> This attribute macro takes the input stream and emits it as-is, effectively being a no-op attribute. > > > ```rust,ignore @@ -262,14 +263,13 @@ The *`proc_macro_attribute` [attribute][attributes]* defines an *attribute macro > ``` > [!EXAMPLE] -> This following example shows the stringified [`TokenStream`s] that the attribute macros see. The output will show in the output of the compiler. The output is shown in the comments after the function prefixed with "out:". +> This shows, in the output of the compiler, the stringified [`TokenStream`s] that attribute macros see. > > > ```rust,ignore > // my-macro/src/lib.rs > # extern crate proc_macro; > # use proc_macro::TokenStream; -> > #[proc_macro_attribute] > pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream { > println!("attr: \"{attr}\""); @@ -285,25 +285,25 @@ The *`proc_macro_attribute` [attribute][attributes]* defines an *attribute macro > > use my_macro::show_streams; > -> // Example: Basic function +> // Example: Basic function. > #[show_streams] > fn invoke1() {} > // out: attr: "" > // out: item: "fn invoke1() {}" > -> // Example: Attribute with input +> // Example: Attribute with input. > #[show_streams(bar)] > fn invoke2() {} > // out: attr: "bar" > // out: item: "fn invoke2() {}" > -> // Example: Multiple tokens in the input +> // Example: Multiple tokens in the input. > #[show_streams(multiple => tokens)] > fn invoke3() {} > // out: attr: "multiple => tokens" > // out: item: "fn invoke3() {}" > -> // Example: +> // Example: Delimiters in the input. > #[show_streams { delimiters }] > fn invoke4() {} > // out: attr: "delimiters" @@ -311,10 +311,10 @@ The *`proc_macro_attribute` [attribute][attributes]* defines an *attribute macro > ``` r[macro.proc.attribute.syntax] -The `proc_macro_attribute` attribute uses the [MetaWord] syntax and thus does not take any inputs. +The `proc_macro_attribute` attribute uses the [MetaWord] syntax. r[macro.proc.attribute.allowed-positions] -The `proc_macro_attribute` attribute may only be applied to a function with the signature of `pub fn(TokenStream, TokenStream) -> TokenStream` where [`TokenStream`] comes from the [`proc_macro` crate]. It must have the ["Rust" ABI][items.fn.extern]. No other function qualifiers are allowed. +The `proc_macro_attribute` attribute may only be applied to a `pub` function of type `fn(TokenStream, TokenStream) -> TokenStream` where [`TokenStream`] comes from the [`proc_macro` crate]. It must have the ["Rust" ABI][items.fn.extern]. No other function qualifiers are allowed. It must be located in the root of the crate. r[macro.proc.attribute.duplicates] The `proc_macro_attribute` attribute may only be specified once on a function. @@ -325,17 +325,17 @@ The `proc_macro_attribute` attribute defines the attribute in the [macro namespa r[macro.proc.attribute.use-positions] Attribute macros can only be used on: -- [items] -- items in [`extern` blocks] -- inherent and trait [implementations] -- [trait definitions] +- [Items] +- Items in [`extern` blocks] +- Inherent and trait [implementations] +- [Trait definitions] r[macro.proc.attribute.behavior] -The first [`TokenStream`] parameter is the delimited token tree following the attribute's name, not including the outer delimiters. If the attribute is written as a bare attribute name, the [`TokenStream`] is empty. +The first [`TokenStream`] parameter is the delimited token tree following the attribute's name but not including the outer delimiters. If the applied attribute contains only the attribute name or the attribute name followed by empty delimiters, the [`TokenStream`] is empty. -The second [`TokenStream`] is the rest of the [item] including other [attributes] on the [item]. +The second [`TokenStream`] is the rest of the [item], including other [attributes] on the [item]. -The returned [`TokenStream`] replaces the [item] with an arbitrary number of [items]. +The item to which the attribute is applied is replaced by the zero or more items in the returned [`TokenStream`]. r[macro.proc.token] ## Declarative macro tokens and procedural macro tokens