diff options
| author | Jason Newcomb <jsnewcomb@pm.me> | 2021-08-01 18:39:56 -0400 |
|---|---|---|
| committer | Jason Newcomb <jsnewcomb@pm.me> | 2021-08-14 19:49:45 -0400 |
| commit | 4838c78ba4ef784379ae6ec5617479de2a32d3f6 (patch) | |
| tree | b5940a333778bd497fb48289c443f15b1132fb99 /clippy_lints | |
| parent | 7c5487dc62d569d4bc32cbe51951668406242137 (diff) | |
| download | rust-4838c78ba4ef784379ae6ec5617479de2a32d3f6.tar.gz rust-4838c78ba4ef784379ae6ec5617479de2a32d3f6.zip | |
Improve `manual_map` and `map_entry`
Locals which can be partially moved created within the to-be-created closure shouldn't block the use of a closure
Diffstat (limited to 'clippy_lints')
| -rw-r--r-- | clippy_lints/src/entry.rs | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index e1d0d65edb1..7fb8e427660 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -7,8 +7,9 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::{ + hir_id::HirIdSet, intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor}, - Block, Expr, ExprKind, Guard, HirId, Local, Stmt, StmtKind, UnOp, + Block, Expr, ExprKind, Guard, HirId, Pat, Stmt, StmtKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -336,6 +337,8 @@ struct InsertSearcher<'cx, 'tcx> { edits: Vec<Edit<'tcx>>, /// A stack of loops the visitor is currently in. loops: Vec<HirId>, + /// Local variables created in the expression. These don't need to be captured. + locals: HirIdSet, } impl<'tcx> InsertSearcher<'_, 'tcx> { /// 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> { } }, StmtKind::Expr(e) => self.visit_expr(e), - StmtKind::Local(Local { init: Some(e), .. }) => { - self.allow_insert_closure &= !self.in_tail_pos; - self.in_tail_pos = false; - self.is_single_insert = false; - self.visit_expr(e); + StmtKind::Local(l) => { + self.visit_pat(l.pat); + if let Some(e) = l.init { + self.allow_insert_closure &= !self.in_tail_pos; + self.in_tail_pos = false; + self.is_single_insert = false; + self.visit_expr(e); + } }, - _ => { + StmtKind::Item(_) => { self.allow_insert_closure &= !self.in_tail_pos; self.is_single_insert = false; }, @@ -471,6 +477,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { // Each branch may contain it's own insert expression. let mut is_map_used = self.is_map_used; for arm in arms { + self.visit_pat(arm.pat); if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard { self.visit_non_tail_expr(guard); } @@ -496,7 +503,8 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { }, _ => { self.allow_insert_closure &= !self.in_tail_pos; - self.allow_insert_closure &= can_move_expr_to_closure_no_visit(self.cx, expr, &self.loops); + self.allow_insert_closure &= + can_move_expr_to_closure_no_visit(self.cx, expr, &self.loops, &self.locals); // Sub expressions are no longer in the tail position. self.is_single_insert = false; self.in_tail_pos = false; @@ -505,6 +513,12 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { }, } } + + fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) { + p.each_binding_or_first(&mut |_, id, _, _| { + self.locals.insert(id); + }); + } } struct InsertSearchResults<'tcx> { @@ -630,6 +644,7 @@ fn find_insert_calls( in_tail_pos: true, is_single_insert: true, loops: Vec::new(), + locals: HirIdSet::default(), }; s.visit_expr(expr); let allow_insert_closure = s.allow_insert_closure; |
