From 16692ab66a6e2c62b416f606f144d60711c14414 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 13 Dec 2020 14:13:52 -0800 Subject: [PATCH 1/9] Suggest `_` and `..` if a pattern has too few fields For example, this code: struct S(i32, f32); let S(x) = S(0, 1.0); will make the compiler suggest either: let S(x, _) = S(0, 1.0); or: let S(x, ..) = S(0, 1.0); --- compiler/rustc_typeck/src/check/pat.rs | 29 +++++ .../tuple_struct_destructure_fail.stderr | 18 +++ src/test/ui/error-codes/E0023.stderr | 9 ++ ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 9 ++ src/test/ui/issues/issue-72574-2.stderr | 9 ++ .../match/match-pattern-field-mismatch.stderr | 9 ++ src/test/ui/pattern/issue-74539.stderr | 9 ++ src/test/ui/pattern/pat-tuple-underfield.rs | 49 +++++++ .../ui/pattern/pat-tuple-underfield.stderr | 121 ++++++++++++++++++ 9 files changed, 262 insertions(+) create mode 100644 src/test/ui/pattern/pat-tuple-underfield.rs create mode 100644 src/test/ui/pattern/pat-tuple-underfield.stderr diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 5fc573a57ad0b..942be1007f062 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -15,10 +15,12 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::Ident; +use rustc_span::{BytePos, DUMMY_SP}; use rustc_trait_selection::traits::{ObligationCause, Pattern}; use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; +use std::iter; use super::report_unexpected_variant_res; @@ -1040,6 +1042,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())], Applicability::MachineApplicable, ); + } else if fields.len() > subpats.len() { + let after_fields_span = if pat_span == DUMMY_SP { + pat_span + } else { + pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi() + }; + + let mut wildcard_sugg = + iter::repeat("_").take(fields.len() - subpats.len()).collect::>().join(", "); + if !subpats.is_empty() { + wildcard_sugg = String::from(", ") + &wildcard_sugg; + } + + let rest_sugg = if subpats.is_empty() { "..".to_owned() } else { ", ..".to_owned() }; + + err.span_suggestion( + after_fields_span, + "use `_` to explicitly ignore each field", + wildcard_sugg, + Applicability::MaybeIncorrect, + ); + err.span_suggestion( + after_fields_span, + "use `..` to ignore all unmentioned fields", + rest_sugg, + Applicability::MaybeIncorrect, + ); } err.emit(); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 0e7174e5b19d6..623e1d674d71a 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -31,6 +31,15 @@ LL | struct TupleStruct(S, T); ... LL | TupleStruct(_) = TupleStruct(1, 2); | ^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | TupleStruct(_, _) = TupleStruct(1, 2); + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | TupleStruct(_, ..) = TupleStruct(1, 2); + | ^^^^ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/tuple_struct_destructure_fail.rs:34:5 @@ -49,6 +58,15 @@ LL | SingleVariant(S, T) ... LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); | ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | Enum::SingleVariant(_, ..) = Enum::SingleVariant(1, 2); + | ^^^^ error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index a3610099294da..1d32eab15d33a 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -6,6 +6,15 @@ LL | Apple(String, String), ... LL | Fruit::Apple(a) => {}, | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Fruit::Apple(a, _) => {}, + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | Fruit::Apple(a, ..) => {}, + | ^^^^ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/E0023.rs:12:9 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 6e8ea6bf618f2..38177d1515820 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -17,6 +17,15 @@ LL | struct P(T); // 1 type parameter wanted ... LL | let P() = U {}; | ^^^ expected 1 field, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | let P(_) = U {}; + | ^ +help: use `..` to ignore all unmentioned fields + | +LL | let P(..) = U {}; + | ^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 0a9c868af7af8..8edc6ca8f0ed6 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -26,6 +26,15 @@ LL | struct Binder(i32, i32, i32); ... LL | Binder(_a, _x @ ..) => {} | ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Binder(_a, _x @ .., _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | Binder(_a, _x @ .., ..) => {} + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index c2298d6fbbf02..299b2d216db98 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -6,6 +6,15 @@ LL | Rgb(usize, usize, usize), ... LL | Color::Rgb(_, _) => { } | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Color::Rgb(_, _, _) => { } + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | Color::Rgb(_, _, ..) => { } + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index cbc90b5397d8b..7a73d39dbc0c6 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -26,6 +26,15 @@ LL | A(u8, u8), ... LL | E::A(x @ ..) => { | ^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::A(x @ .., _) => { + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | E::A(x @ .., ..) => { + | ^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs new file mode 100644 index 0000000000000..246dd0b37b659 --- /dev/null +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -0,0 +1,49 @@ +struct S(i32, f32); +enum E { + S(i32, f32), +} + +fn main() { + match S(0, 1.0) { + S(x) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all unmentioned fields + } + match S(0, 1.0) { + S(_) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all unmentioned fields + } + match S(0, 1.0) { + S() => {} + //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all unmentioned fields + } + + match E::S(0, 1.0) { + E::S(x) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all unmentioned fields + } + match E::S(0, 1.0) { + E::S(_) => {} + //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all unmentioned fields + } + match E::S(0, 1.0) { + E::S() => {} + //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all unmentioned fields + } + match E::S(0, 1.0) { + E::S => {} + //~^ ERROR expected unit struct, unit variant or constant, found tuple variant `E::S` + //~| HELP use the tuple variant pattern syntax instead + } +} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr new file mode 100644 index 0000000000000..5364053b8e526 --- /dev/null +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -0,0 +1,121 @@ +error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` + --> $DIR/pat-tuple-underfield.rs:45:9 + | +LL | S(i32, f32), + | ----------- `E::S` defined here +... +LL | E::S => {} + | ^^^^ help: use the tuple variant pattern syntax instead: `E::S(_, _)` + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields + --> $DIR/pat-tuple-underfield.rs:8:9 + | +LL | struct S(i32, f32); + | ------------------- tuple struct defined here +... +LL | S(x) => {} + | ^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | S(x, _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | S(x, ..) => {} + | ^^^^ + +error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields + --> $DIR/pat-tuple-underfield.rs:14:9 + | +LL | struct S(i32, f32); + | ------------------- tuple struct defined here +... +LL | S(_) => {} + | ^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | S(_, _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | S(_, ..) => {} + | ^^^^ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields + --> $DIR/pat-tuple-underfield.rs:20:9 + | +LL | struct S(i32, f32); + | ------------------- tuple struct defined here +... +LL | S() => {} + | ^^^ expected 2 fields, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | S(_, _) => {} + | ^^^^ +help: use `..` to ignore all unmentioned fields + | +LL | S(..) => {} + | ^^ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:27:9 + | +LL | S(i32, f32), + | ----------- tuple variant defined here +... +LL | E::S(x) => {} + | ^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(x, _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | E::S(x, ..) => {} + | ^^^^ + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:33:9 + | +LL | S(i32, f32), + | ----------- tuple variant defined here +... +LL | E::S(_) => {} + | ^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(_, _) => {} + | ^^^ +help: use `..` to ignore all unmentioned fields + | +LL | E::S(_, ..) => {} + | ^^^^ + +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields + --> $DIR/pat-tuple-underfield.rs:39:9 + | +LL | S(i32, f32), + | ----------- tuple variant defined here +... +LL | E::S() => {} + | ^^^^^^ expected 2 fields, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(_, _) => {} + | ^^^^ +help: use `..` to ignore all unmentioned fields + | +LL | E::S(..) => {} + | ^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0023, E0532. +For more information about an error, try `rustc --explain E0023`. From 5fe61a79cc5d26a0843b7169d1c95fbb3cbda0ba Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 17:09:53 -0800 Subject: [PATCH 2/9] Simplify code Co-authored-by: Esteban Kuber --- compiler/rustc_typeck/src/check/pat.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 942be1007f062..db2f4eca0c9d0 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1049,8 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi() }; - let mut wildcard_sugg = - iter::repeat("_").take(fields.len() - subpats.len()).collect::>().join(", "); + let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", "); if !subpats.is_empty() { wildcard_sugg = String::from(", ") + &wildcard_sugg; } From f3d9df54ee682d0b76909d27938b30c51ca5ec70 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 19:51:39 -0800 Subject: [PATCH 3/9] Suggest `Variant(..)` if all of the mentioned fields are `_` --- compiler/rustc_typeck/src/check/pat.rs | 33 ++++++++++++++----- .../tuple_struct_destructure_fail.stderr | 8 ++--- .../match/match-pattern-field-mismatch.stderr | 4 +-- .../ui/pattern/pat-tuple-underfield.stderr | 8 ++--- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index db2f4eca0c9d0..474aed39eb2fd 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -20,7 +20,6 @@ use rustc_trait_selection::traits::{ObligationCause, Pattern}; use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::iter; use super::report_unexpected_variant_res; @@ -1048,26 +1047,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { pat_span.with_hi(pat_span.hi() - BytePos(1)).shrink_to_hi() }; + let all_fields_span = match subpats { + [] => after_fields_span, + [field] => field.span, + [first, .., last] => first.span.to(last.span), + }; + + // Check if all the fields in the pattern are wildcards. + let all_wildcards = subpats.iter().all(|pat| matches!(pat.kind, PatKind::Wild)); let mut wildcard_sugg = vec!["_"; fields.len() - subpats.len()].join(", "); if !subpats.is_empty() { wildcard_sugg = String::from(", ") + &wildcard_sugg; } - let rest_sugg = if subpats.is_empty() { "..".to_owned() } else { ", ..".to_owned() }; - err.span_suggestion( after_fields_span, "use `_` to explicitly ignore each field", wildcard_sugg, Applicability::MaybeIncorrect, ); - err.span_suggestion( - after_fields_span, - "use `..` to ignore all unmentioned fields", - rest_sugg, - Applicability::MaybeIncorrect, - ); + + if subpats.is_empty() || all_wildcards { + err.span_suggestion( + all_fields_span, + "use `..` to ignore all unmentioned fields", + String::from(".."), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion( + after_fields_span, + "use `..` to ignore all unmentioned fields", + String::from(", .."), + Applicability::MaybeIncorrect, + ); + } } err.emit(); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 623e1d674d71a..dd1fbbbd3bbe5 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -38,8 +38,8 @@ LL | TupleStruct(_, _) = TupleStruct(1, 2); | ^^^ help: use `..` to ignore all unmentioned fields | -LL | TupleStruct(_, ..) = TupleStruct(1, 2); - | ^^^^ +LL | TupleStruct(..) = TupleStruct(1, 2); + | ^^ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/tuple_struct_destructure_fail.rs:34:5 @@ -65,8 +65,8 @@ LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); | ^^^ help: use `..` to ignore all unmentioned fields | -LL | Enum::SingleVariant(_, ..) = Enum::SingleVariant(1, 2); - | ^^^^ +LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); + | ^^ error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 299b2d216db98..1ee45ca1b1ea6 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -13,8 +13,8 @@ LL | Color::Rgb(_, _, _) => { } | ^^^ help: use `..` to ignore all unmentioned fields | -LL | Color::Rgb(_, _, ..) => { } - | ^^^^ +LL | Color::Rgb(..) => { } + | ^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index 5364053b8e526..b7a5402663917 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -40,8 +40,8 @@ LL | S(_, _) => {} | ^^^ help: use `..` to ignore all unmentioned fields | -LL | S(_, ..) => {} - | ^^^^ +LL | S(..) => {} + | ^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields --> $DIR/pat-tuple-underfield.rs:20:9 @@ -94,8 +94,8 @@ LL | E::S(_, _) => {} | ^^^ help: use `..` to ignore all unmentioned fields | -LL | E::S(_, ..) => {} - | ^^^^ +LL | E::S(..) => {} + | ^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields --> $DIR/pat-tuple-underfield.rs:39:9 From a5e8e6ec2df58bd50963af57bbd08d0526f119db Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 19:56:14 -0800 Subject: [PATCH 4/9] Pluralize 'parenthesis' correctly It's 'parentheses', not 'parenthesis', when you have more than one. --- compiler/rustc_typeck/src/check/pat.rs | 10 +++++----- src/test/ui/error-codes/E0023.stderr | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 474aed39eb2fd..a7670624f307c 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1002,7 +1002,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // More generally, the expected type wants a tuple variant with one field of an // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. - let missing_parenthesis = match (&expected.kind(), fields, had_err) { + let missing_parentheses = match (&expected.kind(), fields, had_err) { // #67037: only do this if we could successfully type-check the expected type against // the tuple struct pattern. Otherwise the substs could get out of range on e.g., // `let P() = U;` where `P != U` with `struct P(T);`. @@ -1015,13 +1015,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => false, }; - if missing_parenthesis { + if missing_parentheses { let (left, right) = match subpats { // This is the zero case; we aim to get the "hi" part of the `QPath`'s // span as the "lo" and then the "hi" part of the pattern's span as the "hi". // This looks like: // - // help: missing parenthesis + // help: missing parentheses // | // L | let A(()) = A(()); // | ^ ^ @@ -1030,14 +1030,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // last sub-pattern. In the case of `A(x)` the first and last may coincide. // This looks like: // - // help: missing parenthesis + // help: missing parentheses // | // L | let A((x, y)) = A((1, 2)); // | ^ ^ [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span), }; err.multipart_suggestion( - "missing parenthesis", + "missing parentheses", vec![(left, "(".to_string()), (right.shrink_to_hi(), ")".to_string())], Applicability::MachineApplicable, ); diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 1d32eab15d33a..965cf28c79f91 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -43,7 +43,7 @@ LL | Orange((String, String)), LL | Fruit::Orange(a, b) => {}, | ^^^^^^^^^^^^^^^^^^^ expected 1 field, found 2 | -help: missing parenthesis +help: missing parentheses | LL | Fruit::Orange((a, b)) => {}, | ^ ^ @@ -57,7 +57,7 @@ LL | Banana(()), LL | Fruit::Banana() => {}, | ^^^^^^^^^^^^^^^ expected 1 field, found 0 | -help: missing parenthesis +help: missing parentheses | LL | Fruit::Banana(()) => {}, | ^ ^ From fe82cc38a0b3e39b9425090e2107c0ba15760491 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 18 Dec 2020 20:17:09 -0800 Subject: [PATCH 5/9] Specialize `..` help message for all fields vs. the rest --- compiler/rustc_typeck/src/check/pat.rs | 4 ++-- .../tuple_struct_destructure_fail.stderr | 4 ++-- src/test/ui/error-codes/E0023.stderr | 2 +- ...ue-67037-pat-tup-scrut-ty-diff-less-fields.stderr | 2 +- src/test/ui/issues/issue-72574-2.stderr | 2 +- .../ui/match/match-pattern-field-mismatch.stderr | 2 +- src/test/ui/pattern/issue-74539.stderr | 2 +- src/test/ui/pattern/pat-tuple-underfield.rs | 12 ++++++------ src/test/ui/pattern/pat-tuple-underfield.stderr | 12 ++++++------ 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index a7670624f307c..43a69fe187431 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1071,14 +1071,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if subpats.is_empty() || all_wildcards { err.span_suggestion( all_fields_span, - "use `..` to ignore all unmentioned fields", + "use `..` to ignore all fields", String::from(".."), Applicability::MaybeIncorrect, ); } else { err.span_suggestion( after_fields_span, - "use `..` to ignore all unmentioned fields", + "use `..` to ignore the rest of the fields", String::from(", .."), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index dd1fbbbd3bbe5..c270593cac741 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -36,7 +36,7 @@ help: use `_` to explicitly ignore each field | LL | TupleStruct(_, _) = TupleStruct(1, 2); | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | TupleStruct(..) = TupleStruct(1, 2); | ^^ @@ -63,7 +63,7 @@ help: use `_` to explicitly ignore each field | LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); | ^^ diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 965cf28c79f91..aaaada518d3b7 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -11,7 +11,7 @@ help: use `_` to explicitly ignore each field | LL | Fruit::Apple(a, _) => {}, | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | Fruit::Apple(a, ..) => {}, | ^^^^ diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 38177d1515820..9bdbf0bf9f40d 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -22,7 +22,7 @@ help: use `_` to explicitly ignore each field | LL | let P(_) = U {}; | ^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | let P(..) = U {}; | ^^ diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 8edc6ca8f0ed6..02497029960bf 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -31,7 +31,7 @@ help: use `_` to explicitly ignore each field | LL | Binder(_a, _x @ .., _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | Binder(_a, _x @ .., ..) => {} | ^^^^ diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 1ee45ca1b1ea6..37839482b31a2 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -11,7 +11,7 @@ help: use `_` to explicitly ignore each field | LL | Color::Rgb(_, _, _) => { } | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | Color::Rgb(..) => { } | ^^ diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index 7a73d39dbc0c6..78249ed057ff8 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -31,7 +31,7 @@ help: use `_` to explicitly ignore each field | LL | E::A(x @ .., _) => { | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | E::A(x @ .., ..) => { | ^^^^ diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index 246dd0b37b659..f306377e6e51d 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -8,38 +8,38 @@ fn main() { S(x) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all unmentioned fields + //~| HELP use `..` to ignore the rest of the fields } match S(0, 1.0) { S(_) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all unmentioned fields + //~| HELP use `..` to ignore all fields } match S(0, 1.0) { S() => {} //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all unmentioned fields + //~| HELP use `..` to ignore all fields } match E::S(0, 1.0) { E::S(x) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all unmentioned fields + //~| HELP use `..` to ignore the rest of the fields } match E::S(0, 1.0) { E::S(_) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all unmentioned fields + //~| HELP use `..` to ignore all fields } match E::S(0, 1.0) { E::S() => {} //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all unmentioned fields + //~| HELP use `..` to ignore all fields } match E::S(0, 1.0) { E::S => {} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index b7a5402663917..d1aaeaeafa47e 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -20,7 +20,7 @@ help: use `_` to explicitly ignore each field | LL | S(x, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | S(x, ..) => {} | ^^^^ @@ -38,7 +38,7 @@ help: use `_` to explicitly ignore each field | LL | S(_, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | S(..) => {} | ^^ @@ -56,7 +56,7 @@ help: use `_` to explicitly ignore each field | LL | S(_, _) => {} | ^^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | S(..) => {} | ^^ @@ -74,7 +74,7 @@ help: use `_` to explicitly ignore each field | LL | E::S(x, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore the rest of the fields | LL | E::S(x, ..) => {} | ^^^^ @@ -92,7 +92,7 @@ help: use `_` to explicitly ignore each field | LL | E::S(_, _) => {} | ^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | E::S(..) => {} | ^^ @@ -110,7 +110,7 @@ help: use `_` to explicitly ignore each field | LL | E::S(_, _) => {} | ^^^^ -help: use `..` to ignore all unmentioned fields +help: use `..` to ignore all fields | LL | E::S(..) => {} | ^^ From 9959d6deedbf39d58fac06949596073d9c0dbb23 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 20 Dec 2020 14:43:07 -0800 Subject: [PATCH 6/9] Only suggest `..` if more than one field is missing --- compiler/rustc_typeck/src/check/pat.rs | 33 +++++---- .../tuple_struct_destructure_fail.stderr | 28 +++----- src/test/ui/error-codes/E0023.stderr | 14 ++-- ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 14 ++-- src/test/ui/issues/issue-72574-2.stderr | 14 ++-- .../match/match-pattern-field-mismatch.stderr | 14 ++-- src/test/ui/pattern/issue-74539.stderr | 14 ++-- src/test/ui/pattern/pat-tuple-underfield.rs | 4 -- .../ui/pattern/pat-tuple-underfield.stderr | 68 ++++++------------- 9 files changed, 68 insertions(+), 135 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 43a69fe187431..a863fc95e0ea1 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1061,27 +1061,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wildcard_sugg = String::from(", ") + &wildcard_sugg; } - err.span_suggestion( + err.span_suggestion_short( after_fields_span, "use `_` to explicitly ignore each field", wildcard_sugg, Applicability::MaybeIncorrect, ); - if subpats.is_empty() || all_wildcards { - err.span_suggestion( - all_fields_span, - "use `..` to ignore all fields", - String::from(".."), - Applicability::MaybeIncorrect, - ); - } else { - err.span_suggestion( - after_fields_span, - "use `..` to ignore the rest of the fields", - String::from(", .."), - Applicability::MaybeIncorrect, - ); + // Only suggest `..` if more than one field is missing. + if fields.len() - subpats.len() > 1 { + if subpats.is_empty() || all_wildcards { + err.span_suggestion_short( + all_fields_span, + "use `..` to ignore all fields", + String::from(".."), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_short( + after_fields_span, + "use `..` to ignore the rest of the fields", + String::from(", .."), + Applicability::MaybeIncorrect, + ); + } } } diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index c270593cac741..42859406e178d 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -30,16 +30,10 @@ LL | struct TupleStruct(S, T); | ------------------------------- tuple struct defined here ... LL | TupleStruct(_) = TupleStruct(1, 2); - | ^^^^^^^^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | TupleStruct(_, _) = TupleStruct(1, 2); - | ^^^ -help: use `..` to ignore all fields - | -LL | TupleStruct(..) = TupleStruct(1, 2); - | ^^ + | ^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/tuple_struct_destructure_fail.rs:34:5 @@ -57,16 +51,10 @@ LL | SingleVariant(S, T) | ------------------- tuple variant defined here ... LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); - | ^^^ -help: use `..` to ignore all fields - | -LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); - | ^^ + | ^^^^^^^^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index aaaada518d3b7..0c6f496cf4353 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -5,16 +5,10 @@ LL | Apple(String, String), | --------------------- tuple variant defined here ... LL | Fruit::Apple(a) => {}, - | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | Fruit::Apple(a, _) => {}, - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | Fruit::Apple(a, ..) => {}, - | ^^^^ + | ^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/E0023.rs:12:9 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 9bdbf0bf9f40d..86be8e7db4e6f 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -16,16 +16,10 @@ LL | struct P(T); // 1 type parameter wanted | --------------- tuple struct defined here ... LL | let P() = U {}; - | ^^^ expected 1 field, found 0 - | -help: use `_` to explicitly ignore each field - | -LL | let P(_) = U {}; - | ^ -help: use `..` to ignore all fields - | -LL | let P(..) = U {}; - | ^^ + | ^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 1 field, found 0 error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 02497029960bf..9479e365aee68 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -25,16 +25,10 @@ LL | struct Binder(i32, i32, i32); | ----------------------------- tuple struct defined here ... LL | Binder(_a, _x @ ..) => {} - | ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2 - | -help: use `_` to explicitly ignore each field - | -LL | Binder(_a, _x @ .., _) => {} - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | Binder(_a, _x @ .., ..) => {} - | ^^^^ + | ^^^^^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 3 fields, found 2 error: aborting due to 3 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 37839482b31a2..0bb5e726ccbd8 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -5,16 +5,10 @@ LL | Rgb(usize, usize, usize), | ------------------------ tuple variant defined here ... LL | Color::Rgb(_, _) => { } - | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 - | -help: use `_` to explicitly ignore each field - | -LL | Color::Rgb(_, _, _) => { } - | ^^^ -help: use `..` to ignore all fields - | -LL | Color::Rgb(..) => { } - | ^^ + | ^^^^^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 3 fields, found 2 error: aborting due to previous error diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index 78249ed057ff8..49011d83e5075 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -25,16 +25,10 @@ LL | A(u8, u8), | --------- tuple variant defined here ... LL | E::A(x @ ..) => { - | ^^^^^^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | E::A(x @ .., _) => { - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | E::A(x @ .., ..) => { - | ^^^^ + | ^^^^^^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error: aborting due to 3 previous errors diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index f306377e6e51d..f86d617801455 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -8,13 +8,11 @@ fn main() { S(x) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore the rest of the fields } match S(0, 1.0) { S(_) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all fields } match S(0, 1.0) { S() => {} @@ -27,13 +25,11 @@ fn main() { E::S(x) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore the rest of the fields } match E::S(0, 1.0) { E::S(_) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields //~| HELP use `_` to explicitly ignore each field - //~| HELP use `..` to ignore all fields } match E::S(0, 1.0) { E::S() => {} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index d1aaeaeafa47e..6e7afd8e57b1d 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -1,5 +1,5 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` - --> $DIR/pat-tuple-underfield.rs:45:9 + --> $DIR/pat-tuple-underfield.rs:41:9 | LL | S(i32, f32), | ----------- `E::S` defined here @@ -14,37 +14,25 @@ LL | struct S(i32, f32); | ------------------- tuple struct defined here ... LL | S(x) => {} - | ^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | S(x, _) => {} - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | S(x, ..) => {} - | ^^^^ + | ^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:14:9 + --> $DIR/pat-tuple-underfield.rs:13:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here ... LL | S(_) => {} - | ^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | S(_, _) => {} - | ^^^ -help: use `..` to ignore all fields - | -LL | S(..) => {} - | ^^ + | ^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:20:9 + --> $DIR/pat-tuple-underfield.rs:18:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -62,43 +50,31 @@ LL | S(..) => {} | ^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:27:9 + --> $DIR/pat-tuple-underfield.rs:25:9 | LL | S(i32, f32), | ----------- tuple variant defined here ... LL | E::S(x) => {} - | ^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | E::S(x, _) => {} - | ^^^ -help: use `..` to ignore the rest of the fields - | -LL | E::S(x, ..) => {} - | ^^^^ + | ^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:33:9 + --> $DIR/pat-tuple-underfield.rs:30:9 | LL | S(i32, f32), | ----------- tuple variant defined here ... LL | E::S(_) => {} - | ^^^^^^^ expected 2 fields, found 1 - | -help: use `_` to explicitly ignore each field - | -LL | E::S(_, _) => {} - | ^^^ -help: use `..` to ignore all fields - | -LL | E::S(..) => {} - | ^^ + | ^^^^^^- + | | | + | | help: use `_` to explicitly ignore each field + | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:39:9 + --> $DIR/pat-tuple-underfield.rs:35:9 | LL | S(i32, f32), | ----------- tuple variant defined here From 1bce77576964e069833edb1b3b6ca5baa68ae65e Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 16:47:04 -0800 Subject: [PATCH 7/9] Add a test case with lots of whitespace --- src/test/ui/pattern/pat-tuple-underfield.rs | 8 +++++ .../ui/pattern/pat-tuple-underfield.stderr | 34 ++++++++++++++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index f86d617801455..50f8a855d3639 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -2,6 +2,7 @@ struct S(i32, f32); enum E { S(i32, f32), } +struct Point4(i32, i32, i32, i32); fn main() { match S(0, 1.0) { @@ -42,4 +43,11 @@ fn main() { //~^ ERROR expected unit struct, unit variant or constant, found tuple variant `E::S` //~| HELP use the tuple variant pattern syntax instead } + + match Point4(0, 1, 2, 3) { + Point4( a , _ ) => {} + //~^ ERROR this pattern has 2 fields, but the corresponding tuple struct has 4 fields + //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore the rest of the fields + } } diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index 6e7afd8e57b1d..df6b216272e30 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -1,5 +1,5 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` - --> $DIR/pat-tuple-underfield.rs:41:9 + --> $DIR/pat-tuple-underfield.rs:42:9 | LL | S(i32, f32), | ----------- `E::S` defined here @@ -8,7 +8,7 @@ LL | E::S => {} | ^^^^ help: use the tuple variant pattern syntax instead: `E::S(_, _)` error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:8:9 + --> $DIR/pat-tuple-underfield.rs:9:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -20,7 +20,7 @@ LL | S(x) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:13:9 + --> $DIR/pat-tuple-underfield.rs:14:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -32,7 +32,7 @@ LL | S(_) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:18:9 + --> $DIR/pat-tuple-underfield.rs:19:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -50,7 +50,7 @@ LL | S(..) => {} | ^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:25:9 + --> $DIR/pat-tuple-underfield.rs:26:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -62,7 +62,7 @@ LL | E::S(x) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:30:9 + --> $DIR/pat-tuple-underfield.rs:31:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -74,7 +74,7 @@ LL | E::S(_) => {} | expected 2 fields, found 1 error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:35:9 + --> $DIR/pat-tuple-underfield.rs:36:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -91,7 +91,25 @@ help: use `..` to ignore all fields LL | E::S(..) => {} | ^^ -error: aborting due to 7 previous errors +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields + --> $DIR/pat-tuple-underfield.rs:48:9 + | +LL | struct Point4(i32, i32, i32, i32); + | ---------------------------------- tuple struct defined here +... +LL | Point4( a , _ ) => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 4 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Point4( a , _ , _, _) => {} + | ^^^^^^ +help: use `..` to ignore the rest of the fields + | +LL | Point4( a , _ , ..) => {} + | ^^^^ + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0023, E0532. For more information about an error, try `rustc --explain E0023`. From d7307a71f5e1893f7bd69ff160ce38dc97b5d195 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 19:06:20 -0800 Subject: [PATCH 8/9] Always show suggestions in their own subwindows --- compiler/rustc_typeck/src/check/pat.rs | 6 +-- .../tuple_struct_destructure_fail.stderr | 20 ++++++---- src/test/ui/error-codes/E0023.stderr | 10 +++-- ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 10 +++-- src/test/ui/issues/issue-72574-2.stderr | 10 +++-- .../match/match-pattern-field-mismatch.stderr | 10 +++-- src/test/ui/pattern/issue-74539.stderr | 10 +++-- .../ui/pattern/pat-tuple-underfield.stderr | 40 +++++++++++-------- 8 files changed, 69 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index a863fc95e0ea1..e176389f0e279 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wildcard_sugg = String::from(", ") + &wildcard_sugg; } - err.span_suggestion_short( + err.span_suggestion_verbose( after_fields_span, "use `_` to explicitly ignore each field", wildcard_sugg, @@ -1071,14 +1071,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only suggest `..` if more than one field is missing. if fields.len() - subpats.len() > 1 { if subpats.is_empty() || all_wildcards { - err.span_suggestion_short( + err.span_suggestion_verbose( all_fields_span, "use `..` to ignore all fields", String::from(".."), Applicability::MaybeIncorrect, ); } else { - err.span_suggestion_short( + err.span_suggestion_verbose( after_fields_span, "use `..` to ignore the rest of the fields", String::from(", .."), diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 42859406e178d..8c20bb4fb833c 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -30,10 +30,12 @@ LL | struct TupleStruct(S, T); | ------------------------------- tuple struct defined here ... LL | TupleStruct(_) = TupleStruct(1, 2); - | ^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | TupleStruct(_, _) = TupleStruct(1, 2); + | ^^^ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/tuple_struct_destructure_fail.rs:34:5 @@ -51,10 +53,12 @@ LL | SingleVariant(S, T) | ------------------- tuple variant defined here ... LL | Enum::SingleVariant(_) = Enum::SingleVariant(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); + | ^^^ error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 0c6f496cf4353..832eba6972213 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -5,10 +5,12 @@ LL | Apple(String, String), | --------------------- tuple variant defined here ... LL | Fruit::Apple(a) => {}, - | ^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | Fruit::Apple(a, _) => {}, + | ^^^ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/E0023.rs:12:9 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 86be8e7db4e6f..46ffac48c1bad 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -16,10 +16,12 @@ LL | struct P(T); // 1 type parameter wanted | --------------- tuple struct defined here ... LL | let P() = U {}; - | ^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 1 field, found 0 + | ^^^ expected 1 field, found 0 + | +help: use `_` to explicitly ignore each field + | +LL | let P(_) = U {}; + | ^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 9479e365aee68..a1e8ec1677db5 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -25,10 +25,12 @@ LL | struct Binder(i32, i32, i32); | ----------------------------- tuple struct defined here ... LL | Binder(_a, _x @ ..) => {} - | ^^^^^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 3 fields, found 2 + | ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Binder(_a, _x @ .., _) => {} + | ^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 0bb5e726ccbd8..04f8cab900e1b 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -5,10 +5,12 @@ LL | Rgb(usize, usize, usize), | ------------------------ tuple variant defined here ... LL | Color::Rgb(_, _) => { } - | ^^^^^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 3 fields, found 2 + | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Color::Rgb(_, _, _) => { } + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr index 49011d83e5075..f7644c19ea0d9 100644 --- a/src/test/ui/pattern/issue-74539.stderr +++ b/src/test/ui/pattern/issue-74539.stderr @@ -25,10 +25,12 @@ LL | A(u8, u8), | --------- tuple variant defined here ... LL | E::A(x @ ..) => { - | ^^^^^^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::A(x @ .., _) => { + | ^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index df6b216272e30..cdf7cfe30054d 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -14,10 +14,12 @@ LL | struct S(i32, f32); | ------------------- tuple struct defined here ... LL | S(x) => {} - | ^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | S(x, _) => {} + | ^^^ error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields --> $DIR/pat-tuple-underfield.rs:14:9 @@ -26,10 +28,12 @@ LL | struct S(i32, f32); | ------------------- tuple struct defined here ... LL | S(_) => {} - | ^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | S(_, _) => {} + | ^^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields --> $DIR/pat-tuple-underfield.rs:19:9 @@ -56,10 +60,12 @@ LL | S(i32, f32), | ----------- tuple variant defined here ... LL | E::S(x) => {} - | ^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(x, _) => {} + | ^^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields --> $DIR/pat-tuple-underfield.rs:31:9 @@ -68,10 +74,12 @@ LL | S(i32, f32), | ----------- tuple variant defined here ... LL | E::S(_) => {} - | ^^^^^^- - | | | - | | help: use `_` to explicitly ignore each field - | expected 2 fields, found 1 + | ^^^^^^^ expected 2 fields, found 1 + | +help: use `_` to explicitly ignore each field + | +LL | E::S(_, _) => {} + | ^^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields --> $DIR/pat-tuple-underfield.rs:36:9 From e8c87935e0004ff784ad361a5bac39d7677c3f4f Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 12 Jan 2021 20:39:51 -0800 Subject: [PATCH 9/9] Include `..` suggestion if fields are all wildcards --- compiler/rustc_typeck/src/check/pat.rs | 5 +++-- .../tuple_struct_destructure_fail.stderr | 8 ++++++++ ...7-pat-tup-scrut-ty-diff-less-fields.stderr | 4 ++++ .../match/match-pattern-field-mismatch.stderr | 4 ++++ src/test/ui/pattern/pat-tuple-underfield.rs | 2 ++ .../ui/pattern/pat-tuple-underfield.stderr | 20 +++++++++++++------ 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index e176389f0e279..ecc6e8599ad01 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1068,8 +1068,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); - // Only suggest `..` if more than one field is missing. - if fields.len() - subpats.len() > 1 { + // Only suggest `..` if more than one field is missing + // or the pattern consists of all wildcards. + if fields.len() - subpats.len() > 1 || all_wildcards { if subpats.is_empty() || all_wildcards { err.span_suggestion_verbose( all_fields_span, diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr index 8c20bb4fb833c..c270593cac741 100644 --- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr +++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr @@ -36,6 +36,10 @@ help: use `_` to explicitly ignore each field | LL | TupleStruct(_, _) = TupleStruct(1, 2); | ^^^ +help: use `..` to ignore all fields + | +LL | TupleStruct(..) = TupleStruct(1, 2); + | ^^ error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields --> $DIR/tuple_struct_destructure_fail.rs:34:5 @@ -59,6 +63,10 @@ help: use `_` to explicitly ignore each field | LL | Enum::SingleVariant(_, _) = Enum::SingleVariant(1, 2); | ^^^ +help: use `..` to ignore all fields + | +LL | Enum::SingleVariant(..) = Enum::SingleVariant(1, 2); + | ^^ error[E0070]: invalid left-hand side of assignment --> $DIR/tuple_struct_destructure_fail.rs:40:12 diff --git a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr index 46ffac48c1bad..9bdbf0bf9f40d 100644 --- a/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr +++ b/src/test/ui/issues/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr @@ -22,6 +22,10 @@ help: use `_` to explicitly ignore each field | LL | let P(_) = U {}; | ^ +help: use `..` to ignore all fields + | +LL | let P(..) = U {}; + | ^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr index 04f8cab900e1b..37839482b31a2 100644 --- a/src/test/ui/match/match-pattern-field-mismatch.stderr +++ b/src/test/ui/match/match-pattern-field-mismatch.stderr @@ -11,6 +11,10 @@ help: use `_` to explicitly ignore each field | LL | Color::Rgb(_, _, _) => { } | ^^^ +help: use `..` to ignore all fields + | +LL | Color::Rgb(..) => { } + | ^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs index 50f8a855d3639..ed852a47bb4ee 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.rs +++ b/src/test/ui/pattern/pat-tuple-underfield.rs @@ -14,6 +14,7 @@ fn main() { S(_) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple struct has 2 fields //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields } match S(0, 1.0) { S() => {} @@ -31,6 +32,7 @@ fn main() { E::S(_) => {} //~^ ERROR this pattern has 1 field, but the corresponding tuple variant has 2 fields //~| HELP use `_` to explicitly ignore each field + //~| HELP use `..` to ignore all fields } match E::S(0, 1.0) { E::S() => {} diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr index cdf7cfe30054d..76323d9a7bf56 100644 --- a/src/test/ui/pattern/pat-tuple-underfield.stderr +++ b/src/test/ui/pattern/pat-tuple-underfield.stderr @@ -1,5 +1,5 @@ error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S` - --> $DIR/pat-tuple-underfield.rs:42:9 + --> $DIR/pat-tuple-underfield.rs:44:9 | LL | S(i32, f32), | ----------- `E::S` defined here @@ -34,9 +34,13 @@ help: use `_` to explicitly ignore each field | LL | S(_, _) => {} | ^^^ +help: use `..` to ignore all fields + | +LL | S(..) => {} + | ^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields - --> $DIR/pat-tuple-underfield.rs:19:9 + --> $DIR/pat-tuple-underfield.rs:20:9 | LL | struct S(i32, f32); | ------------------- tuple struct defined here @@ -54,7 +58,7 @@ LL | S(..) => {} | ^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:26:9 + --> $DIR/pat-tuple-underfield.rs:27:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -68,7 +72,7 @@ LL | E::S(x, _) => {} | ^^^ error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:31:9 + --> $DIR/pat-tuple-underfield.rs:32:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -80,9 +84,13 @@ help: use `_` to explicitly ignore each field | LL | E::S(_, _) => {} | ^^^ +help: use `..` to ignore all fields + | +LL | E::S(..) => {} + | ^^ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields - --> $DIR/pat-tuple-underfield.rs:36:9 + --> $DIR/pat-tuple-underfield.rs:38:9 | LL | S(i32, f32), | ----------- tuple variant defined here @@ -100,7 +108,7 @@ LL | E::S(..) => {} | ^^ error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields - --> $DIR/pat-tuple-underfield.rs:48:9 + --> $DIR/pat-tuple-underfield.rs:50:9 | LL | struct Point4(i32, i32, i32, i32); | ---------------------------------- tuple struct defined here