@@ -87,7 +87,8 @@ pub struct LoweringContext<'a> {
87
87
cached_id : Cell < u32 > ,
88
88
// Keep track of gensym'ed idents.
89
89
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.
91
92
gensym_key : Cell < u32 > ,
92
93
}
93
94
@@ -114,32 +115,79 @@ impl<'a, 'hir> LoweringContext<'a> {
114
115
}
115
116
116
117
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 {
119
120
return self . id_assigner . next_node_id ( ) ;
120
121
}
121
122
122
- self . cached_id . set ( cached + 1 ) ;
123
- cached
123
+ self . cached_id . set ( cached_id + 1 ) ;
124
+ cached_id
124
125
}
125
126
126
127
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 {
129
130
return hir:: Ident :: from_name ( token:: gensym ( s) ) ;
130
131
}
131
132
132
- let cached = self . gensym_cache . borrow ( ) . contains_key ( & ( cached_id , s) ) ;
133
+ let cached = self . gensym_cache . borrow ( ) . contains_key ( & ( gensym_key , s) ) ;
133
134
if cached {
134
- self . gensym_cache . borrow ( ) [ & ( cached_id , s) ]
135
+ self . gensym_cache . borrow ( ) [ & ( gensym_key , s) ]
135
136
} else {
136
137
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) ;
138
139
result
139
140
}
140
141
}
141
142
}
142
143
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
+
143
191
pub fn lower_ident ( _lctx : & LoweringContext , ident : Ident ) -> hir:: Ident {
144
192
hir:: Ident {
145
193
name : mtwt:: resolve ( ident) ,
@@ -918,47 +966,6 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
918
966
} )
919
967
}
920
968
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
-
962
969
pub fn lower_expr ( lctx : & LoweringContext , e : & Expr ) -> P < hir:: Expr > {
963
970
P ( hir:: Expr {
964
971
id : e. id ,
@@ -1935,7 +1942,9 @@ mod test {
1935
1942
let ast_while_let = assigner. fold_expr ( ast_while_let) ;
1936
1943
let ast_for = quote_expr ! ( & cx,
1937
1944
for i in 0 ..10 {
1938
- foo( i) ;
1945
+ for j in 0 ..10 {
1946
+ foo( i, j) ;
1947
+ }
1939
1948
} ) ;
1940
1949
let ast_for = assigner. fold_expr ( ast_for) ;
1941
1950
let ast_in = quote_expr ! ( & cx, in HEAP { foo( ) } ) ;
0 commit comments