diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2018-03-18 23:01:11 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2018-03-18 23:01:11 -0700 |
| commit | 685c3c1b4a7c1949048177409ca43fc05daefd3f (patch) | |
| tree | 8ccd7255bfb5f683256662869bed351749b0f48c /src | |
| parent | adf2135adc4a65a78ba053f04c29d7fe0468eb87 (diff) | |
| download | rust-685c3c1b4a7c1949048177409ca43fc05daefd3f.tar.gz rust-685c3c1b4a7c1949048177409ca43fc05daefd3f.zip | |
Reduce the diagnostic span when multiple fields are missing in pattern
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_typeck/check/_match.rs | 70 | ||||
| -rw-r--r-- | src/test/ui/missing-fields-in-struct-pattern.rs | 17 |
2 files changed, 59 insertions, 28 deletions
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 379fd93ba2b..0b5383f1f8d 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -904,6 +904,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); // Keep track of which fields have already appeared in the pattern. let mut used_fields = FxHashMap(); + let mut inexistent_fields = vec![]; // Typecheck each field. for &Spanned { node: ref field, span } in fields { let field_ty = match used_fields.entry(field.name) { @@ -927,34 +928,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); self.field_ty(span, f, substs) }) .unwrap_or_else(|| { - let mut err = struct_span_err!( - tcx.sess, - span, - E0026, - "{} `{}` does not have a field named `{}`", - kind_name, - tcx.item_path_str(variant.did), - field.name - ); - err.span_label(span, - format!("{} `{}` does not have field `{}`", - kind_name, - tcx.item_path_str(variant.did), - field.name)); - if tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "This error indicates that a struct pattern attempted to \ - extract a non-existent field from a struct. Struct fields \ - are identified by the name used before the colon : so struct \ - patterns should resemble the declaration of the struct type \ - being matched.\n\n\ - If you are using shorthand field patterns but want to refer \ - to the struct field by a different name, you should rename \ - it explicitly." - ); - } - err.emit(); - + inexistent_fields.push((span, field.name)); tcx.types.err }) } @@ -963,6 +937,46 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); self.check_pat_walk(&field.pat, field_ty, def_bm, true); } + if inexistent_fields.len() > 0 { + let field_names = if inexistent_fields.len() == 1 { + format!("a field named `{}`", inexistent_fields[0].1) + } else { + format!("fields named {}", + inexistent_fields.iter() + .map(|(_, name)| format!("`{}`", name)) + .collect::<Vec<String>>() + .join(", ")) + }; + let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>(); + let mut err = struct_span_err!(tcx.sess, + spans, + E0026, + "{} `{}` does not have {}", + kind_name, + tcx.item_path_str(variant.did), + field_names); + for (span, name) in &inexistent_fields { + err.span_label(*span, + format!("{} `{}` does not have field `{}`", + kind_name, + tcx.item_path_str(variant.did), + name)); + } + if tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "This error indicates that a struct pattern attempted to \ + extract a non-existent field from a struct. Struct fields \ + are identified by the name used before the colon : so struct \ + patterns should resemble the declaration of the struct type \ + being matched.\n\n\ + If you are using shorthand field patterns but want to refer \ + to the struct field by a different name, you should rename \ + it explicitly." + ); + } + err.emit(); + } + // Require `..` if struct has non_exhaustive attribute. if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc { span_err!(tcx.sess, span, E0638, diff --git a/src/test/ui/missing-fields-in-struct-pattern.rs b/src/test/ui/missing-fields-in-struct-pattern.rs new file mode 100644 index 00000000000..2469f245345 --- /dev/null +++ b/src/test/ui/missing-fields-in-struct-pattern.rs @@ -0,0 +1,17 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S(usize, usize, usize, usize); + +fn main() { + if let S { a, b, c, d } = S(1, 2, 3, 4) { + println!("hi"); + } +} |
