From 58fee523cfe1e242cbf8776bb8513fb8325bc0ab Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 25 Mar 2020 06:57:00 +0100 Subject: [PATCH 1/4] is_union() instead of string comparsion --- src/librustc_typeck/check/pat.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 0d38fa98bd7f8..d3b1ea8778d65 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1020,7 +1020,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(adt, substs) => (substs, adt), _ => span_bug!(pat.span, "struct pattern is not an ADT"), }; - let kind_name = adt.variant_descr(); // Index the struct fields' types. let field_map = variant @@ -1074,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !inexistent_fields.is_empty() && !variant.recovered { self.error_inexistent_fields( - kind_name, + adt.variant_descr(), &inexistent_fields, &mut unmentioned_fields, variant, @@ -1088,13 +1087,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat.span, E0638, "`..` required with {} marked as non-exhaustive", - kind_name + adt.variant_descr() ) .emit(); } // Report an error if incorrect number of the fields were specified. - if kind_name == "union" { + if adt.is_union() { if fields.len() != 1 { tcx.sess .struct_span_err(pat.span, "union patterns should have exactly one field") From bd156846fa84fde77cc801ea3b1f4d5750db94a4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 25 Mar 2020 08:35:17 +0100 Subject: [PATCH 2/4] improve non-exhaustive struct pat error --- src/librustc_typeck/check/pat.rs | 32 ++++++++++++++----- .../ui/rfc-2008-non-exhaustive/struct.stderr | 15 +++++++++ .../ui/rfc-2008-non-exhaustive/variant.stderr | 10 ++++++ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index d3b1ea8778d65..ea04454a356de 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1082,14 +1082,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Require `..` if struct has non_exhaustive attribute. if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { - struct_span_err!( - tcx.sess, - pat.span, - E0638, - "`..` required with {} marked as non-exhaustive", - adt.variant_descr() - ) - .emit(); + self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty()); } // Report an error if incorrect number of the fields were specified. @@ -1108,6 +1101,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_field_errors } + fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) { + let sess = self.tcx.sess; + let sm = sess.source_map(); + let sp_brace = sm.end_point(pat.span); + let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi())); + let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" }; + + let mut err = struct_span_err!( + sess, + pat.span, + E0638, + "`..` required with {} marked as non-exhaustive", + descr + ); + err.span_suggestion_verbose( + sp_comma, + "add `..` at the end of the field list", + sugg.to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } + fn error_field_already_bound(&self, span: Span, ident: ast::Ident, other_field: Span) { struct_span_err!( self.tcx.sess, diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 4e91e7bff34b2..b1351e6fb9c4b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -62,18 +62,33 @@ error[E0638]: `..` required with struct marked as non-exhaustive | LL | let NormalStruct { first_field, second_field } = ns; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | let NormalStruct { first_field, second_field , .. } = ns; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:26:9 | LL | let TupleStruct { 0: first_field, 1: second_field } = ts; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:35:9 | LL | let UnitStruct { } = us; | ^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | let UnitStruct { .. } = us; + | ^^^^ error: aborting due to 9 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index ae4f6aff11a02..94432ce29d59e 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -69,12 +69,22 @@ error[E0638]: `..` required with variant marked as non-exhaustive | LL | NonExhaustiveVariants::Struct { field } => "" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | NonExhaustiveVariants::Struct { field , .. } => "" + | ^^^^^^ error[E0638]: `..` required with variant marked as non-exhaustive --> $DIR/variant.rs:30:12 | LL | if let NonExhaustiveVariants::Struct { field } = variant_struct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct { + | ^^^^^^ error: aborting due to 8 previous errors From bd3482632e71681aade51ac1e97730eb907c7249 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 25 Mar 2020 09:32:39 +0100 Subject: [PATCH 3/4] simplify check_pat_tuple_struct --- src/librustc_typeck/check/pat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index ea04454a356de..c235a0bb4ea42 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -835,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { on_error(); return tcx.types.err; } - Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _) => { + Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { report_unexpected_res(res); return tcx.types.err; } From da10963357f91eb1aa8100f224d5ce19a0d4424b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 26 Mar 2020 02:29:42 +0100 Subject: [PATCH 4/4] typeck/pat: address review comments --- src/librustc_typeck/check/pat.rs | 2 +- src/test/ui/rfc-2008-non-exhaustive/struct.stderr | 6 +++--- src/test/ui/rfc-2008-non-exhaustive/variant.stderr | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index c235a0bb4ea42..0c4a05e61814d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1117,7 +1117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_suggestion_verbose( sp_comma, - "add `..` at the end of the field list", + "add `..` at the end of the field list to ignore all other fields", sugg.to_string(), Applicability::MachineApplicable, ); diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index b1351e6fb9c4b..3bc38830537cf 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -63,7 +63,7 @@ error[E0638]: `..` required with struct marked as non-exhaustive LL | let NormalStruct { first_field, second_field } = ns; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add `..` at the end of the field list +help: add `..` at the end of the field list to ignore all other fields | LL | let NormalStruct { first_field, second_field , .. } = ns; | ^^^^^^ @@ -74,7 +74,7 @@ error[E0638]: `..` required with struct marked as non-exhaustive LL | let TupleStruct { 0: first_field, 1: second_field } = ts; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add `..` at the end of the field list +help: add `..` at the end of the field list to ignore all other fields | LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts; | ^^^^^^ @@ -85,7 +85,7 @@ error[E0638]: `..` required with struct marked as non-exhaustive LL | let UnitStruct { } = us; | ^^^^^^^^^^^^^^ | -help: add `..` at the end of the field list +help: add `..` at the end of the field list to ignore all other fields | LL | let UnitStruct { .. } = us; | ^^^^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index 94432ce29d59e..fbdbb0c9930a6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -70,7 +70,7 @@ error[E0638]: `..` required with variant marked as non-exhaustive LL | NonExhaustiveVariants::Struct { field } => "" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add `..` at the end of the field list +help: add `..` at the end of the field list to ignore all other fields | LL | NonExhaustiveVariants::Struct { field , .. } => "" | ^^^^^^ @@ -81,7 +81,7 @@ error[E0638]: `..` required with variant marked as non-exhaustive LL | if let NonExhaustiveVariants::Struct { field } = variant_struct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add `..` at the end of the field list +help: add `..` at the end of the field list to ignore all other fields | LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct { | ^^^^^^