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

Popular posts from this blog

python - No exponential form of the z-axis in matplotlib-3D-plots -

php - Best Light server (Linux + Web server + Database) for Raspberry Pi -

c# - "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" error when deserializing class -