Skip to content

Commit

Permalink
improve unknown enum variant errors
Browse files Browse the repository at this point in the history
  • Loading branch information
euclio committed Apr 9, 2019
1 parent 3750348 commit 757ef38
Show file tree
Hide file tree
Showing 24 changed files with 216 additions and 99 deletions.
21 changes: 13 additions & 8 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -1362,27 +1362,32 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
let msg = format!("expected type, found variant `{}`", assoc_ident);
tcx.sess.span_err(span, &msg);
} else if qself_ty.is_enum() {
// Report as incorrect enum variant rather than ambiguous type.
let mut err = tcx.sess.struct_span_err(
span,
&format!("no variant `{}` on enum `{}`", &assoc_ident.as_str(), qself_ty),
assoc_ident.span,
&format!("no variant `{}` in enum `{}`", assoc_ident, qself_ty),
);
// Check if it was a typo.

let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
if let Some(suggested_name) = find_best_match_for_name(
adt_def.variants.iter().map(|variant| &variant.ident.name),
&assoc_ident.as_str(),
None,
) {
err.span_suggestion(
span,
"did you mean",
format!("{}::{}", qself_ty, suggested_name),
assoc_ident.span,
"there is a variant with a similar name",
suggested_name.to_string(),
Applicability::MaybeIncorrect,
);
} else {
err.span_label(span, "unknown variant");
err.span_label(span, format!("variant not found in `{}`", qself_ty));
}

if let Some(sp) = tcx.hir().span_if_local(adt_def.did) {
let sp = tcx.sess.source_map().def_span(sp);
err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
}

err.emit();
} else if !qself_ty.references_error() {
// Don't print `TyErr` to the user.
Expand Down
51 changes: 28 additions & 23 deletions src/librustc_typeck/check/method/suggest.rs
Expand Up @@ -14,11 +14,11 @@ use rustc::hir::map as hir_map;
use rustc::hir::print;
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::traits::Obligation;
use rustc::ty::{self, Adt, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
use rustc::ty::{self, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable};
use rustc::ty::print::with_crate_prefix;
use syntax_pos::{Span, FileName};
use syntax::ast;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax::util::lev_distance;

use std::cmp::Ordering;

Expand Down Expand Up @@ -188,17 +188,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let actual = self.resolve_type_vars_if_possible(&rcvr_ty);
let ty_str = self.ty_to_string(actual);
let is_method = mode == Mode::MethodCall;
let mut suggestion = None;
let item_kind = if is_method {
"method"
} else if actual.is_enum() {
if let Adt(ref adt_def, _) = actual.sty {
let names = adt_def.variants.iter().map(|s| &s.ident.name);
suggestion = find_best_match_for_name(names,
&item_name.as_str(),
None);
}
"variant"
"variant or associated item"
} else {
match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
(Some(name), false) if name.is_lowercase() => {
Expand Down Expand Up @@ -299,25 +292,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return;
} else {
span = item_name.span;
let mut err = struct_span_err!(
struct_span_err!(
tcx.sess,
span,
E0599,
"no {} named `{}` found for type `{}` in the current scope",
item_kind,
item_name,
ty_str
);
if let Some(suggestion) = suggestion {
// enum variant
err.span_suggestion(
span,
"did you mean",
suggestion.to_string(),
Applicability::MaybeIncorrect,
);
}
err
)
}
} else {
tcx.sess.diagnostic().struct_dummy()
Expand Down Expand Up @@ -469,14 +452,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
out_of_scope_traits);
}

if actual.is_enum() {
let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
if let Some(suggestion) = lev_distance::find_best_match_for_name(
adt_def.variants.iter().map(|s| &s.ident.name),
&item_name.as_str(),
None,
) {
err.span_suggestion(
span,
"there is a variant with a similar name",
suggestion.to_string(),
Applicability::MaybeIncorrect,
);
}
}

if let Some(lev_candidate) = lev_candidate {
let def = lev_candidate.def();
err.span_suggestion(
span,
"did you mean",
&format!(
"there is {} {} with a similar name",
def.article(),
def.kind_name(),
),
lev_candidate.ident.to_string(),
Applicability::MaybeIncorrect,
);
}

err.emit();
}

Expand Down
20 changes: 20 additions & 0 deletions src/test/ui/associated-item/associated-item-enum.rs
@@ -0,0 +1,20 @@
enum Enum { Variant }

impl Enum {
const MISSPELLABLE: i32 = 0;
fn misspellable() {}
}

trait Trait {
fn misspellable_trait() {}
}

impl Trait for Enum {
fn misspellable_trait() {}
}

fn main() {
Enum::mispellable(); //~ ERROR no variant or associated item
Enum::mispellable_trait(); //~ ERROR no variant or associated item
Enum::MISPELLABLE; //~ ERROR no variant or associated item
}
36 changes: 36 additions & 0 deletions src/test/ui/associated-item/associated-item-enum.stderr
@@ -0,0 +1,36 @@
error[E0599]: no variant or associated item named `mispellable` found for type `Enum` in the current scope
--> $DIR/associated-item-enum.rs:17:11
|
LL | enum Enum { Variant }
| --------- variant or associated item `mispellable` not found here
...
LL | Enum::mispellable();
| ^^^^^^^^^^^
| |
| variant or associated item not found in `Enum`
| help: there is a method with a similar name: `misspellable`

error[E0599]: no variant or associated item named `mispellable_trait` found for type `Enum` in the current scope
--> $DIR/associated-item-enum.rs:18:11
|
LL | enum Enum { Variant }
| --------- variant or associated item `mispellable_trait` not found here
...
LL | Enum::mispellable_trait();
| ^^^^^^^^^^^^^^^^^ variant or associated item not found in `Enum`

error[E0599]: no variant or associated item named `MISPELLABLE` found for type `Enum` in the current scope
--> $DIR/associated-item-enum.rs:19:11
|
LL | enum Enum { Variant }
| --------- variant or associated item `MISPELLABLE` not found here
...
LL | Enum::MISPELLABLE;
| ^^^^^^^^^^^
| |
| variant or associated item not found in `Enum`
| help: there is an associated constant with a similar name: `MISSPELLABLE`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0599`.
2 changes: 1 addition & 1 deletion src/test/ui/auto-ref-slice-plus-ref.stderr
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}
--> $DIR/auto-ref-slice-plus-ref.rs:7:7
|
LL | a.test_mut();
| ^^^^^^^^ help: did you mean: `get_mut`
| ^^^^^^^^ help: there is a method with a similar name: `get_mut`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `test_mut`, perhaps you need to implement it:
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/block-result/issue-3563.stderr
Expand Up @@ -2,7 +2,7 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope
--> $DIR/issue-3563.rs:3:17
|
LL | || self.b()
| ^ help: did you mean: `a`
| ^ help: there is a method with a similar name: `a`

error: aborting due to previous error

Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/bogus-tag.stderr
@@ -1,11 +1,11 @@
error[E0599]: no variant named `Hsl` found for type `Color` in the current scope
error[E0599]: no variant or associated item named `Hsl` found for type `Color` in the current scope
--> $DIR/bogus-tag.rs:7:16
|
LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), }
| ---------- variant `Hsl` not found here
| ---------- variant or associated item `Hsl` not found here
...
LL | Color::Hsl(h, s, l) => { println!("hsl"); }
| ^^^ variant not found in `Color`
| ^^^ variant or associated item not found in `Color`

error: aborting due to previous error

Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/empty/empty-struct-braces-expr.rs
Expand Up @@ -19,6 +19,8 @@ fn main() {

let xe1 = XEmpty1; //~ ERROR expected value, found struct `XEmpty1`
let xe1 = XEmpty1(); //~ ERROR expected function, found struct `XEmpty1`
let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type
let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type
let xe3 = XE::Empty3; //~ ERROR no variant or associated item named `Empty3` found for type
let xe3 = XE::Empty3(); //~ ERROR no variant or associated item named `Empty3` found for type

XE::Empty1 {}; //~ ERROR no variant `Empty1` in enum `empty_struct::XE`
}
20 changes: 13 additions & 7 deletions src/test/ui/empty/empty-struct-braces-expr.stderr
Expand Up @@ -46,25 +46,31 @@ LL | let xe1 = XEmpty1();
| did you mean `XEmpty1 { /* fields */ }`?
| help: a unit struct with a similar name exists: `XEmpty2`

error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:22:19
|
LL | let xe3 = XE::Empty3;
| ^^^^^^
| |
| variant not found in `empty_struct::XE`
| help: did you mean: `XEmpty3`
| variant or associated item not found in `empty_struct::XE`
| help: there is a variant with a similar name: `XEmpty3`

error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
error[E0599]: no variant or associated item named `Empty3` found for type `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:23:19
|
LL | let xe3 = XE::Empty3();
| ^^^^^^
| |
| variant not found in `empty_struct::XE`
| help: did you mean: `XEmpty3`
| variant or associated item not found in `empty_struct::XE`
| help: there is a variant with a similar name: `XEmpty3`

error: aborting due to 8 previous errors
error: no variant `Empty1` in enum `empty_struct::XE`
--> $DIR/empty-struct-braces-expr.rs:25:9
|
LL | XE::Empty1 {};
| ^^^^^^ help: there is a variant with a similar name: `XEmpty3`

error: aborting due to 9 previous errors

Some errors occurred: E0423, E0599.
For more information about an error, try `rustc --explain E0423`.
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-22933-2.rs
Expand Up @@ -2,7 +2,7 @@ enum Delicious {
Pie = 0x1,
Apple = 0x2,
ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
//~^ ERROR no variant named `PIE` found for type `Delicious`
//~^ ERROR no variant or associated item named `PIE` found for type `Delicious`
}

fn main() {}
6 changes: 3 additions & 3 deletions src/test/ui/issues/issue-22933-2.stderr
@@ -1,11 +1,11 @@
error[E0599]: no variant named `PIE` found for type `Delicious` in the current scope
error[E0599]: no variant or associated item named `PIE` found for type `Delicious` in the current scope
--> $DIR/issue-22933-2.rs:4:55
|
LL | enum Delicious {
| -------------- variant `PIE` not found here
| -------------- variant or associated item `PIE` not found here
...
LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
| ^^^ variant not found in `Delicious`
| ^^^ variant or associated item not found in `Delicious`

error: aborting due to previous error

Expand Down
12 changes: 4 additions & 8 deletions src/test/ui/issues/issue-23173.rs
Expand Up @@ -6,12 +6,8 @@ struct Struct {
fn use_token(token: &Token) { unimplemented!() }

fn main() {
use_token(&Token::Homura);
//~^ ERROR no variant named `Homura`
Struct::method();
//~^ ERROR no function or associated item named `method` found for type
Struct::method;
//~^ ERROR no function or associated item named `method` found for type
Struct::Assoc;
//~^ ERROR no associated item named `Assoc` found for type `Struct` in
use_token(&Token::Homura); //~ ERROR no variant or associated item named `Homura`
Struct::method(); //~ ERROR no function or associated item named `method` found for type
Struct::method; //~ ERROR no function or associated item named `method` found for type
Struct::Assoc; //~ ERROR no associated item named `Assoc` found for type `Struct` in
}
12 changes: 6 additions & 6 deletions src/test/ui/issues/issue-23173.stderr
@@ -1,14 +1,14 @@
error[E0599]: no variant named `Homura` found for type `Token` in the current scope
error[E0599]: no variant or associated item named `Homura` found for type `Token` in the current scope
--> $DIR/issue-23173.rs:9:23
|
LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ }
| ---------- variant `Homura` not found here
| ---------- variant or associated item `Homura` not found here
...
LL | use_token(&Token::Homura);
| ^^^^^^ variant not found in `Token`
| ^^^^^^ variant or associated item not found in `Token`

error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
--> $DIR/issue-23173.rs:11:13
--> $DIR/issue-23173.rs:10:13
|
LL | struct Struct {
| ------------- function or associated item `method` not found for this
Expand All @@ -17,7 +17,7 @@ LL | Struct::method();
| ^^^^^^ function or associated item not found in `Struct`

error[E0599]: no function or associated item named `method` found for type `Struct` in the current scope
--> $DIR/issue-23173.rs:13:13
--> $DIR/issue-23173.rs:11:13
|
LL | struct Struct {
| ------------- function or associated item `method` not found for this
Expand All @@ -26,7 +26,7 @@ LL | Struct::method;
| ^^^^^^ function or associated item not found in `Struct`

error[E0599]: no associated item named `Assoc` found for type `Struct` in the current scope
--> $DIR/issue-23173.rs:15:13
--> $DIR/issue-23173.rs:12:13
|
LL | struct Struct {
| ------------- associated item `Assoc` not found for this
Expand Down
3 changes: 1 addition & 2 deletions src/test/ui/issues/issue-23217.rs
@@ -1,6 +1,5 @@
pub enum SomeEnum {
B = SomeEnum::A,
//~^ ERROR no variant named `A` found for type `SomeEnum`
B = SomeEnum::A, //~ ERROR no variant or associated item named `A` found for type `SomeEnum`
}

fn main() {}
8 changes: 4 additions & 4 deletions src/test/ui/issues/issue-23217.stderr
@@ -1,13 +1,13 @@
error[E0599]: no variant named `A` found for type `SomeEnum` in the current scope
error[E0599]: no variant or associated item named `A` found for type `SomeEnum` in the current scope
--> $DIR/issue-23217.rs:2:19
|
LL | pub enum SomeEnum {
| ----------------- variant `A` not found here
| ----------------- variant or associated item `A` not found here
LL | B = SomeEnum::A,
| ^
| |
| variant not found in `SomeEnum`
| help: did you mean: `B`
| variant or associated item not found in `SomeEnum`
| help: there is a variant with a similar name: `B`

error: aborting due to previous error

Expand Down

0 comments on commit 757ef38

Please sign in to comment.