One long-standing problem of the Rust macro system is the inability to generate item identifiers inside macro expansions (1 2 3 4 5). So far, macro reforms had failed to address this issue, but I think this is important enough, that we should try again before v1.0 is finalized.
Here are a few solutions, that I’ve seen proposed over the years (plus one that I came up with). I would like to see if we can reach a consensus about the best way to proceed. Other ideas are welcome too, of course!
- Add token pasting operator in MBEs, for example “+". We could then have an MBE RHS like "`... => ( foo_ + $x )`” expand into “foo_bar” identifier ($x being “bar”).
A significant drawback of this scheme, IMO, is that it wouldn’t be possible to abstract away identifier generation into a separate macro; all concatenation has to be inline.
Also, this doesn’t cover any operations other than concatenation. What if somebody wants to write a syntax extension to uppercase idents?
- Change Rust parser and AST to allow macros to appear in ident positions.
There was an RFC and an implementation PR of that last year, but they were rejected on the grounds that this might interfere with a possible future “macro methods” syntax.
Admittedly, this extension was broader than absolutely needed, because it would allow to use macros in place of idents even outside of the context of macro expansion, which could easily be confusing.
- Add a new standard syntax extension for eager expansion of macros. For example:
... => ( eager_expand!( concat_idents!(foo_, $x) as #x,
concat_idents!(foo_, $y) as #y in
mod #x {
fn #y (...) {}
}
) )
The idea here is to eagerly expand macros on the LHS side of "in", and substitute results into the RHS, in place of the corresponding identifiers. The RHS is then the result of expansion of this macro.
The # prefix is to prevent the outer macro from messing with eager_expand’s internal identifiers. Another way to achieve the same would be to create an escape for $'s in Rust MBEs, say $$. In this case, these idents would be spelled as $$x and $$y.