Auto merge of #36520 - estebank:dataless-enum, r=brson

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");
}
```

Both errors now look similar:

``` 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 the name of a data-less enum, but this expression uses it like a function name
 --> file3.rs:9:13
  |
9 |     let x = Test::Variant("World");
  |             ^^^^^^^^^^^^^^^^^^^^^^ data-less enum called like a function
  |
  = help: did you mean to write: `Test::Variant`?
note: defined here
 --> file3.rs:2:5
  |
2 |     Variant,
  |     ^^^^^^^

error: aborting due to previous error
```

Re: #28533
This commit is contained in:
bors 2016-11-09 08:51:23 -08:00 committed by GitHub
commit bca365e688
2 changed files with 29 additions and 11 deletions

View File

@ -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;

View File

@ -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`?
}