about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2016-09-12 22:11:05 -0700
committerEsteban Küber <esteban@kuber.com.ar>2016-10-22 11:37:22 -0700
commita449bdb20e5fd691f6d2445a6a58f5a089d60dc1 (patch)
tree39e023afe955138473b3882b5ff4143f52c6dbd1
parentb5f6d7ec2d4e231b9ef0c8a9e8e7ec8a7f67d2ae (diff)
downloadrust-a449bdb20e5fd691f6d2445a6a58f5a089d60dc1.tar.gz
rust-a449bdb20e5fd691f6d2445a6a58f5a089d60dc1.zip
Reword error when data-less enum variant called as function
Given a file like:

```rust
enum Test {
    Variant,
    Variant2 {a: u32},
}

fn main(){
    let x = Test::Variant("Hello");
    let y = Test::Variant2("World");
}
```

The errors now look this way:

```bash
error[E0423]: `Test::Variant2` is the name of a struct or struct variant, but this expression uses it like a function name
  --> file3.rs:10:13
   |
10 |     let y = Test::Variant2("Hello");
   |             ^^^^^^^^^^^^^^ struct called like a function
   |
   = help: did you mean to write: `Test::Variant2 { /* fields */ }`?

error: `Test::Variant` is being called, but it is not a function
 --> file3.rs:9:13
  |
9 |     let x = Test::Variant("World");
  |             ^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: did you mean to write: `Test::Variant`?
note: defined here
 --> file3.rs:2:5
  |
2 |     Variant,
  |     ^^^^^^^

error: aborting due to previous error
```
-rw-r--r--src/librustc_typeck/check/callee.rs32
-rw-r--r--src/test/compile-fail/empty-struct-unit-expr.rs8
2 files changed, 29 insertions, 11 deletions
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index c5a21d7dd91..ac67f75743e 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -13,6 +13,7 @@ use super::{DeferredCallResolution, Expectation, FnCtxt, TupleArgumentsFlag};
 use CrateCtxt;
 use hir::def::Def;
 use hir::def_id::{DefId, LOCAL_CRATE};
+use hir::print;
 use rustc::{infer, traits};
 use rustc::ty::{self, LvaluePreference, Ty};
 use syntax::parse::token;
@@ -194,15 +195,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let error_fn_sig;
 
         let fn_sig = match callee_ty.sty {
-            ty::TyFnDef(.., &ty::BareFnTy { ref sig, .. }) |
-            ty::TyFnPtr(&ty::BareFnTy { ref sig, .. }) => sig,
-            _ => {
-                let mut err = self.type_error_struct(call_expr.span,
-                                                     |actual| {
-                                                         format!("expected function, found `{}`",
-                                                                 actual)
-                                                     },
-                                                     callee_ty);
+            ty::TyFnDef(.., &ty::BareFnTy {ref sig, ..}) |
+            ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => sig,
+            ref t => {
+                let mut unit_variant = None;
+                if let &ty::TyAdt(adt_def, ..) = t {
+                    if adt_def.is_enum() {
+                        if let hir::ExprCall(ref expr, _) = call_expr.node {
+                            unit_variant = Some(print::expr_to_string(expr))
+                        }
+                    }
+                }
+                let mut err = if let Some(path) = unit_variant {
+                    let mut err = self.type_error_struct(call_expr.span, |_| {
+                        format!("`{}` is being called, but it is not a function", path)
+                    }, callee_ty);
+                    err.help(&format!("did you mean to write `{}`?", path));
+                    err
+                } else {
+                    self.type_error_struct(call_expr.span, |actual| {
+                        format!("expected function, found `{}`", actual)
+                    }, callee_ty)
+                };
 
                 if let hir::ExprCall(ref expr, _) = call_expr.node {
                     let tcx = self.tcx;
diff --git a/src/test/compile-fail/empty-struct-unit-expr.rs b/src/test/compile-fail/empty-struct-unit-expr.rs
index 350b96c764c..273ce91a7c5 100644
--- a/src/test/compile-fail/empty-struct-unit-expr.rs
+++ b/src/test/compile-fail/empty-struct-unit-expr.rs
@@ -23,7 +23,11 @@ enum E {
 
 fn main() {
     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
-    let e4 = E::Empty4(); //~ ERROR expected function, found `E`
+    let e4 = E::Empty4();
+    //~^ ERROR `E::Empty4` is being called, but it is not a function
+    //~| HELP did you mean to write `E::Empty4`?
     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
-    let xe4 = XE::XEmpty4(); //~ ERROR  expected function, found `empty_struct::XE`
+    let xe4 = XE::XEmpty4();
+    //~^ ERROR `XE::XEmpty4` is being called, but it is not a function
+    //~| HELP did you mean to write `XE::XEmpty4`?
 }