Skip to content

Commit 80bd085

Browse files
authored
Merge pull request #1887 from ehuss/proc_macro
Update `proc_macro` to use the attribute template
2 parents 52ce896 + b4fbe46 commit 80bd085

File tree

4 files changed

+61
-48
lines changed

4 files changed

+61
-48
lines changed

book.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use-boolean-and = true
3535
"/lifetime-elision.html#static-lifetime-elision" = "lifetime-elision.html#const-and-static-elision"
3636
"/macros-by-example.html#path-based-scope" = "macros-by-example.html#the-macro_export-attribute"
3737
"/procedural-macros.html#derive-macros" = "procedural-macros.html#the-proc_macro_derive-attribute"
38+
"/procedural-macros.html#function-like-procedural-macros" = "procedural-macros.html#the-proc_macro-attribute"
3839
"/runtime.html#the-panic_handler-attribute" = "panic.html#the-panic_handler-attribute"
3940
"/unsafe-blocks.html" = "unsafe-keyword.html"
4041
"/unsafe-functions.html" = "unsafe-keyword.html"

src/attributes.md

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

src/names/namespaces.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ It is still an error for a [`use` import] to shadow another macro, regardless of
153153
[field expression]: ../expressions/field-expr.md
154154
[Function declarations]: ../items/functions.md
155155
[function parameters]: ../items/functions.md#function-parameters
156-
[Function-like procedural macros]: ../procedural-macros.md#function-like-procedural-macros
156+
[Function-like procedural macros]: ../procedural-macros.md#the-proc_macro-attribute
157157
[Generic const parameters]: ../items/generics.md#const-generics
158158
[Generic lifetime parameters]: ../items/generics.md
159159
[Generic type parameters]: ../items/generics.md

src/procedural-macros.md

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ r[macro.proc.error]
4242
Procedural macros have two ways of reporting errors. The first is to panic. The
4343
second is to emit a [`compile_error`] macro invocation.
4444
45-
r[macro.proc.proc_macro]
45+
r[macro.proc.proc_macro-crate]
4646
## The `proc_macro` crate
4747
48-
r[macro.proc.proc_macro.intro]
48+
r[macro.proc.proc_macro-crate.intro]
4949
Procedural macro crates almost always will link to the compiler-provided
5050
[`proc_macro` crate]. The `proc_macro` crate provides types required for
5151
writing procedural macros and facilities to make it easier.
5252
53-
r[macro.proc.proc_macro.token-stream]
53+
r[macro.proc.proc_macro-crate.token-stream]
5454
This crate primarily contains a [`TokenStream`] type. Procedural macros operate
5555
over *token streams* instead of AST nodes, which is a far more stable interface
5656
over time for both the compiler and for procedural macros to target. A
@@ -59,7 +59,7 @@ can roughly be thought of as lexical token. For example `foo` is an `Ident`
5959
token, `.` is a `Punct` token, and `1.2` is a `Literal` token. The `TokenStream`
6060
type, unlike `Vec<TokenTree>`, is cheap to clone.
6161
62-
r[macro.proc.proc_macro.span]
62+
r[macro.proc.proc_macro-crate.span]
6363
All tokens have an associated `Span`. A `Span` is an opaque value that cannot
6464
be modified but can be manufactured. `Span`s represent an extent of source
6565
code within a program and are primarily used for error reporting. While you
@@ -79,56 +79,68 @@ items in libraries (for example, `::std::option::Option` instead of `Option`) or
7979
by ensuring that generated functions have names that are unlikely to clash with
8080
other functions (like `__internal_foo` instead of `foo`).
8181
82-
r[macro.proc.function]
83-
## Function-like procedural macros
84-
85-
r[macro.proc.function.intro]
86-
*Function-like procedural macros* are procedural macros that are invoked using
87-
the macro invocation operator (`!`).
88-
89-
r[macro.proc.function.def]
90-
These macros are defined by a [public]&#32;[function] with the `proc_macro`
91-
[attribute] and a signature of `(TokenStream) -> TokenStream`. The input
92-
[`TokenStream`] is what is inside the delimiters of the macro invocation and the
93-
output [`TokenStream`] replaces the entire macro invocation.
82+
<!-- TODO: rule name needs improvement -->
83+
<!-- template:attributes -->
84+
r[macro.proc.proc_macro]
85+
## The `proc_macro` attribute
9486
95-
r[macro.proc.function.namespace]
96-
The `proc_macro` attribute defines the macro in the [macro namespace] in the root of the crate.
87+
r[macro.proc.proc_macro.intro]
88+
The *`proc_macro` [attribute][attributes]* defines a [function-like][macro.invocation] procedural macro.
9789
98-
For example, the following macro definition ignores its input and outputs a
99-
function `answer` into its scope.
90+
> [!EXAMPLE]
91+
> This macro definition ignores its input and emits a function `answer` into its scope.
92+
>
93+
> <!-- ignore: test doesn't support proc-macro -->
94+
> ```rust,ignore
95+
> # #![crate_type = "proc-macro"]
96+
> extern crate proc_macro;
97+
> use proc_macro::TokenStream;
98+
>
99+
> #[proc_macro]
100+
> pub fn make_answer(_item: TokenStream) -> TokenStream {
101+
> "fn answer() -> u32 { 42 }".parse().unwrap()
102+
> }
103+
> ```
104+
>
105+
> We can use it in a binary crate to print "42" to standard output.
106+
>
107+
> <!-- ignore: requires external crates -->
108+
> ```rust,ignore
109+
> extern crate proc_macro_examples;
110+
> use proc_macro_examples::make_answer;
111+
>
112+
> make_answer!();
113+
>
114+
> fn main() {
115+
> println!("{}", answer());
116+
> }
117+
> ```
100118
101-
<!-- ignore: test doesn't support proc-macro -->
102-
```rust,ignore
103-
# #![crate_type = "proc-macro"]
104-
extern crate proc_macro;
105-
use proc_macro::TokenStream;
119+
r[macro.proc.proc_macro.syntax]
120+
The `proc_macro` attribute uses the [MetaWord] syntax.
106121
107-
#[proc_macro]
108-
pub fn make_answer(_item: TokenStream) -> TokenStream {
109-
"fn answer() -> u32 { 42 }".parse().unwrap()
110-
}
111-
```
122+
r[macro.proc.proc_macro.allowed-positions]
123+
The `proc_macro` attribute may only be applied to a `pub` function of type `fn(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.
112124
113-
And then we use it in a binary crate to print "42" to standard output.
125+
r[macro.proc.proc_macro.duplicates]
126+
The `proc_macro` attribute may only be specified once on a function.
114127
115-
<!-- ignore: requires external crates -->
116-
```rust,ignore
117-
extern crate proc_macro_examples;
118-
use proc_macro_examples::make_answer;
128+
r[macro.proc.proc_macro.namespace]
129+
The `proc_macro` attribute publicly defines the macro in the [macro namespace] in the root of the crate with the same name as the function.
119130
120-
make_answer!();
131+
r[macro.proc.proc_macro.behavior]
132+
A function-like macro invocation of a function-like procedural macro will pass what is inside the delimiters of the macro invocation as the input [`TokenStream`] argument and replace the entire macro invocation with the output [`TokenStream`] of the function.
121133
122-
fn main() {
123-
println!("{}", answer());
124-
}
125-
```
134+
r[macro.proc.proc_macro.invocation]
135+
Function-like procedural macros may be invoked in any macro invocation position, which includes:
126136
127-
r[macro.proc.function.invocation]
128-
Function-like procedural macros may be invoked in any macro invocation
129-
position, which includes [statements], [expressions], [patterns], [type
130-
expressions], [item] positions, including items in [`extern` blocks], inherent
131-
and trait [implementations], and [trait definitions].
137+
- [Statements]
138+
- [Expressions]
139+
- [Patterns]
140+
- [Type expressions]
141+
- [Item] positions, including items in [`extern` blocks]
142+
- Inherent and trait [implementations]
143+
- [Trait definitions]
132144
133145
<!-- template:attributes -->
134146
r[macro.proc.derive]
@@ -384,7 +396,7 @@ their equivalent `#[doc = r"str"]` attributes when passed to macros.
384396
[Attribute macros]: #attribute-macros
385397
[Cargo's build scripts]: ../cargo/reference/build-scripts.html
386398
[Derive macros]: macro.proc.derive
387-
[Function-like macros]: #function-like-procedural-macros
399+
[Function-like macros]: #the-proc_macro-attribute
388400
[`$crate`]: macro.decl.hygiene.crate
389401
[`Delimiter::None`]: proc_macro::Delimiter::None
390402
[`Group`]: proc_macro::Group

0 commit comments

Comments
 (0)