@@ -7,8 +7,9 @@ use clippy_utils::{
7
7
} ;
8
8
use rustc_errors:: Applicability ;
9
9
use rustc_hir:: {
10
+ hir_id:: HirIdSet ,
10
11
intravisit:: { walk_expr, ErasedMap , NestedVisitorMap , Visitor } ,
11
- Block , Expr , ExprKind , Guard , HirId , Local , Stmt , StmtKind , UnOp ,
12
+ Block , Expr , ExprKind , Guard , HirId , Pat , Stmt , StmtKind , UnOp ,
12
13
} ;
13
14
use rustc_lint:: { LateContext , LateLintPass } ;
14
15
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
@@ -336,6 +337,8 @@ struct InsertSearcher<'cx, 'tcx> {
336
337
edits : Vec < Edit < ' tcx > > ,
337
338
/// A stack of loops the visitor is currently in.
338
339
loops : Vec < HirId > ,
340
+ /// Local variables created in the expression. These don't need to be captured.
341
+ locals : HirIdSet ,
339
342
}
340
343
impl < ' tcx > InsertSearcher < ' _ , ' tcx > {
341
344
/// Visit the expression as a branch in control flow. Multiple insert calls can be used, but
@@ -383,13 +386,16 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
383
386
}
384
387
} ,
385
388
StmtKind :: Expr ( e) => self . visit_expr ( e) ,
386
- StmtKind :: Local ( Local { init : Some ( e) , .. } ) => {
387
- self . allow_insert_closure &= !self . in_tail_pos ;
388
- self . in_tail_pos = false ;
389
- self . is_single_insert = false ;
390
- self . visit_expr ( e) ;
389
+ StmtKind :: Local ( l) => {
390
+ self . visit_pat ( l. pat ) ;
391
+ if let Some ( e) = l. init {
392
+ self . allow_insert_closure &= !self . in_tail_pos ;
393
+ self . in_tail_pos = false ;
394
+ self . is_single_insert = false ;
395
+ self . visit_expr ( e) ;
396
+ }
391
397
} ,
392
- _ => {
398
+ StmtKind :: Item ( _ ) => {
393
399
self . allow_insert_closure &= !self . in_tail_pos ;
394
400
self . is_single_insert = false ;
395
401
} ,
@@ -471,6 +477,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
471
477
// Each branch may contain it's own insert expression.
472
478
let mut is_map_used = self . is_map_used ;
473
479
for arm in arms {
480
+ self . visit_pat ( arm. pat ) ;
474
481
if let Some ( Guard :: If ( guard) | Guard :: IfLet ( _, guard) ) = arm. guard {
475
482
self . visit_non_tail_expr ( guard) ;
476
483
}
@@ -496,7 +503,8 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
496
503
} ,
497
504
_ => {
498
505
self . allow_insert_closure &= !self . in_tail_pos ;
499
- self . allow_insert_closure &= can_move_expr_to_closure_no_visit ( self . cx , expr, & self . loops ) ;
506
+ self . allow_insert_closure &=
507
+ can_move_expr_to_closure_no_visit ( self . cx , expr, & self . loops , & self . locals ) ;
500
508
// Sub expressions are no longer in the tail position.
501
509
self . is_single_insert = false ;
502
510
self . in_tail_pos = false ;
@@ -505,6 +513,12 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
505
513
} ,
506
514
}
507
515
}
516
+
517
+ fn visit_pat ( & mut self , p : & ' tcx Pat < ' tcx > ) {
518
+ p. each_binding_or_first ( & mut |_, id, _, _| {
519
+ self . locals . insert ( id) ;
520
+ } ) ;
521
+ }
508
522
}
509
523
510
524
struct InsertSearchResults < ' tcx > {
@@ -630,6 +644,7 @@ fn find_insert_calls(
630
644
in_tail_pos : true ,
631
645
is_single_insert : true ,
632
646
loops : Vec :: new ( ) ,
647
+ locals : HirIdSet :: default ( ) ,
633
648
} ;
634
649
s. visit_expr ( expr) ;
635
650
let allow_insert_closure = s. allow_insert_closure ;
0 commit comments