Weird macro expansion
⚓ Rust 📅 2025-12-12 👤 surdeus 👁️ 3Take 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
🏷️ Rust_feed