Given this code:
macro_rules! macro_a {
($val:expr) => {
let tmp = $val;
println!("{}", tmp);
};
}
fn main() {
let tmp = false;
macro_a!(42);
println!("After macro_a: {}", tmp);
}
According to cargo expand
, this expands to:
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
fn main() {
let tmp = false;
let tmp = 42;
{
::std::io::_print(format_args!("{0}\n", tmp));
};
{
::std::io::_print(format_args!("After macro_a: {0}\n", tmp));
};
}
And when I mouse-hover over the variable tmp
in the last println!()
, VSCode shows me the hint let tmp: i32
.
Yet, when I compile and run it, I get:
42
After macro_a: false
I would have expected:
42
After macro_a: 42
How does false
sneak by the macro? Is this a compiler bug?
If I compile the output of cargo expand
directly, I get the following output:
#![feature(prelude_import)]
#![feature(print_internals)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
fn main() {
let tmp = false;
let tmp = 42;
{
::std::io::_print(format_args!("{0}\n", tmp));
};
{
::std::io::_print(format_args!("After macro_a: {0}\n", tmp));
};
}
$ cargo +nightly run
42
After macro_a: 42
What's going on here? Do macros introduce a hidden scope or something? Is this a bug in rustc
or in cargo-expand
? One of them have to be wrong, otherwise this behaviour wouldn't be inconsistent ...
If I leave out the first declaration of tmp, I get a compiler error:
macro_rules! macro_a {
($val:expr) => {
let tmp = $val;
println!("{}", tmp);
};
}
fn main() {
macro_a!(42);
println!("After macro_a: {}", tmp);
}
error[E0425]: cannot find value `tmp` in this scope
--> src/main.rs:10:35
|
10 | println!("After macro_a: {}", tmp);
| ^^^ not found in this scope
I thought this should work? Isn't a macro simply inserted into the code?
This compiles:
macro_rules! macro_a {
($name: ident, $val:expr) => {
let $name = $val;
println!("{}", $name);
};
}
fn main() {
macro_a!(tmp, 42);
println!("After macro_a: {}", tmp);
}
What's the difference between the two?