@@ -28,9 +28,8 @@ struct InteriorVisitor<'a, 'tcx> {
28
28
/// such borrows can span across this yield point.
29
29
/// As such, we need to track these borrows and record them despite of the fact
30
30
/// that they may succeed the said yield point in the post-order.
31
- nested_scope_of_guards : SmallVec < [ SmallVec < [ HirId ; 4 ] > ; 4 ] > ,
32
- current_scope_of_guards : HirIdSet ,
33
- arm_has_guard : bool ,
31
+ guard_bindings : SmallVec < [ SmallVec < [ HirId ; 4 ] > ; 1 ] > ,
32
+ guard_bindings_set : HirIdSet ,
34
33
}
35
34
36
35
impl < ' a , ' tcx > InteriorVisitor < ' a , ' tcx > {
@@ -147,9 +146,8 @@ pub fn resolve_interior<'a, 'tcx>(
147
146
expr_count : 0 ,
148
147
kind,
149
148
prev_unresolved_span : None ,
150
- nested_scope_of_guards : <_ >:: default ( ) ,
151
- current_scope_of_guards : <_ >:: default ( ) ,
152
- arm_has_guard : false ,
149
+ guard_bindings : <_ >:: default ( ) ,
150
+ guard_bindings_set : <_ >:: default ( ) ,
153
151
} ;
154
152
intravisit:: walk_body ( & mut visitor, body) ;
155
153
@@ -228,25 +226,34 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
228
226
229
227
fn visit_arm ( & mut self , arm : & ' tcx Arm < ' tcx > ) {
230
228
if arm. guard . is_some ( ) {
231
- self . nested_scope_of_guards . push ( <_ >:: default ( ) ) ;
232
- self . arm_has_guard = true ;
229
+ self . guard_bindings . push ( <_ >:: default ( ) ) ;
233
230
}
234
231
self . visit_pat ( & arm. pat ) ;
235
232
if let Some ( ref g) = arm. guard {
233
+ self . guard_bindings . push ( <_ >:: default ( ) ) ;
234
+ ArmPatCollector {
235
+ guard_bindings_set : & mut self . guard_bindings_set ,
236
+ guard_bindings : self
237
+ . guard_bindings
238
+ . last_mut ( )
239
+ . expect ( "should have pushed at least one earlier" ) ,
240
+ }
241
+ . visit_pat ( & arm. pat ) ;
242
+
236
243
match g {
237
244
Guard :: If ( ref e) => {
238
245
self . visit_expr ( e) ;
239
246
}
240
247
}
248
+
241
249
let mut scope_var_ids =
242
- self . nested_scope_of_guards . pop ( ) . expect ( "should have pushed at least one earlier" ) ;
250
+ self . guard_bindings . pop ( ) . expect ( "should have pushed at least one earlier" ) ;
243
251
for var_id in scope_var_ids. drain ( ..) {
244
252
assert ! (
245
- self . current_scope_of_guards . remove( & var_id) ,
253
+ self . guard_bindings_set . remove( & var_id) ,
246
254
"variable should be placed in scope earlier"
247
255
) ;
248
256
}
249
- self . arm_has_guard = false ;
250
257
}
251
258
self . visit_expr ( & arm. body ) ;
252
259
}
@@ -256,14 +263,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
256
263
257
264
self . expr_count += 1 ;
258
265
259
- if let PatKind :: Binding ( _ , id , ..) = pat. kind {
266
+ if let PatKind :: Binding ( ..) = pat. kind {
260
267
let scope = self . region_scope_tree . var_scope ( pat. hir_id . local_id ) ;
261
268
let ty = self . fcx . typeck_results . borrow ( ) . pat_ty ( pat) ;
262
269
self . record ( ty, Some ( scope) , None , pat. span , false ) ;
263
- if self . arm_has_guard {
264
- self . nested_scope_of_guards . as_mut_slice ( ) . last_mut ( ) . unwrap ( ) . push ( id) ;
265
- self . current_scope_of_guards . insert ( id) ;
266
- }
267
270
}
268
271
}
269
272
@@ -299,8 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
299
302
intravisit:: walk_expr ( self , expr) ;
300
303
let res = self . fcx . typeck_results . borrow ( ) . qpath_res ( qpath, expr. hir_id ) ;
301
304
match res {
302
- Res :: Local ( id) if self . current_scope_of_guards . contains ( & id) => {
303
- debug ! ( "a borrow in guard from pattern local is detected" ) ;
305
+ Res :: Local ( id) if self . guard_bindings_set . contains ( & id) => {
304
306
guard_borrowing_from_pattern = true ;
305
307
}
306
308
_ => { }
@@ -350,3 +352,24 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
350
352
}
351
353
}
352
354
}
355
+
356
+ struct ArmPatCollector < ' a > {
357
+ guard_bindings_set : & ' a mut HirIdSet ,
358
+ guard_bindings : & ' a mut SmallVec < [ HirId ; 4 ] > ,
359
+ }
360
+
361
+ impl < ' a , ' tcx > Visitor < ' tcx > for ArmPatCollector < ' a > {
362
+ type Map = intravisit:: ErasedMap < ' tcx > ;
363
+
364
+ fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
365
+ NestedVisitorMap :: None
366
+ }
367
+
368
+ fn visit_pat ( & mut self , pat : & ' tcx Pat < ' tcx > ) {
369
+ intravisit:: walk_pat ( self , pat) ;
370
+ if let PatKind :: Binding ( _, id, ..) = pat. kind {
371
+ self . guard_bindings . push ( id) ;
372
+ self . guard_bindings_set . insert ( id) ;
373
+ }
374
+ }
375
+ }
0 commit comments