about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-09-15 00:17:13 +0000
committerbors <bors@rust-lang.org>2020-09-15 00:17:13 +0000
commit255ceeb5ff9875b7f525aa101c8adc155f3e0ef8 (patch)
tree37a3e1a5cd0ff5cb87c601e75234af92376a4303
parent9b4154193e8471f36b1a9e781f1ef7d492fc6a6c (diff)
parent21f8326cec03848368e02936a032103aa24cf6d2 (diff)
downloadrust-255ceeb5ff9875b7f525aa101c8adc155f3e0ef8.tar.gz
rust-255ceeb5ff9875b7f525aa101c8adc155f3e0ef8.zip
Auto merge of #76612 - estebank:pat-missing-fields-suggestion, r=davidtwco
Provide suggestion for missing fields in patterns
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs58
-rw-r--r--src/test/ui/error-codes/E0027-teach.rs15
-rw-r--r--src/test/ui/error-codes/E0027-teach.stderr11
-rw-r--r--src/test/ui/error-codes/E0027.rs6
-rw-r--r--src/test/ui/error-codes/E0027.stderr26
-rw-r--r--src/test/ui/structs/struct-field-cfg.stderr9
-rw-r--r--src/test/ui/structs/struct-pat-derived-error.stderr9
7 files changed, 96 insertions, 38 deletions
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 171d5ee4ff2..6be2fdf9f19 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -1150,7 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if no_accessible_unmentioned_fields {
                 unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
             } else {
-                unmentioned_err = Some(self.error_unmentioned_fields(pat, &unmentioned_fields));
+                unmentioned_err =
+                    Some(self.error_unmentioned_fields(pat, &unmentioned_fields, &fields));
             }
         }
         match (inexistent_fields_err, unmentioned_err) {
@@ -1405,6 +1406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         pat: &Pat<'_>,
         unmentioned_fields: &[(&ty::FieldDef, Ident)],
+        fields: &'tcx [hir::FieldPat<'tcx>],
     ) -> DiagnosticBuilder<'tcx> {
         let field_names = if unmentioned_fields.len() == 1 {
             format!("field `{}`", unmentioned_fields[0].1)
@@ -1424,14 +1426,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             field_names
         );
         err.span_label(pat.span, format!("missing {}", field_names));
-        if self.tcx.sess.teach(&err.get_code().unwrap()) {
-            err.note(
-                "This error indicates that a pattern for a struct fails to specify a \
-                 sub-pattern for every one of the struct's fields. Ensure that each field \
-                 from the struct's definition is mentioned in the pattern, or use `..` to \
-                 ignore unwanted fields.",
-            );
-        }
+        let len = unmentioned_fields.len();
+        let (prefix, postfix, sp) = match fields {
+            [] => match &pat.kind {
+                PatKind::Struct(path, [], false) => {
+                    (" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi()))
+                }
+                _ => return err,
+            },
+            [.., field] => (
+                match pat.kind {
+                    PatKind::Struct(_, [_, ..], _) => ", ",
+                    _ => "",
+                },
+                "",
+                field.span.shrink_to_hi(),
+            ),
+        };
+        err.span_suggestion(
+            sp,
+            &format!(
+                "include the missing field{} in the pattern",
+                if len == 1 { "" } else { "s" },
+            ),
+            format!(
+                "{}{}{}",
+                prefix,
+                unmentioned_fields
+                    .iter()
+                    .map(|(_, name)| name.to_string())
+                    .collect::<Vec<_>>()
+                    .join(", "),
+                postfix,
+            ),
+            Applicability::MachineApplicable,
+        );
+        err.span_suggestion(
+            sp,
+            &format!(
+                "if you don't care about {} missing field{}, you can explicitely ignore {}",
+                if len == 1 { "this" } else { "these" },
+                if len == 1 { "" } else { "s" },
+                if len == 1 { "it" } else { "them" },
+            ),
+            format!("{}..{}", prefix, postfix),
+            Applicability::MachineApplicable,
+        );
         err
     }
 
diff --git a/src/test/ui/error-codes/E0027-teach.rs b/src/test/ui/error-codes/E0027-teach.rs
deleted file mode 100644
index 11402f01484..00000000000
--- a/src/test/ui/error-codes/E0027-teach.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// compile-flags: -Z teach
-
-struct Dog {
-    name: String,
-    age: u32,
-}
-
-fn main() {
-    let d = Dog { name: "Rusty".to_string(), age: 8 };
-
-    match d {
-        Dog { age: x } => {}
-        //~^ ERROR pattern does not mention field `name`
-    }
-}
diff --git a/src/test/ui/error-codes/E0027-teach.stderr b/src/test/ui/error-codes/E0027-teach.stderr
deleted file mode 100644
index aa4cb9d4d18..00000000000
--- a/src/test/ui/error-codes/E0027-teach.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0027]: pattern does not mention field `name`
-  --> $DIR/E0027-teach.rs:12:9
-   |
-LL |         Dog { age: x } => {}
-   |         ^^^^^^^^^^^^^^ missing field `name`
-   |
-   = note: This error indicates that a pattern for a struct fails to specify a sub-pattern for every one of the struct's fields. Ensure that each field from the struct's definition is mentioned in the pattern, or use `..` to ignore unwanted fields.
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0027`.
diff --git a/src/test/ui/error-codes/E0027.rs b/src/test/ui/error-codes/E0027.rs
index b8c6a2b7fcd..8d08e178934 100644
--- a/src/test/ui/error-codes/E0027.rs
+++ b/src/test/ui/error-codes/E0027.rs
@@ -7,7 +7,9 @@ fn main() {
     let d = Dog { name: "Rusty".to_string(), age: 8 };
 
     match d {
-        Dog { age: x } => {}
-        //~^ ERROR pattern does not mention field `name`
+        Dog { age: x } => {} //~ ERROR pattern does not mention field `name`
+    }
+    match d {
+        Dog {} => {} //~ ERROR pattern does not mention fields `name`, `age`
     }
 }
diff --git a/src/test/ui/error-codes/E0027.stderr b/src/test/ui/error-codes/E0027.stderr
index 4f17bba6477..c09f1ff1f2a 100644
--- a/src/test/ui/error-codes/E0027.stderr
+++ b/src/test/ui/error-codes/E0027.stderr
@@ -3,7 +3,31 @@ error[E0027]: pattern does not mention field `name`
    |
 LL |         Dog { age: x } => {}
    |         ^^^^^^^^^^^^^^ missing field `name`
+   |
+help: include the missing field in the pattern
+   |
+LL |         Dog { age: x, name } => {}
+   |                     ^^^^^^
+help: if you don't care about this missing field, you can explicitely ignore it
+   |
+LL |         Dog { age: x, .. } => {}
+   |                     ^^^^
+
+error[E0027]: pattern does not mention fields `name`, `age`
+  --> $DIR/E0027.rs:13:9
+   |
+LL |         Dog {} => {}
+   |         ^^^^^^ missing fields `name`, `age`
+   |
+help: include the missing fields in the pattern
+   |
+LL |         Dog { name, age } => {}
+   |             ^^^^^^^^^^^^^
+help: if you don't care about these missing fields, you can explicitely ignore them
+   |
+LL |         Dog { .. } => {}
+   |             ^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0027`.
diff --git a/src/test/ui/structs/struct-field-cfg.stderr b/src/test/ui/structs/struct-field-cfg.stderr
index 29bad31ef96..b913b929079 100644
--- a/src/test/ui/structs/struct-field-cfg.stderr
+++ b/src/test/ui/structs/struct-field-cfg.stderr
@@ -17,6 +17,15 @@ error[E0027]: pattern does not mention field `present`
    |
 LL |     let Foo { #[cfg(any())] present: () } = foo;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `present`
+   |
+help: include the missing field in the pattern
+   |
+LL |     let Foo { present } = foo;
+   |             ^^^^^^^^^^^
+help: if you don't care about this missing field, you can explicitely ignore it
+   |
+LL |     let Foo { .. } = foo;
+   |             ^^^^^^
 
 error[E0026]: struct `Foo` does not have a field named `absent`
   --> $DIR/struct-field-cfg.rs:16:42
diff --git a/src/test/ui/structs/struct-pat-derived-error.stderr b/src/test/ui/structs/struct-pat-derived-error.stderr
index 6526ef58a44..f3e9ce76f1e 100644
--- a/src/test/ui/structs/struct-pat-derived-error.stderr
+++ b/src/test/ui/structs/struct-pat-derived-error.stderr
@@ -15,6 +15,15 @@ error[E0027]: pattern does not mention fields `b`, `c`
    |
 LL |         let A { x, y } = self.d;
    |             ^^^^^^^^^^ missing fields `b`, `c`
+   |
+help: include the missing fields in the pattern
+   |
+LL |         let A { x, y, b, c } = self.d;
+   |                     ^^^^^^
+help: if you don't care about these missing fields, you can explicitely ignore them
+   |
+LL |         let A { x, y, .. } = self.d;
+   |                     ^^^^
 
 error: aborting due to 3 previous errors