@@ -87,7 +87,8 @@ pub struct LoweringContext<'a> {
8787 cached_id : Cell < u32 > ,
8888 // Keep track of gensym'ed idents.
8989 gensym_cache : RefCell < HashMap < ( NodeId , & ' static str ) , hir:: Ident > > ,
90- // A copy of cached_id, but is also set to an id while it is being cached.
90+ // A copy of cached_id, but is also set to an id while a node is lowered for
91+ // the first time.
9192 gensym_key : Cell < u32 > ,
9293}
9394
@@ -114,32 +115,79 @@ impl<'a, 'hir> LoweringContext<'a> {
114115 }
115116
116117 fn next_id ( & self ) -> NodeId {
117- let cached = self . cached_id . get ( ) ;
118- if cached == 0 {
118+ let cached_id = self . cached_id . get ( ) ;
119+ if cached_id == 0 {
119120 return self . id_assigner . next_node_id ( ) ;
120121 }
121122
122- self . cached_id . set ( cached + 1 ) ;
123- cached
123+ self . cached_id . set ( cached_id + 1 ) ;
124+ cached_id
124125 }
125126
126127 fn str_to_ident ( & self , s : & ' static str ) -> hir:: Ident {
127- let cached_id = self . gensym_key . get ( ) ;
128- if cached_id == 0 {
128+ let gensym_key = self . gensym_key . get ( ) ;
129+ if gensym_key == 0 {
129130 return hir:: Ident :: from_name ( token:: gensym ( s) ) ;
130131 }
131132
132- let cached = self . gensym_cache . borrow ( ) . contains_key ( & ( cached_id , s) ) ;
133+ let cached = self . gensym_cache . borrow ( ) . contains_key ( & ( gensym_key , s) ) ;
133134 if cached {
134- self . gensym_cache . borrow ( ) [ & ( cached_id , s) ]
135+ self . gensym_cache . borrow ( ) [ & ( gensym_key , s) ]
135136 } else {
136137 let result = hir:: Ident :: from_name ( token:: gensym ( s) ) ;
137- self . gensym_cache . borrow_mut ( ) . insert ( ( cached_id , s) , result) ;
138+ self . gensym_cache . borrow_mut ( ) . insert ( ( gensym_key , s) , result) ;
138139 result
139140 }
140141 }
141142}
142143
144+ // Utility fn for setting and unsetting the cached id.
145+ fn cache_ids < ' a , OP , R > ( lctx : & LoweringContext , expr_id : NodeId , op : OP ) -> R
146+ where OP : FnOnce ( & LoweringContext ) -> R
147+ {
148+ // Only reset the id if it was previously 0, i.e., was not cached.
149+ // If it was cached, we are in a nested node, but our id count will
150+ // still count towards the parent's count.
151+ let reset_cached_id = lctx. cached_id . get ( ) == 0 ;
152+ // We always reset gensym_key so that if we use the same name in a nested
153+ // node and after that node, they get different values.
154+ let old_gensym_key = lctx. gensym_key . get ( ) ;
155+
156+ {
157+ let id_cache: & mut HashMap < _ , _ > = & mut lctx. id_cache . borrow_mut ( ) ;
158+
159+ if id_cache. contains_key ( & expr_id) {
160+ let cached_id = lctx. cached_id . get ( ) ;
161+ if cached_id == 0 {
162+ // We're entering a node where we need to track ids, but are not
163+ // yet tracking.
164+ lctx. cached_id . set ( id_cache[ & expr_id] ) ;
165+ } else {
166+ // We're already tracking - check that the tracked id is the same
167+ // as the expected id.
168+ assert ! ( cached_id == id_cache[ & expr_id] , "id mismatch" ) ;
169+ }
170+ lctx. gensym_key . set ( id_cache[ & expr_id] ) ;
171+ } else {
172+ // We've never lowered this node before, remember it for next time.
173+ let next_id = lctx. id_assigner . peek_node_id ( ) ;
174+ id_cache. insert ( expr_id, next_id) ;
175+ lctx. gensym_key . set ( next_id) ;
176+ // self.cached_id is not set when we lower a node for the first time,
177+ // only on re-lowering.
178+ }
179+ }
180+
181+ let result = op ( lctx) ;
182+
183+ if reset_cached_id {
184+ lctx. cached_id . set ( 0 ) ;
185+ }
186+ lctx. gensym_key . set ( old_gensym_key) ;
187+
188+ result
189+ }
190+
143191pub fn lower_ident ( _lctx : & LoweringContext , ident : Ident ) -> hir:: Ident {
144192 hir:: Ident {
145193 name : mtwt:: resolve ( ident) ,
@@ -918,47 +966,6 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
918966 } )
919967}
920968
921- // Utility fn for setting and unsetting the cached id.
922- fn cache_ids < ' a , OP , R > ( lctx : & LoweringContext , expr_id : NodeId , op : OP ) -> R
923- where OP : FnOnce ( & LoweringContext ) -> R
924- {
925- // Only reset the id if it was previously 0, i.e., was not cached.
926- // If it was cached, we are in a nested node, but our id count will
927- // still count towards the parent's count.
928- let reset_cached_id = lctx. cached_id . get ( ) == 0 ;
929-
930- {
931- let id_cache: & mut HashMap < _ , _ > = & mut lctx. id_cache . borrow_mut ( ) ;
932-
933- if id_cache. contains_key ( & expr_id) {
934- let cached_id = lctx. cached_id . get ( ) ;
935- if cached_id == 0 {
936- // We're entering a node where we need to track ids, but are not
937- // yet tracking.
938- lctx. cached_id . set ( id_cache[ & expr_id] ) ;
939- lctx. gensym_key . set ( id_cache[ & expr_id] ) ;
940- } else {
941- // We're already tracking - check that the tracked id is the same
942- // as the expected id.
943- assert ! ( cached_id == id_cache[ & expr_id] , "id mismatch" ) ;
944- }
945- } else {
946- let next_id = lctx. id_assigner . peek_node_id ( ) ;
947- id_cache. insert ( expr_id, next_id) ;
948- lctx. gensym_key . set ( next_id) ;
949- }
950- }
951-
952- let result = op ( lctx) ;
953-
954- if reset_cached_id {
955- lctx. cached_id . set ( 0 ) ;
956- lctx. gensym_key . set ( 0 ) ;
957- }
958-
959- result
960- }
961-
962969pub fn lower_expr ( lctx : & LoweringContext , e : & Expr ) -> P < hir:: Expr > {
963970 P ( hir:: Expr {
964971 id : e. id ,
@@ -1935,7 +1942,9 @@ mod test {
19351942 let ast_while_let = assigner. fold_expr ( ast_while_let) ;
19361943 let ast_for = quote_expr ! ( & cx,
19371944 for i in 0 ..10 {
1938- foo( i) ;
1945+ for j in 0 ..10 {
1946+ foo( i, j) ;
1947+ }
19391948 } ) ;
19401949 let ast_for = assigner. fold_expr ( ast_for) ;
19411950 let ast_in = quote_expr ! ( & cx, in HEAP { foo( ) } ) ;
0 commit comments