Reduce the diagnostic span when multiple fields are missing in pattern
This commit is contained in:
parent
adf2135adc
commit
685c3c1b4a
@ -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,
|
||||
|
17
src/test/ui/missing-fields-in-struct-pattern.rs
Normal file
17
src/test/ui/missing-fields-in-struct-pattern.rs
Normal file
@ -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");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user