Skip to content

Commit 978dc3d

Browse files
committed
Fixed: Multiple errors on single typo in match pattern
Here we have fixed the case where we were throwing two diagnostic messages `E0026` and `E0027` for same case like this Example error[E0026]: variant `A::A` does not have a field named `fob` --> src/test/ui/issue-52717.rs:20:12 | 20 | A::A { fob } => { println!("{}", fob); } | ^^^ variant `A::A` does not have this field error[E0027]: pattern does not mention field `foo` --> src/test/ui/issue-52717.rs:20:5 | 20 | A::A { fob } => { println!("{}", fob); } | ^^^^^^^^^^^^ missing field `foo` error: aborting due to 2 previous errors Here above we can see that both `E0026` and `E0027` are depicting same thing. So, to fix this issue, we are simply checking element of `inexistent_fields` is there any value lies in `unmentioned_fields` using Levenshtein algorithm, if does then for that case we are simply deleting element from `unmentioned_fields`. More or less now instead of showing separate message in `E0027` we are giving extra hint on `E0026` Address: #52717
1 parent cbbd70d commit 978dc3d

File tree

5 files changed

+56
-20
lines changed

5 files changed

+56
-20
lines changed

src/librustc_typeck/check/_match.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::cmp;
2424
use syntax::ast;
2525
use syntax::source_map::Spanned;
2626
use syntax::ptr::P;
27+
use syntax::util::lev_distance::find_best_match_for_name;
2728
use syntax_pos::Span;
2829

2930
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
@@ -925,7 +926,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
925926

926927
self.check_pat_walk(&field.pat, field_ty, def_bm, true);
927928
}
928-
929+
let mut unmentioned_fields = variant.fields
930+
.iter()
931+
.map(|field| field.ident.modern())
932+
.filter(|ident| !used_fields.contains_key(&ident))
933+
.collect::<Vec<_>>();
929934
if inexistent_fields.len() > 0 {
930935
let (field_names, t, plural) = if inexistent_fields.len() == 1 {
931936
(format!("a field named `{}`", inexistent_fields[0].1), "this", "")
@@ -944,13 +949,23 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
944949
kind_name,
945950
tcx.item_path_str(variant.did),
946951
field_names);
947-
if let Some((span, _)) = inexistent_fields.last() {
952+
if let Some((span, ident)) = inexistent_fields.last() {
948953
err.span_label(*span,
949954
format!("{} `{}` does not have {} field{}",
950955
kind_name,
951956
tcx.item_path_str(variant.did),
952957
t,
953958
plural));
959+
if plural == "" {
960+
let input = unmentioned_fields.iter().map(|field| &field.name);
961+
let suggested_name =
962+
find_best_match_for_name(input, &ident.name.as_str(), None);
963+
if let Some(suggested_name) = suggested_name {
964+
err.span_suggestion(*span, "did you mean", suggested_name.to_string());
965+
// we don't want to throw `E0027` in case we have thrown `E0026` for them
966+
unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
967+
}
968+
}
954969
}
955970
if tcx.sess.teach(&err.get_code().unwrap()) {
956971
err.note(
@@ -983,11 +998,6 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
983998
tcx.sess.span_err(span, "`..` cannot be used in union patterns");
984999
}
9851000
} else if !etc {
986-
let unmentioned_fields = variant.fields
987-
.iter()
988-
.map(|field| field.ident.modern())
989-
.filter(|ident| !used_fields.contains_key(&ident))
990-
.collect::<Vec<_>>();
9911001
if unmentioned_fields.len() > 0 {
9921002
let field_names = if unmentioned_fields.len() == 1 {
9931003
format!("field `{}`", unmentioned_fields[0])

src/test/ui/issue-52717.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
enum A {
11+
A {
12+
foo: usize,
13+
}
14+
}
15+
16+
fn main() {
17+
let x = A::A { foo: 3 };
18+
match x {
19+
A::A { fob } => { println!("{}", fob); }
20+
}
21+
}

src/test/ui/issue-52717.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0026]: variant `A::A` does not have a field named `fob`
2+
--> $DIR/issue-52717.rs:19:12
3+
|
4+
LL | A::A { fob } => { println!("{}", fob); }
5+
| ^^^
6+
| |
7+
| variant `A::A` does not have this field
8+
| help: did you mean: `foo`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0026`.

src/test/ui/issues/issue-17800.rs

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ fn main() {
1717
match MyOption::MySome(42) {
1818
MyOption::MySome { x: 42 } => (),
1919
//~^ ERROR variant `MyOption::MySome` does not have a field named `x`
20-
//~| ERROR pattern does not mention field `0`
2120
_ => (),
2221
}
2322
}

src/test/ui/issues/issue-17800.stderr

+6-12
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,11 @@ error[E0026]: variant `MyOption::MySome` does not have a field named `x`
22
--> $DIR/issue-17800.rs:18:28
33
|
44
LL | MyOption::MySome { x: 42 } => (),
5-
| ^^^^^ variant `MyOption::MySome` does not have this field
5+
| ^^^^^
6+
| |
7+
| variant `MyOption::MySome` does not have this field
8+
| help: did you mean: `0`
69

7-
error[E0027]: pattern does not mention field `0`
8-
--> $DIR/issue-17800.rs:18:9
9-
|
10-
LL | MyOption::MySome { x: 42 } => (),
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `0`
12-
|
13-
= note: trying to match a tuple variant with a struct variant pattern
14-
15-
error: aborting due to 2 previous errors
10+
error: aborting due to previous error
1611

17-
Some errors occurred: E0026, E0027.
18-
For more information about an error, try `rustc --explain E0026`.
12+
For more information about this error, try `rustc --explain E0026`.

0 commit comments

Comments
 (0)