@@ -28,9 +28,8 @@ struct InteriorVisitor<'a, 'tcx> {
2828 /// such borrows can span across this yield point.
2929 /// As such, we need to track these borrows and record them despite of the fact
3030 /// 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 ,
3433}
3534
3635impl < ' a , ' tcx > InteriorVisitor < ' a , ' tcx > {
@@ -147,9 +146,8 @@ pub fn resolve_interior<'a, 'tcx>(
147146 expr_count : 0 ,
148147 kind,
149148 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 ( ) ,
153151 } ;
154152 intravisit:: walk_body ( & mut visitor, body) ;
155153
@@ -228,25 +226,34 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
228226
229227 fn visit_arm ( & mut self , arm : & ' tcx Arm < ' tcx > ) {
230228 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 ( ) ) ;
233230 }
234231 self . visit_pat ( & arm. pat ) ;
235232 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+
236243 match g {
237244 Guard :: If ( ref e) => {
238245 self . visit_expr ( e) ;
239246 }
240247 }
248+
241249 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" ) ;
243251 for var_id in scope_var_ids. drain ( ..) {
244252 assert ! (
245- self . current_scope_of_guards . remove( & var_id) ,
253+ self . guard_bindings_set . remove( & var_id) ,
246254 "variable should be placed in scope earlier"
247255 ) ;
248256 }
249- self . arm_has_guard = false ;
250257 }
251258 self . visit_expr ( & arm. body ) ;
252259 }
@@ -256,14 +263,10 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
256263
257264 self . expr_count += 1 ;
258265
259- if let PatKind :: Binding ( _ , id , ..) = pat. kind {
266+ if let PatKind :: Binding ( ..) = pat. kind {
260267 let scope = self . region_scope_tree . var_scope ( pat. hir_id . local_id ) ;
261268 let ty = self . fcx . typeck_results . borrow ( ) . pat_ty ( pat) ;
262269 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- }
267270 }
268271 }
269272
@@ -299,8 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
299302 intravisit:: walk_expr ( self , expr) ;
300303 let res = self . fcx . typeck_results . borrow ( ) . qpath_res ( qpath, expr. hir_id ) ;
301304 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) => {
304306 guard_borrowing_from_pattern = true ;
305307 }
306308 _ => { }
@@ -350,3 +352,24 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
350352 }
351353 }
352354}
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