Allow attribute and function macros to share name

Rusts builtin cfg!(...) and #[cfg(...)] already share a namespace without issues, as they have two different non-conflicting methods of calling.

This would allow having different ways of, e.g., exposing a proc-macro both as an attribute and a function, or sharing a name between a proc-macro attribute macro and a macro_rules macro.

When one wants to combine two identically named proc-macros, this can be problematic, not from the callers' perspective, but from the implementing crate, as you cannot have two functions of identical name in the same module. This is however a separate issue.

My use case is the manyhow crate, inspired by anyhow and I wanted to both have a #[manyhow] attribute to annotate proc-macro implementations with and a manyhow!() (which I now had to rename) macro_rules macro that would be like anyhow!(...). But those names conflict, even though, they don't have to, IMO.

2 Likes

I did notice, that #[cfg(...)] is not necessarily a “proc-macro attribute” but a built-in language feature, but that doesn't really change the fact, that it is not necessary for them to conflict when they are.

I also recently noticed this and would really like it, for being able to support #[throws] fn foo() { ... } along with throws!(|| { ... }) for being able to stably annotate both functions and closures with the same macro.

My thought on API was that instead of trying to split the macro namespace up, it could still be a single proc-macro but with arguments that allow it to distinguish how it was called:

#[proc_macro_maybe_attribute]
fn foo(tokens: TokenStream, other_tokens: Option<TokenStream>) -> TokenStream

#[foo]
struct Foo;
// would be like
foo(TokenStream::new(), Some(TokenStream::parse("struct Foo;")))

foo!(struct Foo)
// would be like
foo(TokenStream::parse("struct Foo"), None)

yes, but this would not solve having one proc-macro and one macro_rules. And is probably actually more difficult in terms of getting it potentially accepted.