Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this macro result in an unresolved name error?

Tags:

macros

rust

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?

like image 971
Philipp Matthias Schäfer Avatar asked Jan 23 '16 15:01

Philipp Matthias Schäfer


1 Answers

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;
        }
    }
}
like image 57
DK. Avatar answered Sep 28 '22 11:09

DK.