Reputation:
I would like to compile code similiar to this minimal test case:
macro_rules! why {
( [ $saved:ident ] $body:block ) => {
let $saved = 3;
$body
let _a = $saved;
}
}
fn bar() {
why!([saved] {
});
}
fn main() {
}
When I try to compile it, I get the following error:
src/main.rs:10:20: 10:21 error: unresolved name `saved` [E0425]
src/main.rs:10 why!([saved] {
^
src/main.rs:10:9: 11:12 note: in this expansion of why! (defined in src/main.rs)
src/main.rs:10:20: 10:21 help: run `rustc --explain E0425` to see a detailed explanation
Other macros that introduce variables work; what's the problem here?
Upvotes: 5
Views: 787
Reputation: 59145
This is because macro_rules!
is kinda broken when it comes to macros that expand to statements.
The problem is basically that it considers each statement independently for the purposes of hygiene. In other words, the third statement literally cannot see the binding defined on the first line.
In some cases, you can work around this by wrapping the statements in a block:
macro_rules! why {
( [ $saved:ident ] $body:block ) => {
{
let $saved = 3;
$body
let _a = $saved;
}
}
}
Upvotes: 6
Reputation: 447
Your fn bar
doesn't have anything named saved
in scope at the invocation site.
Upvotes: 0