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.
}
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;
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",
+ );
}
}
}
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? })();
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
|
LL | k = (|a, b| a * b)(1, 5);
| ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors