|  | 
| 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