Skip to content

macro_metavar_expr_concat broken when combining repeats and optionals #150002

@bjorn3

Description

@bjorn3

I tried this code:

#![feature(macro_metavar_expr_concat)]
macro_rules! define_ioctl_data {
    (struct $s:ident {
        $($field:ident: $ty:ident $([$opt:ident])?,)*
    }) => {
        pub struct $s {
            $($field: $ty,)*
        }

        impl $s {
            $($(
                fn ${concat(get_, $field)}(&self) -> $ty {
                    let _ = $opt;
                    todo!()
                }
            )?)*
        }
    };
}

define_ioctl_data! {
    struct Foo {
        a: A [aa],
        b: B [bb],
    }
}

I expected to see this happen: Expands to

pub struct Foo {
    a: A,
    b: B,
}
impl Foo {
    fn get_a(&self) -> A {
        let _ = aa;

        ::core::panicking::panic("not yet implemented")
    }
    fn get_b(&self) -> B {
        let _ = bb;
        ::core::panicking::panic("not yet implemented")
    }
}

Instead, this happened: Expands to

pub struct Foo {
    a: A,
    b: B,
}
impl Foo {
    fn get_a(&self) -> A {
        let _ = aa;

        ::core::panicking::panic("not yet implemented")
    }
    fn get_a(&self) -> B {
        let _ = bb;
        ::core::panicking::panic("not yet implemented")
    }
}

which defines get_a twice.

Meta

rustc --version --verbose:

1.94.0-nightly (2025-12-13 430d8297c712ca7e8a48)

Metadata

Metadata

Assignees

Labels

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