@@ -7,8 +7,9 @@ use clippy_utils::{
77} ;
88use rustc_errors:: Applicability ;
99use rustc_hir:: {
10+ hir_id:: HirIdSet ,
1011 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 ,
1213} ;
1314use rustc_lint:: { LateContext , LateLintPass } ;
1415use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
@@ -336,6 +337,8 @@ struct InsertSearcher<'cx, 'tcx> {
336337 edits : Vec < Edit < ' tcx > > ,
337338 /// A stack of loops the visitor is currently in.
338339 loops : Vec < HirId > ,
340+ /// Local variables created in the expression. These don't need to be captured.
341+ locals : HirIdSet ,
339342}
340343impl < ' tcx > InsertSearcher < ' _ , ' tcx > {
341344 /// 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> {
383386 }
384387 } ,
385388 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+ }
391397 } ,
392- _ => {
398+ StmtKind :: Item ( _ ) => {
393399 self . allow_insert_closure &= !self . in_tail_pos ;
394400 self . is_single_insert = false ;
395401 } ,
@@ -471,6 +477,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
471477 // Each branch may contain it's own insert expression.
472478 let mut is_map_used = self . is_map_used ;
473479 for arm in arms {
480+ self . visit_pat ( arm. pat ) ;
474481 if let Some ( Guard :: If ( guard) | Guard :: IfLet ( _, guard) ) = arm. guard {
475482 self . visit_non_tail_expr ( guard) ;
476483 }
@@ -496,7 +503,8 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
496503 } ,
497504 _ => {
498505 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 ) ;
500508 // Sub expressions are no longer in the tail position.
501509 self . is_single_insert = false ;
502510 self . in_tail_pos = false ;
@@ -505,6 +513,12 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
505513 } ,
506514 }
507515 }
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+ }
508522}
509523
510524struct InsertSearchResults < ' tcx > {
@@ -630,6 +644,7 @@ fn find_insert_calls(
630644 in_tail_pos : true ,
631645 is_single_insert : true ,
632646 loops : Vec :: new ( ) ,
647+ locals : HirIdSet :: default ( ) ,
633648 } ;
634649 s. visit_expr ( expr) ;
635650 let allow_insert_closure = s. allow_insert_closure ;
0 commit comments