]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/eta_reduction.rs
ast/hir: Rename field-related structures
[rust.git] / clippy_lints / src / eta_reduction.rs
index 53df3abbf543744ef1300c6b80ddaef834a2afdb..c461732fd3693dc1301f3cdbbced43026adc862c 100644 (file)
@@ -10,6 +10,8 @@
     implements_trait, is_adjusted, iter_input_pats, snippet_opt, span_lint_and_sugg, span_lint_and_then,
     type_is_unsafe_function,
 };
+use clippy_utils::higher;
+use clippy_utils::higher::VecArgs;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for closures which just call another function where
@@ -22,7 +24,7 @@
     /// **Known problems:** If creating the closure inside the closure has a side-
     /// effect then moving the closure creation out will change when that side-
     /// effect runs.
-    /// See rust-lang/rust-clippy#1439 for more details.
+    /// See [#1439](https://github.com/rust-lang/rust-clippy/issues/1439) for more details.
     ///
     /// **Example:**
     /// ```rust,ignore
@@ -45,8 +47,9 @@
     ///
     /// **Why is this bad?** It's unnecessary to create the closure.
     ///
-    /// **Known problems:** rust-lang/rust-clippy#3071, rust-lang/rust-clippy#4002,
-    /// rust-lang/rust-clippy#3942
+    /// **Known problems:** [#3071](https://github.com/rust-lang/rust-clippy/issues/3071),
+    /// [#3942](https://github.com/rust-lang/rust-clippy/issues/3942),
+    /// [#4002](https://github.com/rust-lang/rust-clippy/issues/4002)
     ///
     ///
     /// **Example:**
@@ -73,7 +76,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)
+                    }
                 }
             },
             _ => (),
@@ -86,6 +92,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;
 
@@ -106,11 +129,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,
                         );
@@ -140,8 +163,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,
                 );