rust - 'Unresolved name' inside macro despite 'ident' designator -
i'm playing around rust macro system in order learn more how works. wrote simple macro takes identifier , adds list of numbers it.
macro_rules! do_your_thing { ( $v:ident; $($e:expr),+ ) => { let mut $v = 0; $( $v += $e; )+ }; } fn main() { do_your_thing!(i; 3, 3, 3); println!("{}", i); }
if run this program, compiler complain 3 times 'i' being unresolved name every repetition inside macro '$v += $e;'
<anon>:5:13: 5:15 error: unresolved name `i` <anon>:5 $v += $e; ^
i know macros in rust hygienic. why used ident
designator. possible there additional syntactic context repetition $(...)+
?
update
after dk.'s answer did little digging , found hygiene
argument --pretty
option. basically, annotates syntax contexts after macro expansion happened. after running
rustc -z unstable-options --pretty expanded,hygiene main.rs
on initial program gave me following output
fn main /* 67#0 */() { let mut /* 68#4 */ = 0; /* 68#3 */ += 3; /* 68#3 */ += 3; /* 68#3 */ += 3; }
running same command on dk.'s modifications resulted in
fn main /* 67#0 */() { let /* 68#4 */ = { let mut /* 68#5 */ = 0; /* 68#5 */ += 3; /* 68#5 */ += 3; /* 68#5 */ += 3; /* 68#5 */ }; }
so, $(...)+ inside macro did in fact introduce new syntax context in original macro. however, wrapping in block, dk did, somehow prevented happening. instead new syntax context introduced whole block.
ok, 1 weird. first, here's found work:
macro_rules! do_your_thing { ( $v:ident; $($e:expr),+ ) => { let mut $v = { let mut $v = 0; $( $v += $e; )+ $v }; }; } fn main() { do_your_thing!(i; 3, 3, 3); println!("{}", i); }
the problem, near can tell, original macro producing set of statements, , somehow confusing compiler. wrapping statements in block appears fix this.
of course, then problem putting let mut $v
scope makes inaccessible following println!
, modified return final value block, assigned new $v
.
honestly, can't think of why original code shouldn't have worked. might bug... or might yet subtlety of macro_rules!
haven't gotten hold of yet. it's hard tell. :)
Comments
Post a Comment