Concat_idents! ,curious

just curious what stops fn concat_idents!(..) working, how deep a problem is it (is it something that's just lower priority or is there some intrinsic structural problem in how macro contents are parsed.. I dont know my way around the rust compiler and it's most likely changed alot since I last looked..)

this would be an awesome feature especially with the absence of overloading, i.e. rolling naming conventions (the other thing I'd be interested in is a camel-case / snake case switch ie. for rolling the naming conventions consistently .. e.g. imagine a 'single-function trait' macro, etc)

Macro invocations are incorporated into rust's grammar. This means that you can only call a macro in places where it is supported. The currently supported places include expressions, types, and the body of a module (where it may produce zero or more items)... but it does not include identifiers.

Of course, the above is just a statement of the status quo. With that, the question becomes, what's stopping Rust from supporting macros in identifiers?

This I don't know for certain, but I will point out the following:

  • The macro invocation grammar begins with an ident.

  • To my knowledge, current rust is always able to tell exactly what any given macro's output should be parsed as (expression, type, or items) without having to look ahead after the closing brace. But suppose we wrote something like this:

    // the identity macro
    macro_rules! id { ($($x:tt)+) => {$($x)+}; }
    fn main() {
        let x: id!(Vec)<usize> = vec![];

    Currently, this is a parse error; it parses id!(Vec) as a type, which cannot be followed by <. However, if macros were supported in all identifiers, then in theory it could alternatively choose to parse id!(Vec) as an identifier, in which case the type could be successfully parsed as id!(Vec)<usize>.

    Of course, that would require the grammar for types to look ahead and see if there is a < after the macro call. If it did, it seems to me this would create problems in as casts.

    // this is already stable
    vec![] as id!(Vec<usize>) < vec![]; // '<' is comparison
    // meaning we can't have this
    vec![] as id!(Vec)<usize>;          // '<' is part of type

Maybe this could be saved by somehow limiting it to specific idents; those in declarations. Honestly, I don't know! In any case, most discussion I've seen has not been about trying to save concat_idents!, but rather, finding entirely new solutions to the problem that concat_idents! was meant to solve (such as early macro expansion, or gensyms).

1 Like