@@ -240,91 +240,102 @@ A helper attribute for a derive macro is declared by adding its identifier to th
240240> }
241241> ```
242242
243+ <!-- template:attributes -->
243244r[macro.proc.attribute]
244- ## Attribute macros
245+ ## The `proc_macro_attribute` attribute
245246
246247r[macro.proc.attribute.intro]
247- *Attribute macros* define new [outer attributes][attributes] which can be
248- attached to [items], including items in [`extern` blocks], inherent and trait
249- [implementations], and [trait definitions].
250-
251- r[macro.proc.attribute.def]
252- Attribute macros are defined by a [public] [function] with the
253- `proc_macro_attribute` [attribute] that has a signature of `(TokenStream,
254- TokenStream) -> TokenStream`. The first [`TokenStream`] is the delimited token
255- tree following the attribute's name, not including the outer delimiters. If
256- the attribute is written as a bare attribute name, the attribute
257- [`TokenStream`] is empty. The second [`TokenStream`] is the rest of the [item]
258- including other [attributes] on the [item]. The returned [`TokenStream`]
259- replaces the [item] with an arbitrary number of [items].
248+ The *`proc_macro_attribute` [attribute][attributes]* defines an *attribute macro* which can be used as an [outer attribute][attributes].
249+
250+ > [!EXAMPLE]
251+ > This attribute macro takes the input stream and emits it as-is, effectively being a no-op attribute.
252+ >
253+ > <!-- ignore: test doesn't support proc-macro -->
254+ > ```rust,ignore
255+ > # #![crate_type = "proc-macro"]
256+ > # extern crate proc_macro;
257+ > # use proc_macro::TokenStream;
258+ >
259+ > #[proc_macro_attribute]
260+ > pub fn return_as_is(_attr: TokenStream, item: TokenStream) -> TokenStream {
261+ > item
262+ > }
263+ > ```
264+
265+ > [!EXAMPLE]
266+ > This shows, in the output of the compiler, the stringified [`TokenStream`s] that attribute macros see.
267+ >
268+ > <!-- ignore: test doesn't support proc-macro -->
269+ > ```rust,ignore
270+ > // my-macro/src/lib.rs
271+ > # extern crate proc_macro;
272+ > # use proc_macro::TokenStream;
273+ > #[proc_macro_attribute]
274+ > pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream {
275+ > println!("attr: \"{attr}\"");
276+ > println!("item: \"{item}\"");
277+ > item
278+ > }
279+ > ```
280+ >
281+ > <!-- ignore: requires external crates -->
282+ > ```rust,ignore
283+ > // src/lib.rs
284+ > extern crate my_macro;
285+ >
286+ > use my_macro::show_streams;
287+ >
288+ > // Example: Basic function.
289+ > #[show_streams]
290+ > fn invoke1() {}
291+ > // out: attr: ""
292+ > // out: item: "fn invoke1() {}"
293+ >
294+ > // Example: Attribute with input.
295+ > #[show_streams(bar)]
296+ > fn invoke2() {}
297+ > // out: attr: "bar"
298+ > // out: item: "fn invoke2() {}"
299+ >
300+ > // Example: Multiple tokens in the input.
301+ > #[show_streams(multiple => tokens)]
302+ > fn invoke3() {}
303+ > // out: attr: "multiple => tokens"
304+ > // out: item: "fn invoke3() {}"
305+ >
306+ > // Example: Delimiters in the input.
307+ > #[show_streams { delimiters }]
308+ > fn invoke4() {}
309+ > // out: attr: "delimiters"
310+ > // out: item: "fn invoke4() {}"
311+ > ```
312+
313+ r[macro.proc.attribute.syntax]
314+ The `proc_macro_attribute` attribute uses the [MetaWord] syntax.
315+
316+ r[macro.proc.attribute.allowed-positions]
317+ 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.
318+
319+ r[macro.proc.attribute.duplicates]
320+ The `proc_macro_attribute` attribute may only be specified once on a function.
260321
261322r[macro.proc.attribute.namespace]
262- The `proc_macro_attribute` attribute defines the attribute in the [macro namespace] in the root of the crate.
323+ 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 .
263324
264- For example, this attribute macro takes the input stream and returns it as is,
265- effectively being the no-op of attributes.
325+ r[ macro.proc.attribute.use-positions]
326+ Attribute macros can only be used on:
266327
267- <!-- ignore: test doesn't support proc-macro -->
268- ```rust,ignore
269- # #![crate_type = "proc-macro"]
270- # extern crate proc_macro;
271- # use proc_macro::TokenStream;
328+ - [Items]
329+ - Items in [`extern` blocks]
330+ - Inherent and trait [implementations]
331+ - [Trait definitions]
272332
273- #[proc_macro_attribute]
274- pub fn return_as_is(_attr: TokenStream, item: TokenStream) -> TokenStream {
275- item
276- }
277- ```
333+ r[macro.proc.attribute.behavior]
334+ 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.
278335
279- This following example shows the stringified [ ` TokenStream ` s] that the attribute
280- macros see. The output will show in the output of the compiler. The output is
281- shown in the comments after the function prefixed with "out:".
282-
283- <!-- ignore: test doesn't support proc-macro -->
284- ``` rust,ignore
285- // my-macro/src/lib.rs
286- # extern crate proc_macro;
287- # use proc_macro::TokenStream;
288-
289- #[proc_macro_attribute]
290- pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream {
291- println!("attr: \"{attr}\"");
292- println!("item: \"{item}\"");
293- item
294- }
295- ```
336+ The second [`TokenStream`] is the rest of the [item], including other [attributes] on the [item].
296337
297- <!-- ignore: requires external crates -->
298- ``` rust,ignore
299- // src/lib.rs
300- extern crate my_macro;
301-
302- use my_macro::show_streams;
303-
304- // Example: Basic function
305- #[show_streams]
306- fn invoke1() {}
307- // out: attr: ""
308- // out: item: "fn invoke1() {}"
309-
310- // Example: Attribute with input
311- #[show_streams(bar)]
312- fn invoke2() {}
313- // out: attr: "bar"
314- // out: item: "fn invoke2() {}"
315-
316- // Example: Multiple tokens in the input
317- #[show_streams(multiple => tokens)]
318- fn invoke3() {}
319- // out: attr: "multiple => tokens"
320- // out: item: "fn invoke3() {}"
321-
322- // Example:
323- #[show_streams { delimiters }]
324- fn invoke4() {}
325- // out: attr: "delimiters"
326- // out: item: "fn invoke4() {}"
327- ```
338+ The item to which the attribute is applied is replaced by the zero or more items in the returned [`TokenStream`].
328339
329340r[macro.proc.token]
330341## Declarative macro tokens and procedural macro tokens
@@ -393,7 +404,7 @@ Note that neither declarative nor procedural macros support doc comment tokens
393404(e.g. `/// Doc`), so they are always converted to token streams representing
394405their equivalent `#[doc = r"str"]` attributes when passed to macros.
395406
396- [ Attribute macros ] : #attribute-macros
407+ [Attribute macros]: #the-proc_macro_attribute-attribute
397408[Cargo's build scripts]: ../cargo/reference/build-scripts.html
398409[Derive macros]: macro.proc.derive
399410[Function-like macros]: #the-proc_macro-attribute
0 commit comments