Skip to content

Commit

Permalink
Rollup merge of #99030 - rust-lang:notriddle/field-recovery, r=petroc…
Browse files Browse the repository at this point in the history
…henkov

diagnostics: error messages when struct literals fail to parse

If an expression is supplied where a field is expected, the parser can become convinced that it's a shorthand field syntax when it's not.

This PR addresses it by explicitly recording the permitted `:` token immediately after the identifier, and also adds a suggestion to insert the name of the field if it looks like a complex expression.

Fixes #98917
  • Loading branch information
Dylan-DPC authored Jul 13, 2022
2 parents 1e7d04b + 9fcb9c6 commit 980579a
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 10 deletions.
18 changes: 18 additions & 0 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3028,6 +3028,11 @@ impl<'a> Parser<'a> {
}
};

let is_shorthand = parsed_field.as_ref().map_or(false, |f| f.is_shorthand);
// A shorthand field can be turned into a full field with `:`.
// We should point this out.
self.check_or_expected(!is_shorthand, TokenType::Token(token::Colon));

match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) {
Ok(_) => {
if let Some(f) = parsed_field.or(recovery_field) {
Expand All @@ -3048,6 +3053,19 @@ impl<'a> Parser<'a> {
",",
Applicability::MachineApplicable,
);
} else if is_shorthand
&& (AssocOp::from_token(&self.token).is_some()
|| matches!(&self.token.kind, token::OpenDelim(_))
|| self.token.kind == token::Dot)
{
// Looks like they tried to write a shorthand, complex expression.
let ident = parsed_field.expect("is_shorthand implies Some").ident;
e.span_suggestion(
ident.span.shrink_to_lo(),
"try naming a field",
&format!("{ident}: "),
Applicability::HasPlaceholders,
);
}
}
if !recover {
Expand Down
7 changes: 4 additions & 3 deletions src/test/ui/parser/issues/issue-52496.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ error: float literals must have an integer part
LL | let _ = Foo { bar: .5, baz: 42 };
| ^^ help: must have an integer part: `0.5`

error: expected one of `,` or `}`, found `.`
error: expected one of `,`, `:`, or `}`, found `.`
--> $DIR/issue-52496.rs:8:22
|
LL | let _ = Foo { bar.into(), bat: -1, . };
| --- ^ expected one of `,` or `}`
| |
| --- - ^ expected one of `,`, `:`, or `}`
| | |
| | help: try naming a field: `bar:`
| while parsing this struct

error: expected identifier, found `.`
Expand Down
16 changes: 12 additions & 4 deletions src/test/ui/parser/issues/issue-62973.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,23 @@ LL |
LL |
| ^

error: expected one of `,` or `}`, found `{`
error: expected one of `,`, `:`, or `}`, found `{`
--> $DIR/issue-62973.rs:6:8
|
LL | fn p() { match s { v, E { [) {) }
| ^ - -^ expected one of `,` or `}`
| | | |
| | | help: `}` may belong here
| ^ - ^ expected one of `,`, `:`, or `}`
| | |
| | while parsing this struct
| unclosed delimiter
|
help: `}` may belong here
|
LL | fn p() { match s { v, E} { [) {) }
| +
help: try naming a field
|
LL | fn p() { match s { v, E: E { [) {) }
| ++

error: struct literals are not allowed here
--> $DIR/issue-62973.rs:6:16
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/parser/removed-syntax-with-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ fn main() {

let a = S { foo: (), bar: () };
let b = S { foo: (), with a };
//~^ ERROR expected one of `,` or `}`, found `a`
//~^ ERROR expected one of `,`, `:`, or `}`, found `a`
//~| ERROR missing field `bar` in initializer of `S`
}
4 changes: 2 additions & 2 deletions src/test/ui/parser/removed-syntax-with-2.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: expected one of `,` or `}`, found `a`
error: expected one of `,`, `:`, or `}`, found `a`
--> $DIR/removed-syntax-with-2.rs:8:31
|
LL | let b = S { foo: (), with a };
| - ^ expected one of `,` or `}`
| - ^ expected one of `,`, `:`, or `}`
| |
| while parsing this struct

Expand Down

0 comments on commit 980579a

Please sign in to comment.