diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 4f155995cd3d2..3204ef556f5dd 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -24,6 +24,7 @@ use std::cmp; use syntax::ast; use syntax::source_map::Spanned; use syntax::ptr::P; +use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { @@ -926,7 +927,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); self.check_pat_walk(&field.pat, field_ty, def_bm, true); } - + let mut unmentioned_fields = variant.fields + .iter() + .map(|field| field.ident.modern()) + .filter(|ident| !used_fields.contains_key(&ident)) + .collect::>(); if inexistent_fields.len() > 0 { let (field_names, t, plural) = if inexistent_fields.len() == 1 { (format!("a field named `{}`", inexistent_fields[0].1), "this", "") @@ -945,13 +950,23 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); kind_name, tcx.item_path_str(variant.did), field_names); - if let Some((span, _)) = inexistent_fields.last() { + if let Some((span, ident)) = inexistent_fields.last() { err.span_label(*span, format!("{} `{}` does not have {} field{}", kind_name, tcx.item_path_str(variant.did), t, plural)); + if plural == "" { + let input = unmentioned_fields.iter().map(|field| &field.name); + let suggested_name = + find_best_match_for_name(input, &ident.name.as_str(), None); + if let Some(suggested_name) = suggested_name { + err.span_suggestion(*span, "did you mean", suggested_name.to_string()); + // we don't want to throw `E0027` in case we have thrown `E0026` for them + unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str()); + } + } } if tcx.sess.teach(&err.get_code().unwrap()) { err.note( @@ -984,11 +999,6 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); tcx.sess.span_err(span, "`..` cannot be used in union patterns"); } } else if !etc { - let unmentioned_fields = variant.fields - .iter() - .map(|field| field.ident.modern()) - .filter(|ident| !used_fields.contains_key(&ident)) - .collect::>(); if unmentioned_fields.len() > 0 { let field_names = if unmentioned_fields.len() == 1 { format!("field `{}`", unmentioned_fields[0]) diff --git a/src/test/ui/issue-52717.rs b/src/test/ui/issue-52717.rs new file mode 100644 index 0000000000000..d40e2bd3d530c --- /dev/null +++ b/src/test/ui/issue-52717.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +enum A { + A { + foo: usize, + } +} + +fn main() { + let x = A::A { foo: 3 }; + match x { + A::A { fob } => { println!("{}", fob); } + } +} diff --git a/src/test/ui/issue-52717.stderr b/src/test/ui/issue-52717.stderr new file mode 100644 index 0000000000000..0ef5a84671d8d --- /dev/null +++ b/src/test/ui/issue-52717.stderr @@ -0,0 +1,12 @@ +error[E0026]: variant `A::A` does not have a field named `fob` + --> $DIR/issue-52717.rs:19:12 + | +LL | A::A { fob } => { println!("{}", fob); } + | ^^^ + | | + | variant `A::A` does not have this field + | help: did you mean: `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0026`. diff --git a/src/test/ui/issues/issue-17800.rs b/src/test/ui/issues/issue-17800.rs index f7cae91aa93a4..8ccf34f2456f4 100644 --- a/src/test/ui/issues/issue-17800.rs +++ b/src/test/ui/issues/issue-17800.rs @@ -17,7 +17,6 @@ fn main() { match MyOption::MySome(42) { MyOption::MySome { x: 42 } => (), //~^ ERROR variant `MyOption::MySome` does not have a field named `x` - //~| ERROR pattern does not mention field `0` _ => (), } } diff --git a/src/test/ui/issues/issue-17800.stderr b/src/test/ui/issues/issue-17800.stderr index 2cc562fbd7a1a..e1c48e8a0e8ef 100644 --- a/src/test/ui/issues/issue-17800.stderr +++ b/src/test/ui/issues/issue-17800.stderr @@ -2,17 +2,11 @@ error[E0026]: variant `MyOption::MySome` does not have a field named `x` --> $DIR/issue-17800.rs:18:28 | LL | MyOption::MySome { x: 42 } => (), - | ^^^^^ variant `MyOption::MySome` does not have this field + | ^^^^^ + | | + | variant `MyOption::MySome` does not have this field + | help: did you mean: `0` -error[E0027]: pattern does not mention field `0` - --> $DIR/issue-17800.rs:18:9 - | -LL | MyOption::MySome { x: 42 } => (), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `0` - | - = note: trying to match a tuple variant with a struct variant pattern - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0026, E0027. -For more information about an error, try `rustc --explain E0026`. +For more information about this error, try `rustc --explain E0026`.