Skip to content

Commit

Permalink
Rollup merge of rust-lang#103012 - chenyukang:fix-102806, r=davidtwco…
Browse files Browse the repository at this point in the history
…,compiler-errors

Suggest use .. to fill in the rest of the fields of Struct

Fixes rust-lang#102806
  • Loading branch information
matthiaskrgr authored Nov 6, 2022
2 parents e6fead4 + 28d82dd commit 2e08d30
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 4 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/parser.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ parser_missing_semicolon_before_array = expected `;`, found `[`
parser_invalid_block_macro_segment = cannot use a `block` macro fragment here
.label = the `block` fragment is within this context
parser_expect_dotdot_not_dotdotdot = expected `..`, found `...`
.suggestion = use `..` to fill in the rest of the fields
parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition
.add_then_block = add a block here
.condition_possibly_unfinished = this binary operation is possibly unfinished
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ pub(crate) struct MissingSemicolonBeforeArray {
pub semicolon: Span,
}

#[derive(Diagnostic)]
#[diag(parser_expect_dotdot_not_dotdotdot)]
pub(crate) struct MissingDotDot {
#[primary_span]
pub token_span: Span,
#[suggestion(applicability = "maybe-incorrect", code = "..", style = "verbose")]
pub sugg_span: Span,
}

#[derive(Diagnostic)]
#[diag(parser_invalid_block_macro_segment)]
pub(crate) struct InvalidBlockMacroSegment {
Expand Down
20 changes: 16 additions & 4 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ use crate::errors::{
InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall,
NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported,
OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub,
OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
Expand Down Expand Up @@ -2880,7 +2880,7 @@ impl<'a> Parser<'a> {
};

while self.token != token::CloseDelim(close_delim) {
if self.eat(&token::DotDot) {
if self.eat(&token::DotDot) || self.recover_struct_field_dots(close_delim) {
let exp_span = self.prev_token.span;
// We permit `.. }` on the left-hand side of a destructuring assignment.
if self.check(&token::CloseDelim(close_delim)) {
Expand Down Expand Up @@ -3027,6 +3027,18 @@ impl<'a> Parser<'a> {
self.recover_stmt();
}

fn recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool {
if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim))
&& self.eat(&token::DotDotDot)
{
// recover from typo of `...`, suggest `..`
let span = self.prev_token.span;
self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span });
return true;
}
false
}

/// Parses `ident (COLON expr)?`.
fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
let attrs = self.parse_outer_attributes()?;
Expand Down
25 changes: 25 additions & 0 deletions src/test/ui/parser/issue-102806.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#![allow(dead_code)]

#[derive(Default)]
struct V3 {
x: f32,
y: f32,
z: f32,
}

fn pz(v: V3) {
let _ = V3 { z: 0.0, ...v};
//~^ ERROR expected `..`

let _ = V3 { z: 0.0, ...Default::default() };
//~^ ERROR expected `..`

let _ = V3 { z: 0.0, ... };
//~^ expected identifier
//~| ERROR missing fields `x` and `y` in initializer of `V3`

let V3 { z: val, ... } = v;
//~^ ERROR expected field pattern
}

fn main() {}
45 changes: 45 additions & 0 deletions src/test/ui/parser/issue-102806.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
error: expected `..`, found `...`
--> $DIR/issue-102806.rs:11:26
|
LL | let _ = V3 { z: 0.0, ...v};
| ^^^
|
help: use `..` to fill in the rest of the fields
|
LL | let _ = V3 { z: 0.0, ..v};
| ~~

error: expected `..`, found `...`
--> $DIR/issue-102806.rs:14:26
|
LL | let _ = V3 { z: 0.0, ...Default::default() };
| ^^^
|
help: use `..` to fill in the rest of the fields
|
LL | let _ = V3 { z: 0.0, ..Default::default() };
| ~~

error: expected identifier, found `...`
--> $DIR/issue-102806.rs:17:26
|
LL | let _ = V3 { z: 0.0, ... };
| -- ^^^ expected identifier
| |
| while parsing this struct

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 `.`: `..`

error[E0063]: missing fields `x` and `y` in initializer of `V3`
--> $DIR/issue-102806.rs:17:13
|
LL | let _ = V3 { z: 0.0, ... };
| ^^ missing `x` and `y`

error: aborting due to 5 previous errors

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

0 comments on commit 2e08d30

Please sign in to comment.