X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=clippy_lints%2Fsrc%2Feta_reduction.rs;h=99253555a95e36659b14d1caa114d587e20e17bb;hb=9f6b5de7deaf4dc9e7917370ad09ab85dc23997c;hp=1a722d39f730bb1cb293920cd610fbe9b8f329b7;hpb=488153ff2ff678051f06a94dc4486632d788c328;p=rust.git diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 1a722d39f73..99253555a95 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,3 +1,9 @@ +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::higher; +use clippy_utils::higher::VecArgs; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::{implements_trait, type_is_unsafe_function}; +use clippy_utils::{is_adjusted, iter_input_pats}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath}; @@ -6,11 +12,6 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::{ - implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_sugg, span_lint_and_then, - type_is_unsafe_function, -}; - declare_clippy_lint! { /// **What it does:** Checks for closures which just call another function where /// the function can be called directly. `unsafe` functions or calls where types @@ -74,7 +75,10 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { match expr.kind { ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => { for arg in args { - check_closure(cx, arg) + // skip `foo(macro!())` + if arg.span.ctxt() == expr.span.ctxt() { + check_closure(cx, arg) + } } }, _ => (), @@ -87,6 +91,23 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { let body = cx.tcx.hir().body(eid); let ex = &body.value; + if ex.span.ctxt() != expr.span.ctxt() { + if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) { + // replace `|| vec![]` with `Vec::new` + span_lint_and_sugg( + cx, + REDUNDANT_CLOSURE, + expr.span, + "redundant closure", + "replace the closure with `Vec::new`", + "std::vec::Vec::new".into(), + Applicability::MachineApplicable, + ); + } + // skip `foo(|| macro!())` + return; + } + if_chain!( if let ExprKind::Call(ref caller, ref args) = ex.kind; @@ -107,11 +128,11 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { if compare_inputs(&mut iter_input_pats(decl, body), &mut args.iter()); then { - span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |diag| { + span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { if let Some(snippet) = snippet_opt(cx, caller.span) { diag.span_suggestion( expr.span, - "remove closure as shown", + "replace the closure with the function itself", snippet, Applicability::MachineApplicable, ); @@ -141,8 +162,8 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) { cx, REDUNDANT_CLOSURE_FOR_METHOD_CALLS, expr.span, - "redundant closure found", - "remove closure as shown", + "redundant closure", + "replace the closure with the method itself", format!("{}::{}", name, path.ident.name), Applicability::MachineApplicable, );