@@ -17,7 +17,6 @@ use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
1717use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
1818use rustc_span:: symbol:: sym;
1919use rustc_span:: Span ;
20- use smallvec:: SmallVec ;
2120use tracing:: debug;
2221
2322mod drop_ranges;
@@ -29,13 +28,6 @@ struct InteriorVisitor<'a, 'tcx> {
2928 expr_count : usize ,
3029 kind : hir:: GeneratorKind ,
3130 prev_unresolved_span : Option < Span > ,
32- /// Match arm guards have temporary borrows from the pattern bindings.
33- /// In case there is a yield point in a guard with a reference to such bindings,
34- /// such borrows can span across this yield point.
35- /// As such, we need to track these borrows and record them despite of the fact
36- /// that they may succeed the said yield point in the post-order.
37- guard_bindings : SmallVec < [ SmallVec < [ HirId ; 4 ] > ; 1 ] > ,
38- guard_bindings_set : HirIdSet ,
3931 linted_values : HirIdSet ,
4032 drop_ranges : DropRanges ,
4133}
@@ -48,7 +40,6 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
4840 scope : Option < region:: Scope > ,
4941 expr : Option < & ' tcx Expr < ' tcx > > ,
5042 source_span : Span ,
51- guard_borrowing_from_pattern : bool ,
5243 ) {
5344 use rustc_span:: DUMMY_SP ;
5445
@@ -89,8 +80,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
8980 // If it is a borrowing happening in the guard,
9081 // it needs to be recorded regardless because they
9182 // do live across this yield point.
92- guard_borrowing_from_pattern
93- || yield_data. expr_and_pat_count >= self . expr_count
83+ yield_data. expr_and_pat_count >= self . expr_count
9484 } )
9585 . cloned ( )
9686 } )
@@ -196,8 +186,6 @@ pub fn resolve_interior<'a, 'tcx>(
196186 expr_count : 0 ,
197187 kind,
198188 prev_unresolved_span : None ,
199- guard_bindings : <_ >:: default ( ) ,
200- guard_bindings_set : <_ >:: default ( ) ,
201189 linted_values : <_ >:: default ( ) ,
202190 drop_ranges : drop_ranges:: compute_drop_ranges ( fcx, def_id, body) ,
203191 } ;
@@ -284,15 +272,47 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
284272 let Arm { guard, pat, body, .. } = arm;
285273 self . visit_pat ( pat) ;
286274 if let Some ( ref g) = guard {
287- self . guard_bindings . push ( <_ >:: default ( ) ) ;
288- ArmPatCollector {
289- guard_bindings_set : & mut self . guard_bindings_set ,
290- guard_bindings : self
291- . guard_bindings
292- . last_mut ( )
293- . expect ( "should have pushed at least one earlier" ) ,
275+ {
276+ // If there is a guard, we need to count all variables bound in the pattern as
277+ // borrowed for the entire guard body, regardless of whether they are accessed.
278+ // We do this by walking the pattern bindings and recording `&T` for any `x: T`
279+ // that is bound.
280+
281+ struct ArmPatCollector < ' a , ' b , ' tcx > {
282+ interior_visitor : & ' a mut InteriorVisitor < ' b , ' tcx > ,
283+ scope : Scope ,
284+ }
285+
286+ impl < ' a , ' b , ' tcx > Visitor < ' tcx > for ArmPatCollector < ' a , ' b , ' tcx > {
287+ fn visit_pat ( & mut self , pat : & ' tcx Pat < ' tcx > ) {
288+ intravisit:: walk_pat ( self , pat) ;
289+ if let PatKind :: Binding ( _, id, ident, ..) = pat. kind {
290+ let ty =
291+ self . interior_visitor . fcx . typeck_results . borrow ( ) . node_type ( id) ;
292+ let tcx = self . interior_visitor . fcx . tcx ;
293+ let ty = tcx. mk_ref (
294+ // Use `ReErased` as `resolve_interior` is going to replace all the
295+ // regions anyway.
296+ tcx. mk_region ( ty:: ReErased ) ,
297+ ty:: TypeAndMut { ty, mutbl : hir:: Mutability :: Not } ,
298+ ) ;
299+ self . interior_visitor . record (
300+ ty,
301+ id,
302+ Some ( self . scope ) ,
303+ None ,
304+ ident. span ,
305+ ) ;
306+ }
307+ }
308+ }
309+
310+ ArmPatCollector {
311+ interior_visitor : self ,
312+ scope : Scope { id : g. body ( ) . hir_id . local_id , data : ScopeData :: Node } ,
313+ }
314+ . visit_pat ( pat) ;
294315 }
295- . visit_pat ( pat) ;
296316
297317 match g {
298318 Guard :: If ( ref e) => {
@@ -302,12 +322,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
302322 self . visit_let_expr ( l) ;
303323 }
304324 }
305-
306- let mut scope_var_ids =
307- self . guard_bindings . pop ( ) . expect ( "should have pushed at least one earlier" ) ;
308- for var_id in scope_var_ids. drain ( ..) {
309- self . guard_bindings_set . remove ( & var_id) ;
310- }
311325 }
312326 self . visit_expr ( body) ;
313327 }
@@ -320,13 +334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
320334 if let PatKind :: Binding ( ..) = pat. kind {
321335 let scope = self . region_scope_tree . var_scope ( pat. hir_id . local_id ) . unwrap ( ) ;
322336 let ty = self . fcx . typeck_results . borrow ( ) . pat_ty ( pat) ;
323- self . record ( ty, pat. hir_id , Some ( scope) , None , pat. span , false ) ;
337+ self . record ( ty, pat. hir_id , Some ( scope) , None , pat. span ) ;
324338 }
325339 }
326340
327341 fn visit_expr ( & mut self , expr : & ' tcx Expr < ' tcx > ) {
328- let mut guard_borrowing_from_pattern = false ;
329-
330342 match & expr. kind {
331343 ExprKind :: Call ( callee, args) => match & callee. kind {
332344 ExprKind :: Path ( qpath) => {
@@ -353,16 +365,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
353365 }
354366 _ => intravisit:: walk_expr ( self , expr) ,
355367 } ,
356- ExprKind :: Path ( qpath) => {
357- intravisit:: walk_expr ( self , expr) ;
358- let res = self . fcx . typeck_results . borrow ( ) . qpath_res ( qpath, expr. hir_id ) ;
359- match res {
360- Res :: Local ( id) if self . guard_bindings_set . contains ( & id) => {
361- guard_borrowing_from_pattern = true ;
362- }
363- _ => { }
364- }
365- }
366368 _ => intravisit:: walk_expr ( self , expr) ,
367369 }
368370
@@ -391,14 +393,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
391393 // If there are adjustments, then record the final type --
392394 // this is the actual value that is being produced.
393395 if let Some ( adjusted_ty) = self . fcx . typeck_results . borrow ( ) . expr_ty_adjusted_opt ( expr) {
394- self . record (
395- adjusted_ty,
396- expr. hir_id ,
397- scope,
398- Some ( expr) ,
399- expr. span ,
400- guard_borrowing_from_pattern,
401- ) ;
396+ self . record ( adjusted_ty, expr. hir_id , scope, Some ( expr) , expr. span ) ;
402397 }
403398
404399 // Also record the unadjusted type (which is the only type if
@@ -426,54 +421,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
426421 // The type table might not have information for this expression
427422 // if it is in a malformed scope. (#66387)
428423 if let Some ( ty) = self . fcx . typeck_results . borrow ( ) . expr_ty_opt ( expr) {
429- if guard_borrowing_from_pattern {
430- // Match guards create references to all the bindings in the pattern that are used
431- // in the guard, e.g. `y if is_even(y) => ...` becomes `is_even(*r_y)` where `r_y`
432- // is a reference to `y`, so we must record a reference to the type of the binding.
433- let tcx = self . fcx . tcx ;
434- let ref_ty = tcx. mk_ref (
435- // Use `ReErased` as `resolve_interior` is going to replace all the regions anyway.
436- tcx. mk_region ( ty:: ReErased ) ,
437- ty:: TypeAndMut { ty, mutbl : hir:: Mutability :: Not } ,
438- ) ;
439- self . record (
440- ref_ty,
441- expr. hir_id ,
442- scope,
443- Some ( expr) ,
444- expr. span ,
445- guard_borrowing_from_pattern,
446- ) ;
447- }
448- self . record (
449- ty,
450- expr. hir_id ,
451- scope,
452- Some ( expr) ,
453- expr. span ,
454- guard_borrowing_from_pattern,
455- ) ;
424+ self . record ( ty, expr. hir_id , scope, Some ( expr) , expr. span ) ;
456425 } else {
457426 self . fcx . tcx . sess . delay_span_bug ( expr. span , "no type for node" ) ;
458427 }
459428 }
460429}
461430
462- struct ArmPatCollector < ' a > {
463- guard_bindings_set : & ' a mut HirIdSet ,
464- guard_bindings : & ' a mut SmallVec < [ HirId ; 4 ] > ,
465- }
466-
467- impl < ' a , ' tcx > Visitor < ' tcx > for ArmPatCollector < ' a > {
468- fn visit_pat ( & mut self , pat : & ' tcx Pat < ' tcx > ) {
469- intravisit:: walk_pat ( self , pat) ;
470- if let PatKind :: Binding ( _, id, ..) = pat. kind {
471- self . guard_bindings . push ( id) ;
472- self . guard_bindings_set . insert ( id) ;
473- }
474- }
475- }
476-
477431#[ derive( Default ) ]
478432pub struct SuspendCheckData < ' a , ' tcx > {
479433 expr : Option < & ' tcx Expr < ' tcx > > ,
0 commit comments