Skip to content

Commit 8f47954

Browse files
authored
Rollup merge of #106919 - compiler-errors:underscore-typo-in-field-pat, r=jackh726
Recover `_` as `..` in field pattern
2 parents 97872b7 + 9dd5d3e commit 8f47954

File tree

8 files changed

+42
-32
lines changed

8 files changed

+42
-32
lines changed

compiler/rustc_error_messages/locales/en-US/parse.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -535,8 +535,8 @@ parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` ar
535535
536536
parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
537537
538-
parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `...`
539-
.suggestion = to omit remaining fields, use one fewer `.`
538+
parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
539+
.suggestion = to omit remaining fields, use `..`
540540
541541
parse_expected_comma_after_pattern_field = expected `,`
542542

compiler/rustc_parse/src/errors.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::borrow::Cow;
2+
13
use rustc_ast::token::Token;
24
use rustc_ast::{Path, Visibility};
35
use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
@@ -1802,8 +1804,9 @@ pub(crate) struct EnumPatternInsteadOfIdentifier {
18021804
#[diag(parse_dot_dot_dot_for_remaining_fields)]
18031805
pub(crate) struct DotDotDotForRemainingFields {
18041806
#[primary_span]
1805-
#[suggestion(code = "..", applicability = "machine-applicable")]
1807+
#[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")]
18061808
pub span: Span,
1809+
pub token_str: Cow<'static, str>,
18071810
}
18081811

18091812
#[derive(Diagnostic)]

compiler/rustc_parse/src/parser/pat.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -962,12 +962,15 @@ impl<'a> Parser<'a> {
962962
}
963963
ate_comma = false;
964964

965-
if self.check(&token::DotDot) || self.token == token::DotDotDot {
965+
if self.check(&token::DotDot)
966+
|| self.check_noexpect(&token::DotDotDot)
967+
|| self.check_keyword(kw::Underscore)
968+
{
966969
etc = true;
967970
let mut etc_sp = self.token.span;
968971

969-
self.recover_one_fewer_dotdot();
970-
self.bump(); // `..` || `...`
972+
self.recover_bad_dot_dot();
973+
self.bump(); // `..` || `...` || `_`
971974

972975
if self.token == token::CloseDelim(Delimiter::Brace) {
973976
etc_span = Some(etc_sp);
@@ -1060,14 +1063,15 @@ impl<'a> Parser<'a> {
10601063
Ok((fields, etc))
10611064
}
10621065

1063-
/// Recover on `...` as if it were `..` to avoid further errors.
1066+
/// Recover on `...` or `_` as if it were `..` to avoid further errors.
10641067
/// See issue #46718.
1065-
fn recover_one_fewer_dotdot(&self) {
1066-
if self.token != token::DotDotDot {
1068+
fn recover_bad_dot_dot(&self) {
1069+
if self.token == token::DotDot {
10671070
return;
10681071
}
10691072

1070-
self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span });
1073+
let token_str = pprust::token_to_string(&self.token);
1074+
self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str });
10711075
}
10721076

10731077
fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {

tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ error: expected field pattern, found `...`
22
--> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55
33
|
44
LL | PersonalityInventory { expressivity: exp, ... } => exp
5-
| ^^^ help: to omit remaining fields, use one fewer `.`: `..`
5+
| ^^^
6+
|
7+
help: to omit remaining fields, use `..`
8+
|
9+
LL | PersonalityInventory { expressivity: exp, .. } => exp
10+
| ~~
611

712
error: aborting due to previous error
813

tests/ui/parser/issue-102806.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ error: expected field pattern, found `...`
3232
--> $DIR/issue-102806.rs:21:22
3333
|
3434
LL | let V3 { z: val, ... } = v;
35-
| ^^^ help: to omit remaining fields, use one fewer `.`: `..`
35+
| ^^^
36+
|
37+
help: to omit remaining fields, use `..`
38+
|
39+
LL | let V3 { z: val, .. } = v;
40+
| ~~
3641

3742
error[E0063]: missing fields `x` and `y` in initializer of `V3`
3843
--> $DIR/issue-102806.rs:17:13

tests/ui/parser/issues/issue-63135.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ error: expected field pattern, found `...`
2020
--> $DIR/issue-63135.rs:3:8
2121
|
2222
LL | fn i(n{...,f #
23-
| ^^^ help: to omit remaining fields, use one fewer `.`: `..`
23+
| ^^^
24+
|
25+
help: to omit remaining fields, use `..`
26+
|
27+
LL | fn i(n{..,f #
28+
| ~~
2429

2530
error: expected `}`, found `,`
2631
--> $DIR/issue-63135.rs:3:11

tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,5 @@ fn main() {
77
let foo = Some(Foo::Other);
88

99
if let Some(Foo::Bar {_}) = foo {}
10-
//~^ ERROR expected identifier, found reserved identifier `_`
11-
//~| ERROR pattern does not mention field `bar` [E0027]
10+
//~^ ERROR expected field pattern, found `_`
1211
}
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
1-
error: expected identifier, found reserved identifier `_`
1+
error: expected field pattern, found `_`
22
--> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27
33
|
44
LL | if let Some(Foo::Bar {_}) = foo {}
5-
| ^ expected identifier, found reserved identifier
6-
7-
error[E0027]: pattern does not mention field `bar`
8-
--> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17
9-
|
10-
LL | if let Some(Foo::Bar {_}) = foo {}
11-
| ^^^^^^^^^^^^ missing field `bar`
12-
|
13-
help: include the missing field in the pattern
5+
| ^
146
|
15-
LL | if let Some(Foo::Bar {_, bar }) = foo {}
16-
| ~~~~~~~
17-
help: if you don't care about this missing field, you can explicitly ignore it
7+
help: to omit remaining fields, use `..`
188
|
19-
LL | if let Some(Foo::Bar {_, .. }) = foo {}
20-
| ~~~~~~
9+
LL | if let Some(Foo::Bar {..}) = foo {}
10+
| ~~
2111

22-
error: aborting due to 2 previous errors
12+
error: aborting due to previous error
2313

24-
For more information about this error, try `rustc --explain E0027`.

0 commit comments

Comments
 (0)