@@ -17,7 +17,6 @@ use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
17
17
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
18
18
use rustc_span:: symbol:: sym;
19
19
use rustc_span:: Span ;
20
- use smallvec:: SmallVec ;
21
20
use tracing:: debug;
22
21
23
22
mod drop_ranges;
@@ -29,13 +28,6 @@ struct InteriorVisitor<'a, 'tcx> {
29
28
expr_count : usize ,
30
29
kind : hir:: GeneratorKind ,
31
30
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 ,
39
31
linted_values : HirIdSet ,
40
32
drop_ranges : DropRanges ,
41
33
}
@@ -48,7 +40,6 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
48
40
scope : Option < region:: Scope > ,
49
41
expr : Option < & ' tcx Expr < ' tcx > > ,
50
42
source_span : Span ,
51
- guard_borrowing_from_pattern : bool ,
52
43
) {
53
44
use rustc_span:: DUMMY_SP ;
54
45
@@ -89,8 +80,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
89
80
// If it is a borrowing happening in the guard,
90
81
// it needs to be recorded regardless because they
91
82
// 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
94
84
} )
95
85
. cloned ( )
96
86
} )
@@ -196,8 +186,6 @@ pub fn resolve_interior<'a, 'tcx>(
196
186
expr_count : 0 ,
197
187
kind,
198
188
prev_unresolved_span : None ,
199
- guard_bindings : <_ >:: default ( ) ,
200
- guard_bindings_set : <_ >:: default ( ) ,
201
189
linted_values : <_ >:: default ( ) ,
202
190
drop_ranges : drop_ranges:: compute_drop_ranges ( fcx, def_id, body) ,
203
191
} ;
@@ -284,15 +272,47 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
284
272
let Arm { guard, pat, body, .. } = arm;
285
273
self . visit_pat ( pat) ;
286
274
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) ;
294
315
}
295
- . visit_pat ( pat) ;
296
316
297
317
match g {
298
318
Guard :: If ( ref e) => {
@@ -302,12 +322,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
302
322
self . visit_let_expr ( l) ;
303
323
}
304
324
}
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
- }
311
325
}
312
326
self . visit_expr ( body) ;
313
327
}
@@ -320,13 +334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
320
334
if let PatKind :: Binding ( ..) = pat. kind {
321
335
let scope = self . region_scope_tree . var_scope ( pat. hir_id . local_id ) . unwrap ( ) ;
322
336
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 ) ;
324
338
}
325
339
}
326
340
327
341
fn visit_expr ( & mut self , expr : & ' tcx Expr < ' tcx > ) {
328
- let mut guard_borrowing_from_pattern = false ;
329
-
330
342
match & expr. kind {
331
343
ExprKind :: Call ( callee, args) => match & callee. kind {
332
344
ExprKind :: Path ( qpath) => {
@@ -353,16 +365,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
353
365
}
354
366
_ => intravisit:: walk_expr ( self , expr) ,
355
367
} ,
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
- }
366
368
_ => intravisit:: walk_expr ( self , expr) ,
367
369
}
368
370
@@ -391,14 +393,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
391
393
// If there are adjustments, then record the final type --
392
394
// this is the actual value that is being produced.
393
395
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 ) ;
402
397
}
403
398
404
399
// Also record the unadjusted type (which is the only type if
@@ -426,54 +421,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
426
421
// The type table might not have information for this expression
427
422
// if it is in a malformed scope. (#66387)
428
423
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 ) ;
456
425
} else {
457
426
self . fcx . tcx . sess . delay_span_bug ( expr. span , "no type for node" ) ;
458
427
}
459
428
}
460
429
}
461
430
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
-
477
431
#[ derive( Default ) ]
478
432
pub struct SuspendCheckData < ' a , ' tcx > {
479
433
expr : Option < & ' tcx Expr < ' tcx > > ,
0 commit comments