Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx,
res,
Some(expr),
&[],
qpath,
expr.span,
E0533,
Expand Down
37 changes: 27 additions & 10 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub use coercion::can_coerce;
use fn_ctxt::FnCtxt;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{HirId, HirIdMap, Node};
Expand Down Expand Up @@ -482,6 +482,7 @@ fn report_unexpected_variant_res(
tcx: TyCtxt<'_>,
res: Res,
expr: Option<&hir::Expr<'_>>,
sub_pats: &[hir::Pat<'_>],
qpath: &hir::QPath<'_>,
span: Span,
err_code: ErrCode,
Expand Down Expand Up @@ -561,19 +562,35 @@ fn report_unexpected_variant_res(
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() {
Comment thread
Snxhit marked this conversation as resolved.
("use the struct variant pattern syntax".to_string(), " {}".to_string())
("use the struct variant pattern syntax", " {}".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
let msg = if fields.is_empty() {
"use struct variant pattern syntax"
} else {
"add the names to match a struct variant's fields"
};
let fields_sugg = fields
.iter()
.map(|field| format!("{}: _", field.ident(tcx)))
.enumerate()
.map(|(i, field)| {
let field_name = field.ident(tcx).to_string();

let pat_snippet = sub_pats
.get(i)
.and_then(|sub_pat| {
tcx.sess.source_map().span_to_snippet(sub_pat.span).ok()
})
.unwrap_or_else(|| "_".to_string());

if field_name == pat_snippet {
field_name
} else {
format!("{field_name}: {pat_snippet}")
}
})
.collect::<Vec<_>>()
.join(", ");
let sugg = format!(" {{ {} }}", fields);
let sugg = format!(" {{ {} }}", fields_sugg);
(msg, sugg)
};

Expand Down
20 changes: 18 additions & 2 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1585,7 +1585,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
let expected = "unit struct, unit variant or constant";
let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected);
let e = report_unexpected_variant_res(
tcx,
res,
None,
&[],
qpath,
span,
E0533,
expected,
);
return Err(e);
}
Res::SelfCtor(def_id) => {
Expand All @@ -1599,6 +1608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx,
res,
None,
&[],
qpath,
span,
E0533,
Expand Down Expand Up @@ -1761,7 +1771,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
let report_unexpected_res = |res: Res| {
let expected = "tuple struct or tuple variant";
let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected);
let sub_pats = match pat.kind {
hir::PatKind::TupleStruct(_, sub_pats, _) => sub_pats,
_ => &[],
};
let e = report_unexpected_variant_res(
tcx, res, None, sub_pats, qpath, pat.span, E0164, expected,
);
Err(e)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia
LL | MyEnum::Struct => "",
| ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant
|
help: the struct variant's field is being ignored
help: add the names to match a struct variant's fields
|
LL | MyEnum::Struct { s: _ } => "",
| ++++++++
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/parser/recover/recover-from-bad-variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ fn main() {
match x {
Enum::Foo(a, b) => {}
//~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
Enum::Foo(x, y) => {}
//~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
Enum::Foo(1 | 2, b @ 3) => {}
//~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
Enum::Foo(a) => {}
//~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
Enum::Foo(a, b, c) => {}
//~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
Enum::Bar { a, b } => {}
//~^ ERROR tuple variant `Enum::Bar` written as struct variant
}
Expand Down
56 changes: 52 additions & 4 deletions tests/ui/parser/recover/recover-from-bad-variant.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,63 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum
LL | Enum::Foo(a, b) => {}
| ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
help: the struct variant's fields are being ignored
help: add the names to match a struct variant's fields
|
LL - Enum::Foo(a, b) => {}
LL + Enum::Foo { a: _, b: _ } => {}
LL + Enum::Foo { a, b } => {}
|

error[E0769]: tuple variant `Enum::Bar` written as struct variant
error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
--> $DIR/recover-from-bad-variant.rs:12:9
|
LL | Enum::Foo(x, y) => {}
| ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
help: add the names to match a struct variant's fields
|
LL - Enum::Foo(x, y) => {}
LL + Enum::Foo { a: x, b: y } => {}
|

error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
--> $DIR/recover-from-bad-variant.rs:14:9
|
LL | Enum::Foo(1 | 2, b @ 3) => {}
| ^^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
help: add the names to match a struct variant's fields
|
LL - Enum::Foo(1 | 2, b @ 3) => {}
LL + Enum::Foo { a: 1 | 2, b: b @ 3 } => {}
|

error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
--> $DIR/recover-from-bad-variant.rs:16:9
|
LL | Enum::Foo(a) => {}
| ^^^^^^^^^^^^ not a tuple struct or tuple variant
|
help: add the names to match a struct variant's fields
|
LL - Enum::Foo(a) => {}
LL + Enum::Foo { a, b: _ } => {}
|

error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
--> $DIR/recover-from-bad-variant.rs:18:9
|
LL | Enum::Foo(a, b, c) => {}
| ^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
help: add the names to match a struct variant's fields
|
LL - Enum::Foo(a, b, c) => {}
LL + Enum::Foo { a, b } => {}
|

error[E0769]: tuple variant `Enum::Bar` written as struct variant
--> $DIR/recover-from-bad-variant.rs:20:9
|
LL | Enum::Bar { a, b } => {}
| ^^^^^^^^^^^^^^^^^^
|
Expand All @@ -39,7 +87,7 @@ LL - Enum::Bar { a, b } => {}
LL + Enum::Bar(a, b) => {}
|

error: aborting due to 3 previous errors
error: aborting due to 7 previous errors

Some errors have detailed explanations: E0164, E0769.
For more information about an error, try `rustc --explain E0164`.
2 changes: 1 addition & 1 deletion tests/ui/suggestions/issue-84700.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Farm
LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
| ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
help: the struct variant's field is being ignored
help: add the names to match a struct variant's fields
|
LL - FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(),
LL + FarmAnimal::Chicken { num_eggs: _ } => "cluck, cluck!".to_string(),
Expand Down
Loading