Idea: macros in attribute position

Say you have this macro:

macro_rules! foo {
    ($($tt:tt)*) => {/* something useful */}
}

foo! {
    fn bar() {}
}

I've been wondering about invoking the macro using an attribute instead. It solves rightward drift and generally looks cleaner.

#[foo]
fn bar() {}

Could this feasibly be added to the language? Might it be any easier if it only worked for macros 2.0 and we didn't bother with macro_rules?

It's possible. No one has created a concrete proposal for this to my knowledge.

For the time being, you can get close to this with crates such as macro_rules_attribute - Rust. You'll just have to write something like #[apply(foo)] instead of #[foo].

1 Like

The main limitation btw is that while function like macros work on arbitrary token trees, attributes have to be applied to a valid parse.

2 Likes

While nobody tried to write an RFC so I can't be sure, I'm afraid this is quite unusable since declarative macros cannot easily parse e.g. generics without tt munching.

1 Like

It is not entirely unusable. Attributes like #[tokio::main] only wrap the function body in something that calls a special function. No parsing of the function body needed for that and it can be done without parsing generics I think. There is also #[bevy::main] which just adds a couple of functions for iOS and Android entry points while leaving the main function intact.

You still need to parse the function signature. And main() is indeed special in that it can't have generic parameters and/or parameters (these also cannot be parsed accurately by macro_rules!), but should we add this feature for that (and tests!) or just let them write a little proc macro?

You can restrict the argument pattern to just a literal name instead of accepting arbitrary patterns and then do something like Rust Playground to emulate #[tracing::instrument].

I'm really worried about that. Because if macros will not support patterns in parameter positions, people will just not use it (there is already a demand for not using it because it is not supported well by rustdoc, and that makes me sad). So we will end up with worse code and unecessary feature that needs to be maintained forever.

If macros cannot parse the full syntax, I don't want them at supported where they need to parse it, because people will just not use the full syntax, effectively splitting the language and creating dialects. If anything, we need macros to be able to parse the full syntax and only then think about allowing them at attribute position.