Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rust macro expansion ignores token `,` and any following

Tags:

macros

rust

this does work

macro_rules! x2 {
    ($x:expr) => {
        [$x, $x]
    };
}


let a = x2!(0)

but the quite similar

macro_rules! x2 {
    ($x:expr) => {
        $x, $x     //removed brackets
    };
}


let a = [x2!(0)]   //added brackets

does not and cancels expansion at the first seperator , with error:

macro expansion ignores token `,` and any following
the usage of `x2!` is likely invalid in expression context
  • why is the seperator valid in one version and in the other not, they would unwrap to the same code?

  • is there a way i could build something similar (to only fill part of the array like e.g. let a = [x2!(1),0])?

    • would a declarative macro suffice?
    • if not, would that be a use-case for a procedural one?

i get that the working example produces an immediatly valid expression, while the latter only does in the context it's expanded in, but why does that matter? (the compiler already hints that the context might produce an invalid syntax but thats clearly not the case?)

like image 969
HannesH Avatar asked Oct 24 '25 16:10

HannesH


1 Answers

i get that the working example produces an immediatly valid expression, while the latter only does in the context it's expanded in, but why does that matter?

To quote from my favourite resource on rust macros, the Little Book of Rust Macros:

All syntax extensions in Rust must result in a complete, supported syntax element (such as an expression, item, etc.). This means that it is impossible to have a syntax extension expand to a partial construct.

Found in this section of the book.

I assume Rust imposes this hygienic constraint on macros, because compile errors caused by badly expanded macros are horrible to debug, often times with unhelpful error messages.

like image 108
Jonas Fassbender Avatar answered Oct 27 '25 11:10

Jonas Fassbender