better diagnostics for pattern matching tuple structs

Better diagnostic message when trying to pattern match a tuple struct with a struct pattern.
This commit is contained in:
Maciej Wasilewski 2023-03-30 10:35:06 +02:00
parent 82bfda848e
commit 3b38dd9112
3 changed files with 42 additions and 4 deletions

View File

@ -36,6 +36,10 @@
You can read more about trait objects in the Trait Objects section of the Reference: \
https://doc.rust-lang.org/reference/types.html#trait-objects";
fn is_number(text: &str) -> bool {
text.chars().all(|c: char| c.is_digit(10))
}
/// Information about the expected type at the top level of type checking a pattern.
///
/// **NOTE:** This is only for use by diagnostics. Do NOT use for type checking logic!
@ -1671,7 +1675,15 @@ fn error_tuple_variant_as_struct_pat(
fields: &'tcx [hir::PatField<'tcx>],
variant: &ty::VariantDef,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
if let (Some(CtorKind::Fn), PatKind::Struct(qpath, ..)) = (variant.ctor_kind(), &pat.kind) {
if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
(variant.ctor_kind(), &pat.kind)
{
let is_tuple_struct_match = !pattern_fields.is_empty()
&& pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
if is_tuple_struct_match {
return None;
}
let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
s.print_qpath(qpath, false)
});
@ -1893,7 +1905,14 @@ fn error_unmentioned_fields(
prefix,
unmentioned_fields
.iter()
.map(|(_, name)| name.to_string())
.map(|(_, name)| {
let field_name = name.to_string();
if is_number(&field_name) {
format!("{}: _", field_name)
} else {
field_name
}
})
.collect::<Vec<_>>()
.join(", "),
if have_inaccessible_fields { ", .." } else { "" },

View File

@ -12,4 +12,7 @@ fn main() {
match y {
S { } => {} //~ ERROR: tuple variant `S` written as struct variant [E0769]
}
if let E::S { 0: a } = x { //~ ERROR: pattern does not mention field `1`
}
}

View File

@ -20,6 +20,22 @@ help: use the tuple variant pattern syntax instead
LL | S(_, _) => {}
| ~~~~~~
error: aborting due to 2 previous errors
error[E0027]: pattern does not mention field `1`
--> $DIR/struct-tuple-field-names.rs:16:12
|
LL | if let E::S { 0: a } = x {
| ^^^^^^^^^^^^^ missing field `1`
|
help: include the missing field in the pattern
|
LL | if let E::S { 0: a, 1: _ } = x {
| ~~~~~~~~
help: if you don't care about this missing field, you can explicitly ignore it
|
LL | if let E::S { 0: a, .. } = x {
| ~~~~~~
For more information about this error, try `rustc --explain E0769`.
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0027, E0769.
For more information about an error, try `rustc --explain E0027`.