|
1 | 1 | use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
2 |
| -use clippy_utils::higher; |
3 | 2 | use clippy_utils::higher::VecArgs;
|
4 | 3 | use clippy_utils::source::snippet_opt;
|
5 | 4 | use clippy_utils::ty::{implements_trait, type_is_unsafe_function};
|
| 5 | +use clippy_utils::usage::UsedAfterExprVisitor; |
| 6 | +use clippy_utils::{get_enclosing_loop_or_closure, higher}; |
6 | 7 | use clippy_utils::{is_adjusted, iter_input_pats};
|
7 | 8 | use if_chain::if_chain;
|
8 | 9 | use rustc_errors::Applicability;
|
9 | 10 | use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath};
|
10 | 11 | use rustc_lint::{LateContext, LateLintPass, LintContext};
|
11 | 12 | use rustc_middle::lint::in_external_macro;
|
12 |
| -use rustc_middle::ty::{self, Ty}; |
| 13 | +use rustc_middle::ty::{self, ClosureKind, Ty}; |
13 | 14 | use rustc_session::{declare_lint_pass, declare_tool_lint};
|
14 | 15 |
|
15 | 16 | declare_clippy_lint! {
|
@@ -86,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
86 | 87 | }
|
87 | 88 | }
|
88 | 89 |
|
89 |
| -fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { |
| 90 | +fn check_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { |
90 | 91 | if let ExprKind::Closure(_, decl, eid, _, _) = expr.kind {
|
91 | 92 | let body = cx.tcx.hir().body(eid);
|
92 | 93 | let ex = &body.value;
|
@@ -131,7 +132,18 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
131 | 132 |
|
132 | 133 | then {
|
133 | 134 | span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
|
134 |
| - if let Some(snippet) = snippet_opt(cx, caller.span) { |
| 135 | + if let Some(mut snippet) = snippet_opt(cx, caller.span) { |
| 136 | + if_chain! { |
| 137 | + if let ty::Closure(_, substs) = fn_ty.kind(); |
| 138 | + if let ClosureKind::FnMut = substs.as_closure().kind(); |
| 139 | + if UsedAfterExprVisitor::is_found(cx, caller) |
| 140 | + || get_enclosing_loop_or_closure(cx.tcx, expr).is_some(); |
| 141 | + |
| 142 | + then { |
| 143 | + // Mutable closure is used after current expr; we cannot consume it. |
| 144 | + snippet = format!("&mut {}", snippet); |
| 145 | + } |
| 146 | + } |
135 | 147 | diag.span_suggestion(
|
136 | 148 | expr.span,
|
137 | 149 | "replace the closure with the function itself",
|
|
0 commit comments