Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
661912e
Declarative `macro_rules!` attribute macros
joshtriplett Sep 21, 2024
6c9944b
RFC 3697
joshtriplett Sep 21, 2024
6fd82e8
Attribute macros are active
joshtriplett Sep 21, 2024
2b4989b
Fix typo
joshtriplett Sep 21, 2024
258608e
Remove the extra `=>`
joshtriplett Sep 21, 2024
fa7820f
Abbreviate to `attr`, with `cfg_attr` as precedent
joshtriplett Sep 22, 2024
0e4e46c
Mention `$crate`
joshtriplett Sep 24, 2024
0fea475
Caching
joshtriplett Sep 24, 2024
b11f474
Add an alternative way of marking and handling attr/non-attr macros
joshtriplett Sep 25, 2024
d13e2ba
Clarify justification for having a single macro support attr and non-…
joshtriplett Sep 25, 2024
0900f9f
Add notes about backwards compatibility of adding `attr` rules
joshtriplett Sep 25, 2024
26e6969
Note that both `MacroMatcher`s share the same namespace
joshtriplett Sep 26, 2024
5cfb620
Document the cases of no arguments and empty arguments
joshtriplett Sep 26, 2024
10f011d
Future possibilities: better error reporting
joshtriplett Sep 26, 2024
1cfec3d
Add drawbacks section mentioning impact on crate maintainers
joshtriplett Sep 30, 2024
b7d4e06
Expand future work
joshtriplett Sep 30, 2024
0110363
Future possibilities: consider the case of multiple attributes in any…
joshtriplett Oct 1, 2024
23cd82f
Recursion
joshtriplett Oct 2, 2024
9fbf852
Clarify recursive invocation
joshtriplett Oct 2, 2024
95838c4
Fix typo
joshtriplett Oct 2, 2024
ff26c82
Add unresolved question to make sure we don't have awful error messages
joshtriplett Oct 2, 2024
25ab000
Word-wrapping
joshtriplett Oct 22, 2024
66ac59f
Support unsafe attributes
joshtriplett Oct 22, 2024
5fdd0d8
Copy a drawback to the unresolved questions section
joshtriplett Oct 22, 2024
f2eb3ed
Fix missing backquote
joshtriplett Oct 28, 2024
27efc29
Example
joshtriplett Oct 28, 2024
e43905e
Document that an attribute macro may invoke another, or itself
joshtriplett Nov 9, 2024
31f4eb7
Document how the compiler should handle using a non-attr macro as an …
joshtriplett Nov 18, 2024
cd2c9f5
Future possibility: attribute macros that don't modify the original t…
joshtriplett Nov 20, 2024
a7dde80
Copy motivating examples from prior art to motivation
joshtriplett Jun 4, 2025
be3c823
Fix typo
joshtriplett Jun 12, 2025
7594f62
Document an additional unresolved question for evaluation during impl…
joshtriplett Jun 12, 2025
f4bfd55
RFC 3697
joshtriplett Jul 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Abbreviate to attr, with cfg_attr as precedent
  • Loading branch information
joshtriplett committed Sep 22, 2024
commit fa7820faa3381661c5399496cf032b98d660b6c0
27 changes: 14 additions & 13 deletions text/3697-declarative-attribute-macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ the user to enable a feature.
[guide-level-explanation]: #guide-level-explanation

When defining a `macro_rules!` macro, you can prefix some of the macro's rules
with `attribute(...)` to allow using the macro as an attribute. The
with `attr(...)` to allow using the macro as an attribute. The
arguments to the attribute, if any, are parsed by the *MacroMatcher* in the
first set of parentheses; the second *MacroMatcher* parses the entire construct
the attribute was applied to. The resulting macro will work anywhere an
attribute currently works.

```rust
macro_rules! main {
attribute() ($func:item) => { make_async_main!($func) };
attribute(threads = $threads:literal) ($func:item) => { make_async_main!($threads, $func) };
attr() ($func:item) => { make_async_main!($func) };
attr(threads = $threads:literal) ($func:item) => { make_async_main!($threads, $func) };
}

#[main]
Expand All @@ -51,20 +51,20 @@ any other macro, and may be invoked by any path that resolves to them.
An attribute macro must not require itself for resolution, either directly or
indirectly (e.g. applied to a containing module or item).

Note that a single macro can have both attribute and non-attribute rules.
Attribute invocations can only match the attribute rules, and non-attribute
invocations can only match the non-attribute rules.
Note that a single macro can have both `attr` and non-`attr` rules. Attribute
invocations can only match the `attr` rules, and non-attribute invocations can
only match the non-`attr` rules.

For simplicity, an attribute macro may not recursively invoke its attribute
rules; to recurse, invoke a non-attribute rule or another macro.
For simplicity, an attribute macro may not recursively invoke its `attr` rules;
to recurse, invoke a non-`attr` rule or another macro.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

The grammar for macros is extended as follows:

> _MacroRule_ :\
> &nbsp;&nbsp; ( `attribute` _MacroMatcher_ )<sup>?</sup> _MacroMatcher_ `=>` _MacroTranscriber_
> &nbsp;&nbsp; ( `attr` _MacroMatcher_ )<sup>?</sup> _MacroMatcher_ `=>` _MacroTranscriber_

The first _MacroMatcher_ matches the attribute's arguments, which will be an
empty token tree if not present. The second _MacroMatcher_ matches the entire
Expand All @@ -73,7 +73,7 @@ proc-macro-based attribute would in the same place.

This grammar addition is backwards compatible: previously, a _MacroRule_ could
only start with `(`, `[`, or `{`, so the parser can easily distinguish the
identifier `attribute`.
identifier `attr`.

Attribute macros declared using `macro_rules!` are
[active](https://doc.rust-lang.org/reference/attributes.html#active-and-inert-attributes),
Expand Down Expand Up @@ -104,9 +104,10 @@ solution is to parse one while carrying along the other.
We could include another `=>` or other syntax between the first and second
macro matchers.

We could use `attr` rather than `attribute`. Rust usually avoids abbreviating
except for the most common constructs; however, this can occur repeatedly in
multiple rules, so it may make sense to abbreviate it.
We could use `attribute` rather than `attr`. Rust usually avoids abbreviating
except for the most common constructs; however, `cfg_attr` provides precedent
for this abbreviation, and `attr` appears repeatedly in multiple rules which
motivates abbreviating it.

# Prior art
[prior-art]: #prior-art
Expand Down