Skip to content

Commit 58f5d57

Browse files
authored
Rollup merge of #103012 - chenyukang:fix-102806, r=davidtwco,compiler-errors
Suggest use .. to fill in the rest of the fields of Struct Fixes #102806
2 parents a4ab2e0 + 28d82dd commit 58f5d57

File tree

5 files changed

+98
-4
lines changed

5 files changed

+98
-4
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ parser_missing_semicolon_before_array = expected `;`, found `[`
112112
parser_invalid_block_macro_segment = cannot use a `block` macro fragment here
113113
.label = the `block` fragment is within this context
114114
115+
parser_expect_dotdot_not_dotdotdot = expected `..`, found `...`
116+
.suggestion = use `..` to fill in the rest of the fields
117+
115118
parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition
116119
.add_then_block = add a block here
117120
.condition_possibly_unfinished = this binary operation is possibly unfinished

compiler/rustc_parse/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,15 @@ pub(crate) struct MissingSemicolonBeforeArray {
368368
pub semicolon: Span,
369369
}
370370

371+
#[derive(Diagnostic)]
372+
#[diag(parser_expect_dotdot_not_dotdotdot)]
373+
pub(crate) struct MissingDotDot {
374+
#[primary_span]
375+
pub token_span: Span,
376+
#[suggestion(applicability = "maybe-incorrect", code = "..", style = "verbose")]
377+
pub sugg_span: Span,
378+
}
379+
371380
#[derive(Diagnostic)]
372381
#[diag(parser_invalid_block_macro_segment)]
373382
pub(crate) struct InvalidBlockMacroSegment {

compiler/rustc_parse/src/parser/expr.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ use crate::errors::{
2020
InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
2121
LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
2222
MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
23-
MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall,
24-
NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported,
25-
OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
23+
MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
24+
NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub,
25+
OctalFloatLiteralNotSupported, OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
2626
RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
2727
StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
2828
UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
@@ -2880,7 +2880,7 @@ impl<'a> Parser<'a> {
28802880
};
28812881

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

3030+
fn recover_struct_field_dots(&mut self, close_delim: Delimiter) -> bool {
3031+
if !self.look_ahead(1, |t| *t == token::CloseDelim(close_delim))
3032+
&& self.eat(&token::DotDotDot)
3033+
{
3034+
// recover from typo of `...`, suggest `..`
3035+
let span = self.prev_token.span;
3036+
self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span });
3037+
return true;
3038+
}
3039+
false
3040+
}
3041+
30303042
/// Parses `ident (COLON expr)?`.
30313043
fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
30323044
let attrs = self.parse_outer_attributes()?;

src/test/ui/parser/issue-102806.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![allow(dead_code)]
2+
3+
#[derive(Default)]
4+
struct V3 {
5+
x: f32,
6+
y: f32,
7+
z: f32,
8+
}
9+
10+
fn pz(v: V3) {
11+
let _ = V3 { z: 0.0, ...v};
12+
//~^ ERROR expected `..`
13+
14+
let _ = V3 { z: 0.0, ...Default::default() };
15+
//~^ ERROR expected `..`
16+
17+
let _ = V3 { z: 0.0, ... };
18+
//~^ expected identifier
19+
//~| ERROR missing fields `x` and `y` in initializer of `V3`
20+
21+
let V3 { z: val, ... } = v;
22+
//~^ ERROR expected field pattern
23+
}
24+
25+
fn main() {}
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
error: expected `..`, found `...`
2+
--> $DIR/issue-102806.rs:11:26
3+
|
4+
LL | let _ = V3 { z: 0.0, ...v};
5+
| ^^^
6+
|
7+
help: use `..` to fill in the rest of the fields
8+
|
9+
LL | let _ = V3 { z: 0.0, ..v};
10+
| ~~
11+
12+
error: expected `..`, found `...`
13+
--> $DIR/issue-102806.rs:14:26
14+
|
15+
LL | let _ = V3 { z: 0.0, ...Default::default() };
16+
| ^^^
17+
|
18+
help: use `..` to fill in the rest of the fields
19+
|
20+
LL | let _ = V3 { z: 0.0, ..Default::default() };
21+
| ~~
22+
23+
error: expected identifier, found `...`
24+
--> $DIR/issue-102806.rs:17:26
25+
|
26+
LL | let _ = V3 { z: 0.0, ... };
27+
| -- ^^^ expected identifier
28+
| |
29+
| while parsing this struct
30+
31+
error: expected field pattern, found `...`
32+
--> $DIR/issue-102806.rs:21:22
33+
|
34+
LL | let V3 { z: val, ... } = v;
35+
| ^^^ help: to omit remaining fields, use one fewer `.`: `..`
36+
37+
error[E0063]: missing fields `x` and `y` in initializer of `V3`
38+
--> $DIR/issue-102806.rs:17:13
39+
|
40+
LL | let _ = V3 { z: 0.0, ... };
41+
| ^^ missing `x` and `y`
42+
43+
error: aborting due to 5 previous errors
44+
45+
For more information about this error, try `rustc --explain E0063`.

0 commit comments

Comments
 (0)