about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-03-26 03:21:30 +0100
committerGitHub <noreply@github.com>2020-03-26 03:21:30 +0100
commitca7dfb1cfad71598992af03f9582200531446ee6 (patch)
tree7d9d818d1d15a6e4f46183b49c823d7d947195e0
parentef01fe6bbc0f675bb2795fb86113ae5ae0c92d3b (diff)
parentda10963357f91eb1aa8100f224d5ce19a0d4424b (diff)
downloadrust-ca7dfb1cfad71598992af03f9582200531446ee6.tar.gz
rust-ca7dfb1cfad71598992af03f9582200531446ee6.zip
Rollup merge of #70386 - Centril:patty, r=estebank
typeck: minor pattern typing improvements

r? @estebank
-rw-r--r--src/librustc_typeck/check/pat.rs39
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.stderr15
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/variant.stderr10
3 files changed, 52 insertions, 12 deletions
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 0d38fa98bd7..0c4a05e6181 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;
             }
@@ -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,
@@ -1083,18 +1082,11 @@ 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",
-                kind_name
-            )
-            .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.
-        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")
@@ -1109,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 to ignore all other fields",
+            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 4e91e7bff34..3bc38830537 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 to ignore all other fields
+   |
+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 to ignore all other fields
+   |
+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 to ignore all other fields
+   |
+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 ae4f6aff11a..fbdbb0c9930 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 to ignore all other fields
+   |
+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 to ignore all other fields
+   |
+LL |     if let NonExhaustiveVariants::Struct { field , .. } = variant_struct {
+   |                                                  ^^^^^^
 
 error: aborting due to 8 previous errors