Why does this macro result in an unresolved name error?

I would like to compile code similar to this minimal test example:

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 is the problem?

+5
source share
2 answers

This is because macro_rules! is broken incorrectly when it comes to macros that expand to statements.

The problem basically is that it considers each statement independently for hygiene purposes. In other words, the third operator literally does not see the binding defined in the first line.

In some cases, you can get around this by wrapping the statements in a block:

 macro_rules! why { ( [ $saved:ident ] $body:block ) => { { let $saved = 3; $body let _a = $saved; } } } 
+7
source

Your fn bar has nothing saved in scope on the call site.

+1
source

Source: https://habr.com/ru/post/1241310/


All Articles