about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/check/callee.rs95
-rw-r--r--src/test/ui/block-result/issue-20862.stderr12
-rw-r--r--src/test/ui/empty/empty-struct-unit-expr.stderr16
-rw-r--r--src/test/ui/error-codes/E0618.stderr8
-rw-r--r--src/test/ui/issues/issue-10969.stderr8
-rw-r--r--src/test/ui/issues/issue-18532.stderr4
-rw-r--r--src/test/ui/issues/issue-20714.stderr4
-rw-r--r--src/test/ui/issues/issue-21701.stderr8
-rw-r--r--src/test/ui/issues/issue-22468.stderr4
-rw-r--r--src/test/ui/issues/issue-26237.rs3
-rw-r--r--src/test/ui/issues/issue-26237.stderr6
-rw-r--r--src/test/ui/issues/issue-45965.stderr4
-rw-r--r--src/test/ui/issues/issue-46771.stderr4
-rw-r--r--src/test/ui/issues/issue-5100.stderr4
-rw-r--r--src/test/ui/parse-error-correct.stderr4
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr12
-rw-r--r--src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs8
-rw-r--r--src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr16
18 files changed, 160 insertions, 60 deletions
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index de4293aaaea..9b78351c3e1 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -218,35 +218,62 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     }
                 }
 
-                let mut err = type_error_struct!(
-                    self.tcx.sess,
-                    call_expr.span,
-                    callee_ty,
-                    E0618,
-                    "expected function, found {}",
-                    match unit_variant {
-                        Some(ref path) => format!("enum variant `{}`", path),
-                        None => format!("`{}`", callee_ty),
-                    });
-
-                err.span_label(call_expr.span, "not a function");
+                if let hir::ExprKind::Call(ref callee, _) = call_expr.node {
+                    let mut err = type_error_struct!(
+                        self.tcx.sess,
+                        callee.span,
+                        callee_ty,
+                        E0618,
+                        "expected function, found {}",
+                        match unit_variant {
+                            Some(ref path) => format!("enum variant `{}`", path),
+                            None => format!("`{}`", callee_ty),
+                        });
 
-                if let Some(ref path) = unit_variant {
-                    err.span_suggestion_with_applicability(
-                        call_expr.span,
-                        &format!("`{}` is a unit variant, you need to write it \
-                                  without the parenthesis", path),
-                        path.to_string(),
-                        Applicability::MachineApplicable
-                    );
-                }
+                    if let Some(ref path) = unit_variant {
+                        err.span_suggestion_with_applicability(
+                            call_expr.span,
+                            &format!("`{}` is a unit variant, you need to write it \
+                                      without the parenthesis", path),
+                            path.to_string(),
+                            Applicability::MachineApplicable
+                        );
+                    }
 
-                if let hir::ExprKind::Call(ref expr, _) = call_expr.node {
-                    let def = if let hir::ExprKind::Path(ref qpath) = expr.node {
-                        self.tables.borrow().qpath_def(qpath, expr.hir_id)
-                    } else {
-                        Def::Err
+                    let mut inner_callee_path = None;
+                    let def = match callee.node {
+                        hir::ExprKind::Path(ref qpath) => {
+                            self.tables.borrow().qpath_def(qpath, callee.hir_id)
+                        },
+                        hir::ExprKind::Call(ref inner_callee, _) => {
+                            // If the call spans more than one line and the callee kind is
+                            // itself another `ExprCall`, that's a clue that we might just be
+                            // missing a semicolon (Issue #51055)
+                            let call_is_multiline = self.tcx.sess.source_map()
+                                .is_multiline(call_expr.span);
+                            if call_is_multiline {
+                                let span = self.tcx.sess.source_map().next_point(callee.span);
+                                err.span_suggestion_with_applicability(
+                                    span,
+                                    "try adding a semicolon",
+                                    ";".to_owned(),
+                                    Applicability::MaybeIncorrect
+                                );
+                            }
+                            if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.node {
+                                inner_callee_path = Some(inner_qpath);
+                                self.tables.borrow().qpath_def(inner_qpath, inner_callee.hir_id)
+                            } else {
+                                Def::Err
+                            }
+                        },
+                        _ => {
+                            Def::Err
+                        }
                     };
+
+                    err.span_label(call_expr.span, "call expression requires function");
+
                     let def_span = match def {
                         Def::Err => None,
                         Def::Local(id) | Def::Upvar(id, ..) => {
@@ -255,16 +282,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         _ => self.tcx.hir.span_if_local(def.def_id())
                     };
                     if let Some(span) = def_span {
-                        let name = match unit_variant {
-                            Some(path) => path,
-                            None => callee_ty.to_string(),
+                        let label = match (unit_variant, inner_callee_path) {
+                            (Some(path), _) => format!("`{}` defined here", path),
+                            (_, Some(hir::QPath::Resolved(_, path))) => format!(
+                                "`{}` defined here returns `{}`", path, callee_ty.to_string()
+                            ),
+                            _ => format!("`{}` defined here", callee_ty.to_string()),
                         };
-                        err.span_label(span, format!("`{}` defined here", name));
+                        err.span_label(span, label);
                     }
+                    err.emit();
+                } else {
+                    bug!("call_expr.node should be an ExprKind::Call, got {:?}", call_expr.node);
                 }
 
-                err.emit();
-
                 // This is the "default" function signature, used in case of error.
                 // In that case, we check each argument against "error" in order to
                 // set up all the node type bindings.
diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr
index 990fb404c94..194cfab8527 100644
--- a/src/test/ui/block-result/issue-20862.stderr
+++ b/src/test/ui/block-result/issue-20862.stderr
@@ -12,8 +12,16 @@ LL |     |y| x + y
 error[E0618]: expected function, found `()`
   --> $DIR/issue-20862.rs:17:13
    |
-LL |     let x = foo(5)(2);
-   |             ^^^^^^^^^ not a function
+LL | / fn foo(x: i32) {
+LL | |     |y| x + y
+LL | | //~^ ERROR: mismatched types
+LL | | }
+   | |_- `foo` defined here returns `()`
+...
+LL |       let x = foo(5)(2);
+   |               ^^^^^^---
+   |               |
+   |               call expression requires function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/empty/empty-struct-unit-expr.stderr b/src/test/ui/empty/empty-struct-unit-expr.stderr
index fff696fc80f..360e0c6f107 100644
--- a/src/test/ui/empty/empty-struct-unit-expr.stderr
+++ b/src/test/ui/empty/empty-struct-unit-expr.stderr
@@ -5,7 +5,9 @@ LL | struct Empty2;
    | -------------- `Empty2` defined here
 ...
 LL |     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
-   |              ^^^^^^^^ not a function
+   |              ^^^^^^--
+   |              |
+   |              call expression requires function
 
 error[E0618]: expected function, found enum variant `E::Empty4`
   --> $DIR/empty-struct-unit-expr.rs:26:14
@@ -14,7 +16,9 @@ LL |     Empty4
    |     ------ `E::Empty4` defined here
 ...
 LL |     let e4 = E::Empty4();
-   |              ^^^^^^^^^^^ not a function
+   |              ^^^^^^^^^--
+   |              |
+   |              call expression requires function
 help: `E::Empty4` is a unit variant, you need to write it without the parenthesis
    |
 LL |     let e4 = E::Empty4;
@@ -24,13 +28,17 @@ error[E0618]: expected function, found `empty_struct::XEmpty2`
   --> $DIR/empty-struct-unit-expr.rs:28:15
    |
 LL |     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
-   |               ^^^^^^^^^ not a function
+   |               ^^^^^^^--
+   |               |
+   |               call expression requires function
 
 error[E0618]: expected function, found enum variant `XE::XEmpty4`
   --> $DIR/empty-struct-unit-expr.rs:29:15
    |
 LL |     let xe4 = XE::XEmpty4();
-   |               ^^^^^^^^^^^^^ not a function
+   |               ^^^^^^^^^^^--
+   |               |
+   |               call expression requires function
 help: `XE::XEmpty4` is a unit variant, you need to write it without the parenthesis
    |
 LL |     let xe4 = XE::XEmpty4;
diff --git a/src/test/ui/error-codes/E0618.stderr b/src/test/ui/error-codes/E0618.stderr
index ef7ace44d59..3bcc83e01c1 100644
--- a/src/test/ui/error-codes/E0618.stderr
+++ b/src/test/ui/error-codes/E0618.stderr
@@ -5,7 +5,9 @@ LL |     Entry,
    |     ----- `X::Entry` defined here
 ...
 LL |     X::Entry();
-   |     ^^^^^^^^^^ not a function
+   |     ^^^^^^^^--
+   |     |
+   |     call expression requires function
 help: `X::Entry` is a unit variant, you need to write it without the parenthesis
    |
 LL |     X::Entry;
@@ -17,7 +19,9 @@ error[E0618]: expected function, found `i32`
 LL |     let x = 0i32;
    |         - `i32` defined here
 LL |     x();
-   |     ^^^ not a function
+   |     ^--
+   |     |
+   |     call expression requires function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-10969.stderr b/src/test/ui/issues/issue-10969.stderr
index edc4ecbab52..d04108ca39e 100644
--- a/src/test/ui/issues/issue-10969.stderr
+++ b/src/test/ui/issues/issue-10969.stderr
@@ -4,7 +4,9 @@ error[E0618]: expected function, found `i32`
 LL | fn func(i: i32) {
    |         - `i32` defined here
 LL |     i(); //~ERROR expected function, found `i32`
-   |     ^^^ not a function
+   |     ^--
+   |     |
+   |     call expression requires function
 
 error[E0618]: expected function, found `i32`
   --> $DIR/issue-10969.rs:16:5
@@ -12,7 +14,9 @@ error[E0618]: expected function, found `i32`
 LL |     let i = 0i32;
    |         - `i32` defined here
 LL |     i(); //~ERROR expected function, found `i32`
-   |     ^^^ not a function
+   |     ^--
+   |     |
+   |     call expression requires function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-18532.stderr b/src/test/ui/issues/issue-18532.stderr
index 8f10cb0f7b0..c297c20069e 100644
--- a/src/test/ui/issues/issue-18532.stderr
+++ b/src/test/ui/issues/issue-18532.stderr
@@ -2,7 +2,9 @@ error[E0618]: expected function, found `!`
   --> $DIR/issue-18532.rs:16:5
    |
 LL |     (return)((),()); //~ ERROR expected function, found `!`
-   |     ^^^^^^^^^^^^^^^ not a function
+   |     ^^^^^^^^-------
+   |     |
+   |     call expression requires function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20714.stderr b/src/test/ui/issues/issue-20714.stderr
index 1ea85ee440e..70a9736d2a2 100644
--- a/src/test/ui/issues/issue-20714.stderr
+++ b/src/test/ui/issues/issue-20714.stderr
@@ -5,7 +5,9 @@ LL | struct G;
    | --------- `G` defined here
 ...
 LL |     let g = G(); //~ ERROR: expected function, found `G`
-   |             ^^^ not a function
+   |             ^--
+   |             |
+   |             call expression requires function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-21701.stderr b/src/test/ui/issues/issue-21701.stderr
index 9fb9a7b51f2..b94e0833a58 100644
--- a/src/test/ui/issues/issue-21701.stderr
+++ b/src/test/ui/issues/issue-21701.stderr
@@ -4,7 +4,9 @@ error[E0618]: expected function, found `U`
 LL | fn foo<U>(t: U) {
    |           - `U` defined here
 LL |     let y = t();
-   |             ^^^ not a function
+   |             ^--
+   |             |
+   |             call expression requires function
 
 error[E0618]: expected function, found `Bar`
   --> $DIR/issue-21701.rs:19:13
@@ -13,7 +15,9 @@ LL | struct Bar;
    | ----------- `Bar` defined here
 ...
 LL |     let f = Bar();
-   |             ^^^^^ not a function
+   |             ^^^--
+   |             |
+   |             call expression requires function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-22468.stderr b/src/test/ui/issues/issue-22468.stderr
index 034a076fbfe..af32c0e20ce 100644
--- a/src/test/ui/issues/issue-22468.stderr
+++ b/src/test/ui/issues/issue-22468.stderr
@@ -4,7 +4,9 @@ error[E0618]: expected function, found `&str`
 LL |     let foo = "bar";
    |         --- `&str` defined here
 LL |     let x = foo("baz");
-   |             ^^^^^^^^^^ not a function
+   |             ^^^-------
+   |             |
+   |             call expression requires function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-26237.rs b/src/test/ui/issues/issue-26237.rs
index 22772e596b1..ffffe6d3ab5 100644
--- a/src/test/ui/issues/issue-26237.rs
+++ b/src/test/ui/issues/issue-26237.rs
@@ -11,7 +11,6 @@
 macro_rules! macro_panic {
     ($not_a_function:expr, $some_argument:ident) => {
         $not_a_function($some_argument)
-        //~^ ERROR expected function, found `{integer}`
     }
 }
 
@@ -19,5 +18,5 @@ fn main() {
     let mut value_a = 0;
     let mut value_b = 0;
     macro_panic!(value_a, value_b);
-    //~^ in this expansion of macro_panic!
+    //~^ ERROR expected function, found `{integer}`
 }
diff --git a/src/test/ui/issues/issue-26237.stderr b/src/test/ui/issues/issue-26237.stderr
index ae6fda8b932..7f481c230ba 100644
--- a/src/test/ui/issues/issue-26237.stderr
+++ b/src/test/ui/issues/issue-26237.stderr
@@ -1,14 +1,14 @@
 error[E0618]: expected function, found `{integer}`
-  --> $DIR/issue-26237.rs:13:9
+  --> $DIR/issue-26237.rs:20:18
    |
 LL |         $not_a_function($some_argument)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a function
+   |         ------------------------------- call expression requires function
 ...
 LL |     let mut value_a = 0;
    |         ----------- `{integer}` defined here
 LL |     let mut value_b = 0;
 LL |     macro_panic!(value_a, value_b);
-   |     ------------------------------- in this macro invocation
+   |                  ^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-45965.stderr b/src/test/ui/issues/issue-45965.stderr
index 2b3870feef3..b7b5f76395a 100644
--- a/src/test/ui/issues/issue-45965.stderr
+++ b/src/test/ui/issues/issue-45965.stderr
@@ -2,7 +2,9 @@ error[E0618]: expected function, found `{float}`
   --> $DIR/issue-45965.rs:12:30
    |
 LL |     let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 };
-   |                              ^^^^^^^^^^^^^ not a function
+   |                              ^^^----------
+   |                              |
+   |                              call expression requires function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-46771.stderr b/src/test/ui/issues/issue-46771.stderr
index 0d57d61e9ff..90adb3ed73f 100644
--- a/src/test/ui/issues/issue-46771.stderr
+++ b/src/test/ui/issues/issue-46771.stderr
@@ -4,7 +4,9 @@ error[E0618]: expected function, found `main::Foo`
 LL |     struct Foo;
    |     ----------- `main::Foo` defined here
 LL |     (1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `main::Foo`
-   |                       ^^^^^^ not a function
+   |                       ^^^---
+   |                       |
+   |                       call expression requires function
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr
index 6f5a84966bf..305ee2f5471 100644
--- a/src/test/ui/issues/issue-5100.stderr
+++ b/src/test/ui/issues/issue-5100.stderr
@@ -47,9 +47,9 @@ error[E0618]: expected function, found `(char, char)`
   --> $DIR/issue-5100.rs:58:14
    |
 LL |       let v = [('a', 'b')   //~ ERROR expected function, found `(char, char)`
-   |  ______________^
+   |  ______________-^^^^^^^^^
 LL | |              ('c', 'd'),
-   | |_______________________^ not a function
+   | |_______________________- call expression requires function
 
 error[E0308]: mismatched types
   --> $DIR/issue-5100.rs:65:19
diff --git a/src/test/ui/parse-error-correct.stderr b/src/test/ui/parse-error-correct.stderr
index 3eb0b19a6aa..9c87806da9e 100644
--- a/src/test/ui/parse-error-correct.stderr
+++ b/src/test/ui/parse-error-correct.stderr
@@ -17,7 +17,9 @@ LL |     let y = 42;
    |         - `{integer}` defined here
 LL |     let x = y.;  //~ ERROR unexpected token
 LL |     let x = y.();  //~ ERROR unexpected token
-   |             ^^^^ not a function
+   |             ^---
+   |             |
+   |             call expression requires function
 
 error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
   --> $DIR/parse-error-correct.rs:21:15
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 8e08f124d68..01e6488de53 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -171,7 +171,9 @@ LL |             Unit,
    |             ---- `Z::Unit` defined here
 ...
 LL |         let _ = Z::Unit();
-   |                 ^^^^^^^^^ not a function
+   |                 ^^^^^^^--
+   |                 |
+   |                 call expression requires function
 help: `Z::Unit` is a unit variant, you need to write it without the parenthesis
    |
 LL |         let _ = Z::Unit;
@@ -193,7 +195,9 @@ LL |         Unit,
    |         ---- `m::E::Unit` defined here
 ...
 LL |     let _: E = m::E::Unit();
-   |                ^^^^^^^^^^^^ not a function
+   |                ^^^^^^^^^^--
+   |                |
+   |                call expression requires function
 help: `m::E::Unit` is a unit variant, you need to write it without the parenthesis
    |
 LL |     let _: E = m::E::Unit;
@@ -215,7 +219,9 @@ LL |         Unit,
    |         ---- `E::Unit` defined here
 ...
 LL |     let _: E = E::Unit();
-   |                ^^^^^^^^^ not a function
+   |                ^^^^^^^--
+   |                |
+   |                call expression requires function
 help: `E::Unit` is a unit variant, you need to write it without the parenthesis
    |
 LL |     let _: E = E::Unit;
diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs
new file mode 100644
index 00000000000..37f078285d6
--- /dev/null
+++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs
@@ -0,0 +1,8 @@
+fn vindictive() -> bool { true }
+
+fn perfidy() -> (i32, i32) {
+    vindictive() //~ ERROR expected function, found `bool`
+    (1, 2)
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
new file mode 100644
index 00000000000..40ddb5ec53c
--- /dev/null
+++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
@@ -0,0 +1,16 @@
+error[E0618]: expected function, found `bool`
+  --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:4:5
+   |
+LL |   fn vindictive() -> bool { true }
+   |   -------------------------------- `vindictive` defined here returns `bool`
+...
+LL |       vindictive() //~ ERROR expected function, found `bool`
+   |       -^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |  _____|
+   | |
+LL | |     (1, 2)
+   | |__________- call expression requires function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.