]> git.lizzy.rs Git - rust.git/commitdiff
Fix suggestion for `async` in redundant_closure_call
authorAaron Christiansen <aaronc20000@gmail.com>
Sat, 25 Jun 2022 22:15:44 +0000 (23:15 +0100)
committerAaron Christiansen <aaronc20000@gmail.com>
Fri, 15 Jul 2022 14:49:04 +0000 (15:49 +0100)
Fix redundant_closure_call for single-expression async closures

Add Sugg::asyncify

Use Sugg for redundant_closure_call implementation

clippy_lints/src/redundant_closure_call.rs
clippy_utils/src/sugg.rs
tests/ui/redundant_closure_call_fixable.fixed
tests/ui/redundant_closure_call_fixable.rs
tests/ui/redundant_closure_call_fixable.stderr

index f5a93cebab8ca65707c1151a85346c34081a071c..74eea6de4bbeff43d30c92d83a8553c73d6cfab9 100644 (file)
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_ast::visit as ast_visit;
@@ -69,7 +69,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
         if_chain! {
             if let ast::ExprKind::Call(ref paren, _) = expr.kind;
             if let ast::ExprKind::Paren(ref closure) = paren.kind;
-            if let ast::ExprKind::Closure(_, _, _, _, ref decl, ref block, _) = closure.kind;
+            if let ast::ExprKind::Closure(_, _, ref r#async, _, ref decl, ref block, _) = closure.kind;
             then {
                 let mut visitor = ReturnVisitor::new();
                 visitor.visit_expr(block);
@@ -81,10 +81,19 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
                         "try not to call a closure in the expression where it is declared",
                         |diag| {
                             if decl.inputs.is_empty() {
-                                let mut app = Applicability::MachineApplicable;
-                                let hint =
-                                    snippet_with_applicability(cx, block.span, "..", &mut app).into_owned();
-                                diag.span_suggestion(expr.span, "try doing something like", hint, app);
+                                let app = Applicability::MachineApplicable;
+                                let mut hint = Sugg::ast(cx, block, "..");
+
+                                if r#async.is_async() {
+                                    // `async x` is a syntax error, so it becomes `async { x }`
+                                    if !matches!(block.kind, ast::ExprKind::Block(_, _)) {
+                                        hint = hint.blockify();
+                                    }
+
+                                    hint = hint.asyncify();
+                                }
+
+                                diag.span_suggestion(expr.span, "try doing something like", hint.to_string(), app);
                             }
                         },
                     );
index bad291dfc2513f6a0318437107dff89432b03e55..081c98e2f3ce726ccf9019a46fc4631eefde9a29 100644 (file)
@@ -315,6 +315,12 @@ pub fn blockify(self) -> Sugg<'static> {
         Sugg::NonParen(Cow::Owned(format!("{{ {} }}", self)))
     }
 
+    /// Convenience method to prefix the expression with the `async` keyword.
+    /// Can be used after `blockify` to create an async block.
+    pub fn asyncify(self) -> Sugg<'static> {
+        Sugg::NonParen(Cow::Owned(format!("async {}", self)))
+    }
+
     /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
     /// suggestion.
     pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> {
index 0abca6fca0613b4469c74af12206f25c7a0a1b41..7cd687c95a003f14c770fed009c8c4062359156b 100644 (file)
@@ -1,8 +1,28 @@
 // run-rustfix
 
+#![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(unused)]
 
+async fn something() -> u32 {
+    21
+}
+
+async fn something_else() -> u32 {
+    2
+}
+
 fn main() {
     let a = 42;
+    let b = async {
+        let x = something().await;
+        let y = something_else().await;
+        x * y
+    };
+    let c = {
+        let x = 21;
+        let y = 2;
+        x * y
+    };
+    let d = async { something().await };
 }
index f8b9d37a5cc4e757efe2960f1a1a804a62e839cd..37e4d2238641576fbff1184315d1264d2741f205 100644 (file)
@@ -1,8 +1,28 @@
 // run-rustfix
 
+#![feature(async_closure)]
 #![warn(clippy::redundant_closure_call)]
 #![allow(unused)]
 
+async fn something() -> u32 {
+    21
+}
+
+async fn something_else() -> u32 {
+    2
+}
+
 fn main() {
     let a = (|| 42)();
+    let b = (async || {
+        let x = something().await;
+        let y = something_else().await;
+        x * y
+    })();
+    let c = (|| {
+        let x = 21;
+        let y = 2;
+        x * y
+    })();
+    let d = (async || something().await)();
 }
index afd704ef12a934f913454334a42bd68c5a95a954..56a8e57c0c362097b74fb1b000b1438a1c62b097 100644 (file)
@@ -1,10 +1,56 @@
 error: try not to call a closure in the expression where it is declared
-  --> $DIR/redundant_closure_call_fixable.rs:7:13
+  --> $DIR/redundant_closure_call_fixable.rs:16:13
    |
 LL |     let a = (|| 42)();
    |             ^^^^^^^^^ help: try doing something like: `42`
    |
    = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
 
-error: aborting due to previous error
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:17:13
+   |
+LL |       let b = (async || {
+   |  _____________^
+LL | |         let x = something().await;
+LL | |         let y = something_else().await;
+LL | |         x * y
+LL | |     })();
+   | |________^
+   |
+help: try doing something like
+   |
+LL ~     let b = async {
+LL +         let x = something().await;
+LL +         let y = something_else().await;
+LL +         x * y
+LL ~     };
+   |
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:22:13
+   |
+LL |       let c = (|| {
+   |  _____________^
+LL | |         let x = 21;
+LL | |         let y = 2;
+LL | |         x * y
+LL | |     })();
+   | |________^
+   |
+help: try doing something like
+   |
+LL ~     let c = {
+LL +         let x = 21;
+LL +         let y = 2;
+LL +         x * y
+LL ~     };
+   |
+
+error: try not to call a closure in the expression where it is declared
+  --> $DIR/redundant_closure_call_fixable.rs:27:13
+   |
+LL |     let d = (async || something().await)();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }`
+
+error: aborting due to 4 previous errors