Skip to content

Commit c720d82

Browse files
committed
redundant_closure_call - don't lint when used more than once
1 parent 8cf4219 commit c720d82

File tree

3 files changed

+47
-22
lines changed

3 files changed

+47
-22
lines changed

clippy_lints/src/misc_early.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
1414
use rustc_middle::lint::in_external_macro;
1515
use rustc_session::{declare_lint_pass, declare_tool_lint};
1616
use rustc_span::source_map::Span;
17+
use rustc_span::symbol::Ident;
1718

1819
declare_clippy_lint! {
1920
/// **What it does:** Checks for structure field patterns bound to wildcards.
@@ -493,6 +494,29 @@ impl EarlyLintPass for MiscEarlyLints {
493494
}
494495

495496
fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
497+
fn count_closure_usage(block: &Block, ident: &Ident) -> usize {
498+
struct ClosureUsageCount<'ast> {
499+
ident: &'ast Ident,
500+
count: usize,
501+
};
502+
impl<'ast> Visitor<'ast> for ClosureUsageCount<'ast> {
503+
fn visit_expr(&mut self, expr: &'ast Expr) {
504+
if_chain! {
505+
if let ExprKind::Call(ref closure, _) = expr.kind;
506+
if let ExprKind::Path(_, ref path) = closure.kind;
507+
if self.ident == &path.segments[0].ident;
508+
then {
509+
self.count += 1;
510+
}
511+
}
512+
walk_expr(self, expr);
513+
}
514+
}
515+
let mut closure_usage_count = ClosureUsageCount { ident, count: 0 };
516+
closure_usage_count.visit_block(block);
517+
closure_usage_count.count
518+
}
519+
496520
for w in block.stmts.windows(2) {
497521
if_chain! {
498522
if let StmtKind::Local(ref local) = w[0].kind;
@@ -503,15 +527,15 @@ impl EarlyLintPass for MiscEarlyLints {
503527
if let ExprKind::Assign(_, ref call, _) = second.kind;
504528
if let ExprKind::Call(ref closure, _) = call.kind;
505529
if let ExprKind::Path(_, ref path) = closure.kind;
530+
if ident == path.segments[0].ident;
531+
if count_closure_usage(block, &ident) == 1;
506532
then {
507-
if ident == path.segments[0].ident {
508-
span_lint(
509-
cx,
510-
REDUNDANT_CLOSURE_CALL,
511-
second.span,
512-
"Closure called just once immediately after it was declared",
513-
);
514-
}
533+
span_lint(
534+
cx,
535+
REDUNDANT_CLOSURE_CALL,
536+
second.span,
537+
"Closure called just once immediately after it was declared",
538+
);
515539
}
516540
}
517541
}

tests/ui/redundant_closure_call.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,21 @@ fn main() {
88

99
k = (|a, b| a * b)(1, 5);
1010

11-
let closure = || 32;
12-
i = closure();
13-
11+
// don't lint here, the closure is used more than once
1412
let closure = |i| i + 1;
1513
i = closure(3);
16-
1714
i = closure(4);
1815

16+
// lint here
17+
let redun_closure = || 1;
18+
i = redun_closure();
19+
20+
// the lint is applicable here but the lint doesn't support redefinition
21+
let redefined_closure = || 1;
22+
i = redefined_closure();
23+
let redefined_closure = || 2;
24+
i = redefined_closure();
25+
1926
#[allow(clippy::needless_return)]
2027
(|| return 2)();
2128
(|| -> Option<i32> { None? })();
Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
error: Closure called just once immediately after it was declared
2-
--> $DIR/redundant_closure_call.rs:12:5
2+
--> $DIR/redundant_closure_call.rs:18:5
33
|
4-
LL | i = closure();
5-
| ^^^^^^^^^^^^^
4+
LL | i = redun_closure();
5+
| ^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `-D clippy::redundant-closure-call` implied by `-D warnings`
88

9-
error: Closure called just once immediately after it was declared
10-
--> $DIR/redundant_closure_call.rs:15:5
11-
|
12-
LL | i = closure(3);
13-
| ^^^^^^^^^^^^^^
14-
159
error: Try not to call a closure in the expression where it is declared.
1610
--> $DIR/redundant_closure_call.rs:7:17
1711
|
@@ -24,5 +18,5 @@ error: Try not to call a closure in the expression where it is declared.
2418
LL | k = (|a, b| a * b)(1, 5);
2519
| ^^^^^^^^^^^^^^^^^^^^
2620

27-
error: aborting due to 4 previous errors
21+
error: aborting due to 3 previous errors
2822

0 commit comments

Comments
 (0)