Started writing this last night but it was too late to finish it up. BTW, there was also this RFC for macro expansion inside proc macros.
My main thought here is that it’s weird to special case “a cfg that is a combination of other cfgs” and “a derive that is a combination of other derives”. Shouldn’t we go up a level and say “an attribute that’s a combination of other attributes”? That is: #![ let my_attrib = #[cfg(foo)] #[derive(Clone)] ]. (not actually proposing this.)
I was actually going to go the same route of suggesting this be implemented via macros as well. Today we can already do it this way:
macro_rules! my_attrib {
($i: item) => ( #[cfg(foo)] #[derive(Clone)] $i )
}
my_attrib! { struct A; }
but what I would like to see is the ability to put macros in attribute position, like so (though this may not work in Rust’s actual AST order):
macro_rules! my_attrib { // or `macro_rules! #[my_attrib]`
() => ( #[cfg(foo)] #[derive(Clone)] )
}
#[my_attrib!] struct A; // again, arbitrary syntax
// tiny change to today's macro syntax - just adds #[name!] in addition to name!()/name![]/name!{}
or the slightly simpler but harder to read:
macro_rules! my_attrib {
() => ( #[cfg(foo)] #[derive(Clone)] )
}
my_attrib![] struct A;
// no change to today's macro syntax, only in where macros can be placed
Another, possibly more elegant solution, would be to allow macros like #[my_attrib!] tt; which are equivalent to my_attrib!(tt); (i.e. it takes the immediately following token tree and transforms it into another token tree). Perhaps it’s too general (just “another way” to do the thing in the first example), but it seems nice and it enables a slightly nicer syntax (for the first example, and many other current uses of macros):
macro_rules! #[my_attrib] {
($i: item) => ( #[cfg(foo)] #[derive(Clone)] $i )
}
#[my_attrib!] struct A;