]> git.lizzy.rs Git - rust.git/commitdiff
When encountetring `||{}()`, suggest the likely intended `(||{})()`
authorEsteban Küber <esteban@kuber.com.ar>
Sat, 9 Mar 2019 03:08:28 +0000 (19:08 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Sat, 9 Mar 2019 03:08:28 +0000 (19:08 -0800)
src/librustc_typeck/check/callee.rs
src/test/ui/suggestions/suggest-on-bare-closure-call.rs [new file with mode: 0644]
src/test/ui/suggestions/suggest-on-bare-closure-call.stderr [new file with mode: 0644]

index 0a4c0eb3aff72c1b25b5a34fb47dee71ec71c67f..15ae39600f6b4ea40bd99be809263ba7752a46c5 100644 (file)
@@ -2,7 +2,7 @@
 use super::method::MethodCallee;
 use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag};
 
-use errors::Applicability;
+use errors::{Applicability, DiagnosticBuilder};
 use hir::def::Def;
 use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@@ -232,6 +232,32 @@ fn try_overloaded_call_traits(
         None
     }
 
+    /// Give appropriate suggestion when encountering `||{/* not callable */}()`, where the
+    /// likely intention is to call the closure, suggest `(||{})()`. (#55851)
+    fn identify_bad_closure_def_and_call(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        hir_id: hir::HirId,
+        callee_node: &hir::ExprKind,
+        callee_span: Span,
+    ) {
+        let hir_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
+        let parent_node = self.tcx.hir().get_by_hir_id(hir_id);
+        if let (
+            hir::Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, _, _, sp, ..), .. }),
+            hir::ExprKind::Block(..),
+        ) = (parent_node, callee_node) {
+            let start = sp.shrink_to_lo();
+            let end = self.tcx.sess.source_map().next_point(callee_span);
+            err.multipart_suggestion(
+                "if you meant to create this closure and immediately call it, surround the \
+                closure with parenthesis",
+                vec![(start, "(".to_string()), (end, ")".to_string())],
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
     fn confirm_builtin_call(
         &self,
         call_expr: &hir::Expr,
@@ -268,6 +294,13 @@ fn confirm_builtin_call(
                         }
                     );
 
+                    self.identify_bad_closure_def_and_call(
+                        &mut err,
+                        call_expr.hir_id,
+                        &callee.node,
+                        callee.span,
+                    );
+
                     if let Some(ref path) = unit_variant {
                         err.span_suggestion(
                             call_expr.span,
diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.rs b/src/test/ui/suggestions/suggest-on-bare-closure-call.rs
new file mode 100644 (file)
index 0000000..355708c
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = ||{}();
+    //~^ ERROR expected function, found `()`
+}
diff --git a/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr b/src/test/ui/suggestions/suggest-on-bare-closure-call.stderr
new file mode 100644 (file)
index 0000000..17001e3
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0618]: expected function, found `()`
+  --> $DIR/suggest-on-bare-closure-call.rs:2:15
+   |
+LL |     let _ = ||{}();
+   |               ^^--
+   |               |
+   |               call expression requires function
+help: if you meant to create this closure and immediately call it, surround the closure with parenthesis
+   |
+LL |     let _ = (||{})();
+   |             ^    ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.