user1271598
user1271598

Reputation:

Why does this macro result in an unresolved name error?

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

Answers (2)

DK.
DK.

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

jwilm
jwilm

Reputation: 447

Your fn bar doesn't have anything named saved in scope at the invocation site.

Upvotes: 0

Related Questions