Skip to content

Macro metavar expr concat doesn't work with nested repetitions #127723

Open
@Noratrieb

Description

@Noratrieb

Is it a known issue that this doesn't seem to work with identifiers repeating at a depth?

#![feature(macro_metavar_expr_concat)]

macro_rules! many_idents {
    ($a:ident, $c:ident) => {
        const ${concat($a, B, $c, D)}: i32 = 1;
    };
}

// Paste implementation included for reference
macro_rules! many_idents_paste {
    ($a:ident, $c:ident) => {
        paste::paste! {
            const [<$a B $c D>]: i32 = 2;
        }
    };
}

macro_rules! many_idents_multi_metavar {
    ($($a:ident, $c:ident;)*) => {
        $(
            const ${concat($a, B, $c, D)}: i32 = 3;
        )*
    };
}

// Paste implementation included for reference
macro_rules! many_idents_multi_paste {
    ($($a:ident, $c:ident;)*) => {
        $(
            paste::paste! {
                const [<$a B $c D>]: i32 = 3;
            }
        )*
    };
}

fn main() {
    many_idents!(A, C);
    assert_eq!(ABCD, 1);
    many_idents_paste!(F, G);
    assert_eq!(FBGD, 2);
    many_idents_multi_paste! {
        H, I;
        J, K;
        L, M;
    }
    assert_eq!(HBID, 3);
    assert_eq!(JBKD, 3);
    assert_eq!(LBMD, 3);
    many_idents_multi_metavar! {
        N, O;
        P, Q;
        R, S;
    }
}
error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
  --> src/main.rs:19:10
   |
19 |           $(
   |  __________^
20 | |             const ${concat($a, B, $c, D)}: i32 = 3;
21 | |         )*
   | |_________^

The paste version works without errors.

I can go a bit further with ignore

macro_rules! many_idents_multi_metavar {
    ($($a:ident, $c:ident;)*) => {
        $(
            ${ignore($a)}
            ${ignore($c)}
            const ${concat($a, B, $c, D)}: i32 = 3;
        )*
    };
}

But then I get:

error: `${concat(..)}` currently only accepts identifiers or meta-variables as parameters
  --> src/main.rs:22:29
   |
22 |             const ${concat($a, B, $c, D)}: i32 = 3;
   |     

This seems like a major limitation.

Originally posted by @crumblingstatue in #124225 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.F-macro_metavar_expr_concat`#![feature(macro_metavar_expr_concat)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions