]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/clippy/clippy_lints/src/entry.rs
Rollup merge of #89789 - jkugelman:must-use-thread-builder, r=joshtriplett
[rust.git] / src / tools / clippy / clippy_lints / src / entry.rs
index e1d0d65edb1b9c1daa1256c5db63c4c58a00bada..ac6824672f66cbf90c13b7f7d9e6dfab2d009d4d 100644 (file)
@@ -1,3 +1,4 @@
+use clippy_utils::higher;
 use clippy_utils::{
     can_move_expr_to_closure_no_visit,
     diagnostics::span_lint_and_sugg,
@@ -5,15 +6,16 @@
     source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context},
     SpanlessEq,
 };
+use core::fmt::Write;
 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};
 use rustc_span::{Span, SyntaxContext, DUMMY_SP};
-use std::fmt::Write;
 
 declare_clippy_lint! {
     /// ### What it does
 impl<'tcx> LateLintPass<'tcx> for HashMapPass {
     #[allow(clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        let (cond_expr, then_expr, else_expr) = match expr.kind {
-            ExprKind::If(c, t, e) => (c, t, e),
+        let (cond_expr, then_expr, else_expr) = match higher::If::hir(expr) {
+            Some(higher::If { cond, then, r#else }) => (cond, then, r#else),
             _ => return,
         };
+
         let (map_ty, contains_expr) = match try_parse_contains(cx, cond_expr) {
             Some(x) => x,
             None => return,
@@ -336,6 +339,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 +388,16 @@ fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
                 }
             },
             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 +479,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
                     // 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 +505,8 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
                 },
                 _ => {
                     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 +515,12 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
             },
         }
     }
+
+    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 +646,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;