about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-01-15 21:31:04 +0000
committerMichael Goulet <michael@errs.io>2023-02-02 06:10:02 +0000
commit9dd5d3e8e421193be34fa822ab485de115174421 (patch)
tree674d0f71601cd8e5a4e5dd4b5ccaa656534c1cba
parent131f0c6df6777800aa884963bdba0739299cd31f (diff)
downloadrust-9dd5d3e8e421193be34fa822ab485de115174421.tar.gz
rust-9dd5d3e8e421193be34fa822ab485de115174421.zip
Recover _ as .. in field pattern
-rw-r--r--compiler/rustc_error_messages/locales/en-US/parse.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs5
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs18
-rw-r--r--tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr7
-rw-r--r--tests/ui/parser/issue-102806.stderr7
-rw-r--r--tests/ui/parser/issues/issue-63135.stderr7
-rw-r--r--tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs3
-rw-r--r--tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr23
8 files changed, 42 insertions, 32 deletions
diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl
index 21cf4bd789c..6752f05b044 100644
--- a/compiler/rustc_error_messages/locales/en-US/parse.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl
@@ -535,8 +535,8 @@ parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` ar
 
 parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
 
-parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...`
-    .suggestion = to omit remaining fields, use one fewer `.`
+parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
+    .suggestion = to omit remaining fields, use `..`
 
 parse_expected_comma_after_pattern_field = expected `,`
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 145611923ff..20da8ce5b6e 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1,3 +1,5 @@
+use std::borrow::Cow;
+
 use rustc_ast::token::Token;
 use rustc_ast::{Path, Visibility};
 use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
@@ -1802,8 +1804,9 @@ pub(crate) struct EnumPatternInsteadOfIdentifier {
 #[diag(parse_dot_dot_dot_for_remaining_fields)]
 pub(crate) struct DotDotDotForRemainingFields {
     #[primary_span]
-    #[suggestion(code = "..", applicability = "machine-applicable")]
+    #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")]
     pub span: Span,
+    pub token_str: Cow<'static, str>,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 88c75fd81e7..c982d7f99a9 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -963,12 +963,15 @@ impl<'a> Parser<'a> {
             }
             ate_comma = false;
 
-            if self.check(&token::DotDot) || self.token == token::DotDotDot {
+            if self.check(&token::DotDot)
+                || self.check_noexpect(&token::DotDotDot)
+                || self.check_keyword(kw::Underscore)
+            {
                 etc = true;
                 let mut etc_sp = self.token.span;
 
-                self.recover_one_fewer_dotdot();
-                self.bump(); // `..` || `...`
+                self.recover_bad_dot_dot();
+                self.bump(); // `..` || `...` || `_`
 
                 if self.token == token::CloseDelim(Delimiter::Brace) {
                     etc_span = Some(etc_sp);
@@ -1061,14 +1064,15 @@ impl<'a> Parser<'a> {
         Ok((fields, etc))
     }
 
-    /// Recover on `...` as if it were `..` to avoid further errors.
+    /// Recover on `...` or `_` as if it were `..` to avoid further errors.
     /// See issue #46718.
-    fn recover_one_fewer_dotdot(&self) {
-        if self.token != token::DotDotDot {
+    fn recover_bad_dot_dot(&self) {
+        if self.token == token::DotDot {
             return;
         }
 
-        self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span });
+        let token_str = pprust::token_to_string(&self.token);
+        self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str });
     }
 
     fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
diff --git a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
index bfe1ed32859..589b2c37849 100644
--- a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
+++ b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
@@ -2,7 +2,12 @@ error: expected field pattern, found `...`
   --> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55
    |
 LL |             PersonalityInventory { expressivity: exp, ... } => exp
-   |                                                       ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+   |                                                       ^^^
+   |
+help: to omit remaining fields, use `..`
+   |
+LL |             PersonalityInventory { expressivity: exp, .. } => exp
+   |                                                       ~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/parser/issue-102806.stderr b/tests/ui/parser/issue-102806.stderr
index 6872b8bc0af..ba8174a823b 100644
--- a/tests/ui/parser/issue-102806.stderr
+++ b/tests/ui/parser/issue-102806.stderr
@@ -32,7 +32,12 @@ error: expected field pattern, found `...`
   --> $DIR/issue-102806.rs:21:22
    |
 LL |     let V3 { z: val, ... } = v;
-   |                      ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+   |                      ^^^
+   |
+help: to omit remaining fields, use `..`
+   |
+LL |     let V3 { z: val, .. } = v;
+   |                      ~~
 
 error[E0063]: missing fields `x` and `y` in initializer of `V3`
   --> $DIR/issue-102806.rs:17:13
diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr
index 80e9ac5bedf..e0dc356d546 100644
--- a/tests/ui/parser/issues/issue-63135.stderr
+++ b/tests/ui/parser/issues/issue-63135.stderr
@@ -20,7 +20,12 @@ error: expected field pattern, found `...`
   --> $DIR/issue-63135.rs:3:8
    |
 LL | fn i(n{...,f #
-   |        ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+   |        ^^^
+   |
+help: to omit remaining fields, use `..`
+   |
+LL | fn i(n{..,f #
+   |        ~~
 
 error: expected `}`, found `,`
   --> $DIR/issue-63135.rs:3:11
diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs
index c30b8a1e1f1..b569993c614 100644
--- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs
+++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs
@@ -7,6 +7,5 @@ fn main() {
     let foo = Some(Foo::Other);
 
     if let Some(Foo::Bar {_}) = foo {}
-    //~^ ERROR expected identifier, found reserved identifier `_`
-    //~| ERROR pattern does not mention field `bar` [E0027]
+    //~^ ERROR expected field pattern, found `_`
 }
diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr
index 16f751444a5..2f3a150e5cb 100644
--- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr
+++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr
@@ -1,24 +1,13 @@
-error: expected identifier, found reserved identifier `_`
+error: expected field pattern, found `_`
   --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27
    |
 LL |     if let Some(Foo::Bar {_}) = foo {}
-   |                           ^ expected identifier, found reserved identifier
-
-error[E0027]: pattern does not mention field `bar`
-  --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17
-   |
-LL |     if let Some(Foo::Bar {_}) = foo {}
-   |                 ^^^^^^^^^^^^ missing field `bar`
-   |
-help: include the missing field in the pattern
+   |                           ^
    |
-LL |     if let Some(Foo::Bar {_, bar }) = foo {}
-   |                            ~~~~~~~
-help: if you don't care about this missing field, you can explicitly ignore it
+help: to omit remaining fields, use `..`
    |
-LL |     if let Some(Foo::Bar {_, .. }) = foo {}
-   |                            ~~~~~~
+LL |     if let Some(Foo::Bar {..}) = foo {}
+   |                           ~~
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0027`.