]> git.lizzy.rs Git - rust.git/commitdiff
redundant_closure_call - don't lint when used more than once
authorTim Nielens <tim.nielens@gmail.com>
Tue, 14 Jul 2020 18:27:25 +0000 (20:27 +0200)
committerTim Nielens <tim.nielens@gmail.com>
Sun, 19 Jul 2020 22:30:43 +0000 (00:30 +0200)
clippy_lints/src/misc_early.rs
tests/ui/redundant_closure_call.rs
tests/ui/redundant_closure_call.stderr

index b84a1a3fe249449a81a574ea2be25118976bbd7e..125df226ceb3793c3ea97d08ec7fc33e8598a64e 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
+use rustc_span::symbol::Ident;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for structure field patterns bound to wildcards.
@@ -493,6 +494,29 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
     }
 
     fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
+        fn count_closure_usage(block: &Block, ident: &Ident) -> usize {
+            struct ClosureUsageCount<'ast> {
+                ident: &'ast Ident,
+                count: usize,
+            };
+            impl<'ast> Visitor<'ast> for ClosureUsageCount<'ast> {
+                fn visit_expr(&mut self, expr: &'ast Expr) {
+                    if_chain! {
+                        if let ExprKind::Call(ref closure, _) = expr.kind;
+                        if let ExprKind::Path(_, ref path) = closure.kind;
+                        if self.ident == &path.segments[0].ident;
+                        then {
+                            self.count += 1;
+                        }
+                    }
+                    walk_expr(self, expr);
+                }
+            }
+            let mut closure_usage_count = ClosureUsageCount { ident, count: 0 };
+            closure_usage_count.visit_block(block);
+            closure_usage_count.count
+        }
+
         for w in block.stmts.windows(2) {
             if_chain! {
                 if let StmtKind::Local(ref local) = w[0].kind;
@@ -503,15 +527,15 @@ fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
                 if let ExprKind::Assign(_, ref call, _) = second.kind;
                 if let ExprKind::Call(ref closure, _) = call.kind;
                 if let ExprKind::Path(_, ref path) = closure.kind;
+                if ident == path.segments[0].ident;
+                if  count_closure_usage(block, &ident) == 1;
                 then {
-                    if ident == path.segments[0].ident {
-                        span_lint(
-                            cx,
-                            REDUNDANT_CLOSURE_CALL,
-                            second.span,
-                            "Closure called just once immediately after it was declared",
-                        );
-                    }
+                    span_lint(
+                        cx,
+                        REDUNDANT_CLOSURE_CALL,
+                        second.span,
+                        "Closure called just once immediately after it was declared",
+                    );
                 }
             }
         }
index bacd67db7c30571e1e12708e7ae4d911df272efe..0f2ba4a075dd58db9bc3adf0f90d7de148f15e53 100644 (file)
@@ -8,14 +8,21 @@ fn main() {
 
     k = (|a, b| a * b)(1, 5);
 
-    let closure = || 32;
-    i = closure();
-
+    // don't lint here, the closure is used more than once
     let closure = |i| i + 1;
     i = closure(3);
-
     i = closure(4);
 
+    // lint here
+    let redun_closure = || 1;
+    i = redun_closure();
+
+    // the lint is applicable here but the lint doesn't support redefinition
+    let redefined_closure = || 1;
+    i = redefined_closure();
+    let redefined_closure = || 2;
+    i = redefined_closure();
+
     #[allow(clippy::needless_return)]
     (|| return 2)();
     (|| -> Option<i32> { None? })();
index 68c1416bb6b1a33ff731f9fa9895116248011966..d5e0664319b86fdaa5a07f5f76ae6f24fe7fa628 100644 (file)
@@ -1,17 +1,11 @@
 error: Closure called just once immediately after it was declared
-  --> $DIR/redundant_closure_call.rs:12:5
+  --> $DIR/redundant_closure_call.rs:18:5
    |
-LL |     i = closure();
-   |     ^^^^^^^^^^^^^
+LL |     i = redun_closure();
+   |     ^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
 
-error: Closure called just once immediately after it was declared
-  --> $DIR/redundant_closure_call.rs:15:5
-   |
-LL |     i = closure(3);
-   |     ^^^^^^^^^^^^^^
-
 error: Try not to call a closure in the expression where it is declared.
   --> $DIR/redundant_closure_call.rs:7:17
    |
@@ -24,5 +18,5 @@ error: Try not to call a closure in the expression where it is declared.
 LL |     k = (|a, b| a * b)(1, 5);
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors