From f71979b41909016b7f7696eb0f82b11ab721a621 Mon Sep 17 00:00:00 2001 From: tunawasabi <77270077+tunawasabi@users.noreply.github.com> Date: Sun, 25 Aug 2024 04:24:27 +0900 Subject: [PATCH] Suggest the struct variant pattern syntax on usage of unit variant pattern for a struct variant --- compiler/rustc_hir_typeck/src/lib.rs | 32 ++++++++++++++++- .../ui/empty/empty-struct-braces-pat-1.stderr | 14 ++++++-- .../ui/empty/empty-struct-braces-pat-3.stderr | 36 ++++++++++++++++--- tests/ui/issues/issue-63983.stderr | 7 +++- .../recover/recover-from-bad-variant.stderr | 9 ++++- tests/ui/suggestions/issue-84700.stderr | 9 ++++- ...t-variant-form-through-alias-caught.stderr | 16 +++++++-- 7 files changed, 111 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9ec101196a43f..aca6c77d4d0a9 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -45,7 +45,7 @@ pub use coercion::can_coerce; use fn_ctxt::FnCtxt; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; -use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -421,6 +421,36 @@ fn report_unexpected_variant_res( err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect); err } + Res::Def(DefKind::Variant, _) if expr.is_none() => { + let fields = &tcx.expect_variant_res(res).fields.raw; + + let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi()); + let (msg, sugg) = if fields.is_empty() { + ("use the struct variant pattern syntax".to_string(), " {}".to_string()) + } else { + let msg = format!( + "the struct variant's field{s} {are} being ignored", + s = pluralize!(fields.len()), + are = pluralize!("is", fields.len()) + ); + let fields = fields + .iter() + .map(|field| format!("{}: _", field.name.to_ident_string())) + .collect::>() + .join(", "); + let sugg = format!(" {{ /* {} */ }}", fields,); + (msg, sugg) + }; + + err.span_label(span, format!("not a {expected}")); + err.span_suggestion_verbose( + qpath.span().shrink_to_hi().to(span.shrink_to_hi()), + msg, + sugg, + Applicability::HasPlaceholders, + ); + err + } _ => err.with_span_label(span, format!("not a {expected}")), } .emit() diff --git a/tests/ui/empty/empty-struct-braces-pat-1.stderr b/tests/ui/empty/empty-struct-braces-pat-1.stderr index 14e09fc27a06d..4d6156a76250e 100644 --- a/tests/ui/empty/empty-struct-braces-pat-1.stderr +++ b/tests/ui/empty/empty-struct-braces-pat-1.stderr @@ -2,13 +2,23 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia --> $DIR/empty-struct-braces-pat-1.rs:24:9 | LL | E::Empty3 => () - | ^^^^^^^^^ not a unit struct, unit variant or constant + | ^^^^^^^^^- not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ++ error[E0533]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-1.rs:31:9 | LL | XE::XEmpty3 => () - | ^^^^^^^^^^^ not a unit struct, unit variant or constant + | ^^^^^^^^^^^- not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ++ error: aborting due to 2 previous errors diff --git a/tests/ui/empty/empty-struct-braces-pat-3.stderr b/tests/ui/empty/empty-struct-braces-pat-3.stderr index 00c8b12e6f984..33dbd304fb4b9 100644 --- a/tests/ui/empty/empty-struct-braces-pat-3.stderr +++ b/tests/ui/empty/empty-struct-braces-pat-3.stderr @@ -2,25 +2,53 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `E::E --> $DIR/empty-struct-braces-pat-3.rs:17:9 | LL | E::Empty3() => () - | ^^^^^^^^^^^ not a tuple struct or tuple variant + | ^^^^^^^^^-- + | | + | not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-3.rs:21:9 | LL | XE::XEmpty3() => () - | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + | ^^^^^^^^^^^-- + | | + | not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:25:9 | LL | E::Empty3(..) => () - | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + | ^^^^^^^^^---- + | | + | not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-3.rs:29:9 | LL | XE::XEmpty3(..) => () - | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | ^^^^^^^^^^^---- + | | + | not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/issues/issue-63983.stderr b/tests/ui/issues/issue-63983.stderr index f90c81116264a..1d8fa21c3fb86 100644 --- a/tests/ui/issues/issue-63983.stderr +++ b/tests/ui/issues/issue-63983.stderr @@ -11,7 +11,12 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia --> $DIR/issue-63983.rs:10:9 | LL | MyEnum::Struct => "", - | ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + | ^^^^^^^^^^^^^^- not a unit struct, unit variant or constant + | +help: the struct variant's field is being ignored + | +LL | MyEnum::Struct { /* s: _ */ } => "", + | ++++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/parser/recover/recover-from-bad-variant.stderr b/tests/ui/parser/recover/recover-from-bad-variant.stderr index 04968bbdf999d..2735288f5679a 100644 --- a/tests/ui/parser/recover/recover-from-bad-variant.stderr +++ b/tests/ui/parser/recover/recover-from-bad-variant.stderr @@ -18,7 +18,14 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum --> $DIR/recover-from-bad-variant.rs:10:9 | LL | Enum::Foo(a, b) => {} - | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | ^^^^^^^^^------ + | | + | not a tuple struct or tuple variant + | +help: the struct variant's fields are being ignored + | +LL | Enum::Foo { /* a: _, b: _ */ } => {} + | ~~~~~~~~~~~~~~~~~~~~ error[E0769]: tuple variant `Enum::Bar` written as struct variant --> $DIR/recover-from-bad-variant.rs:12:9 diff --git a/tests/ui/suggestions/issue-84700.stderr b/tests/ui/suggestions/issue-84700.stderr index ac9f5ab0b0cbb..9cebd450ee7df 100644 --- a/tests/ui/suggestions/issue-84700.stderr +++ b/tests/ui/suggestions/issue-84700.stderr @@ -11,7 +11,14 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Farm --> $DIR/issue-84700.rs:17:9 | LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(), - | ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | ^^^^^^^^^^^^^^^^^^^--- + | | + | not a tuple struct or tuple variant + | +help: the struct variant's field is being ignored + | +LL | FarmAnimal::Chicken { /* num_eggs: _ */ } => "cluck, cluck!".to_string(), + | ~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr index c21c59397c79e..8f7860e94d68e 100644 --- a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -13,13 +13,25 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:9 | LL | let Alias::Braced = panic!(); - | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant + | ^^^^^^^^^^^^^- not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | let Alias::Braced {} = panic!(); + | ++ error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced` --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9 | LL | let Alias::Braced(..) = panic!(); - | ^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | ^^^^^^^^^^^^^---- + | | + | not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | let Alias::Braced {} = panic!(); + | ~~ error[E0618]: expected function, found enum variant `Alias::Unit` --> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5