Weird macro expansion

⚓ Rust    📅 2025-12-12    👤 surdeus    👁️ 3      

surdeus

Info

This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Weird macro expansion

Take this cute macro (Rust Playground):

macro_rules! m {
    ( $($x:stmt;)* ) => { $($x)* };
}

fn main() {
    m!(4;5;);
}

To my surprise, the code expands the macro successfully and parses! I'd expect that it'll error due to not using semicolons within the macro body. This alone could perhaps be explained by saying that the stmt fragment, despite not capturing the trailing semicolon, acts like it's present - somewhat similar to invisible groups.

But this is only the beginning of the weirdness, because we get this totally unexpected compile error:

error[E0308]: mismatched types
 --> src/main.rs:6:8
  |
6 |     m!(4;5;);
  |        ^ expected `()`, found integer

For more information about this error, try `rustc --explain E0308`.

So somehow the compiler thinks our statements are not just 4; 5;.

And if we try to "fix" the macro by adding semicolons, we get (Rust Playground):

macro_rules! m {
    ( $($x:stmt;)* ) => { $($x;)* };
}

fn main() {
    m!(4;5;);
}
warning: unnecessary trailing semicolon
 --> src/main.rs:2:31
  |
2 |     ( $($x:stmt;)* ) => { $($x;)* };
  |                               ^
...
6 |     m!(4;5;);
  |     -------- in this macro invocation
  |
  = note: `#[warn(redundant_semicolons)]` (part of `#[warn(unused)]`) on by default
  = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
 --> src/main.rs:6:8
  |
6 |     m!(4;5;);
  |        ^ expected `()`, found integer

error[E0308]: mismatched types
 --> src/main.rs:6:10
  |
6 |     m!(4;5;);
  |          ^ expected `()`, found integer

So the compiler thinks our semicolons are redundant, but we also get two "mismatched types" error instead of one.

3 posts - 3 participants

Read full topic

🏷️ Rust_feed