From 17ada052e7f8b785eaadb6fb49197357ad644d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 9 Aug 2020 17:52:29 -0700 Subject: [PATCH] Detect tuple variants used as struct pattern and suggest correct pattern --- src/librustc_resolve/late/diagnostics.rs | 11 ++++++++++- src/test/ui/empty/empty-struct-tuple-pat.stderr | 16 +++++++++++----- src/test/ui/issues/issue-32004.stderr | 14 ++++++++++---- src/test/ui/issues/issue-63983.stderr | 2 +- src/test/ui/parser/recover-from-bad-variant.rs | 3 ++- .../ui/parser/recover-from-bad-variant.stderr | 11 +++++++++-- 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index c57c0e5194185..f0ea325d2ab74 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -701,7 +701,16 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if let Some(span) = self.def_span(def_id) { err.span_label(span, &format!("`{}` defined here", path_str)); } - err.span_label(span, format!("did you mean `{}( /* fields */ )`?", path_str)); + let fields = + self.r.field_names.get(&def_id).map_or("/* fields */".to_string(), |fields| { + vec!["_"; fields.len()].join(", ") + }); + err.span_suggestion( + span, + "use the tuple variant pattern syntax instead", + format!("{}({})", path_str, fields), + Applicability::HasPlaceholders, + ); } (Res::SelfTy(..), _) if ns == ValueNS => { err.span_label(span, fallback_label); diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr index 7b21d31635cf1..7b0d9717e63a2 100644 --- a/src/test/ui/empty/empty-struct-tuple-pat.stderr +++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr @@ -23,16 +23,13 @@ LL | Empty4() | -------- `E::Empty4` defined here ... LL | E::Empty4 => () - | ^^^^^^^^^ did you mean `E::Empty4( /* fields */ )`? + | ^^^^^^^^^ help: use the tuple variant pattern syntax instead: `E::Empty4()` error[E0532]: expected unit struct, unit variant or constant, found tuple variant `XE::XEmpty5` --> $DIR/empty-struct-tuple-pat.rs:33:9 | LL | XE::XEmpty5 => (), - | ^^^^------- - | | | - | | help: a unit variant with a similar name exists: `XEmpty4` - | did you mean `XE::XEmpty5( /* fields */ )`? + | ^^^^^^^^^^^ | ::: $DIR/auxiliary/empty-struct.rs:7:5 | @@ -40,6 +37,15 @@ LL | XEmpty4, | ------- similarly named unit variant `XEmpty4` defined here LL | XEmpty5(), | --------- `XE::XEmpty5` defined here + | +help: use the tuple variant pattern syntax instead + | +LL | XE::XEmpty5(/* fields */) => (), + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: a unit variant with a similar name exists + | +LL | XE::XEmpty4 => (), + | ^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr index ab723e26680dc..f95afb9c1fdc7 100644 --- a/src/test/ui/issues/issue-32004.stderr +++ b/src/test/ui/issues/issue-32004.stderr @@ -7,10 +7,16 @@ LL | Baz | --- similarly named unit variant `Baz` defined here ... LL | Foo::Bar => {} - | ^^^^^--- - | | | - | | help: a unit variant with a similar name exists: `Baz` - | did you mean `Foo::Bar( /* fields */ )`? + | ^^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL | Foo::Bar(_) => {} + | ^^^^^^^^^^^ +help: a unit variant with a similar name exists + | +LL | Foo::Baz => {} + | ^^^ error[E0532]: expected tuple struct or tuple variant, found unit struct `S` --> $DIR/issue-32004.rs:16:9 diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr index 771a5c285aff8..eb0428341020f 100644 --- a/src/test/ui/issues/issue-63983.stderr +++ b/src/test/ui/issues/issue-63983.stderr @@ -5,7 +5,7 @@ LL | Tuple(i32), | ---------- `MyEnum::Tuple` defined here ... LL | MyEnum::Tuple => "", - | ^^^^^^^^^^^^^ did you mean `MyEnum::Tuple( /* fields */ )`? + | ^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `MyEnum::Tuple(_)` error[E0532]: expected unit struct, unit variant or constant, found struct variant `MyEnum::Struct` --> $DIR/issue-63983.rs:10:9 diff --git a/src/test/ui/parser/recover-from-bad-variant.rs b/src/test/ui/parser/recover-from-bad-variant.rs index 27b03c0c2db27..1bcef450bb9be 100644 --- a/src/test/ui/parser/recover-from-bad-variant.rs +++ b/src/test/ui/parser/recover-from-bad-variant.rs @@ -9,6 +9,7 @@ fn main() { match x { Enum::Foo(a, b) => {} //~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo` - Enum::Bar(a, b) => {} + Enum::Bar { a, b } => {} + //~^ ERROR tuple variant `Enum::Bar` written as struct variant } } diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr index 6986d966d69ec..89232a519d7b2 100644 --- a/src/test/ui/parser/recover-from-bad-variant.stderr +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -18,6 +18,13 @@ LL | Foo { a: usize, b: usize }, LL | Enum::Foo(a, b) => {} | ^^^^^^^^^^^^^^^ help: use struct pattern syntax instead: `Enum::Foo { a, b }` -error: aborting due to 2 previous errors +error[E0769]: tuple variant `Enum::Bar` written as struct variant + --> $DIR/recover-from-bad-variant.rs:12:9 + | +LL | Enum::Bar { a, b } => {} + | ^^^^^^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `Enum::Bar(a, b)` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0532`. +Some errors have detailed explanations: E0532, E0769. +For more information about an error, try `rustc --explain E0532`.