enum SemiColonMode {
Break,
Ignore,
+ Comma,
}
#[derive(Clone, Copy, PartialEq, Debug)]
break;
}
+ let mut recovery_field = None;
+ if let token::Ident(ident, _) = self.token {
+ if !self.token.is_reserved_ident() {
+ let mut ident = ident.clone();
+ ident.span = self.span;
+ recovery_field = Some(ast::Field {
+ ident,
+ span: self.span,
+ expr: self.mk_expr(self.span, ExprKind::Err, ThinVec::new()),
+ is_shorthand: true,
+ attrs: ThinVec::new(),
+ });
+ }
+ }
match self.parse_field() {
Ok(f) => fields.push(f),
Err(mut e) => {
e.span_label(struct_sp, "while parsing this struct");
e.emit();
+ if let Some(f) = recovery_field {
+ fields.push(f);
+ }
// If the next token is a comma, then try to parse
// what comes next as additional fields, rather than
// bailing out until next `}`.
if self.token != token::Comma {
- self.recover_stmt();
- break;
+ self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
+ if self.token != token::Comma {
+ break;
+ }
}
}
}
&[token::CloseDelim(token::Brace)]) {
Ok(()) => {}
Err(mut e) => {
+ e.span_label(struct_sp, "while parsing this struct");
e.emit();
- self.recover_stmt();
- break;
+ self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
+ self.eat(&token::Comma);
}
}
}
token::CloseDelim(token::DelimToken::Brace) => {
if brace_depth == 0 {
debug!("recover_stmt_ return - close delim {:?}", self.token);
- return;
+ break;
}
brace_depth -= 1;
self.bump();
if in_block && bracket_depth == 0 && brace_depth == 0 {
debug!("recover_stmt_ return - block end {:?}", self.token);
- return;
+ break;
}
}
token::CloseDelim(token::DelimToken::Bracket) => {
}
token::Eof => {
debug!("recover_stmt_ return - Eof");
- return;
+ break;
}
token::Semi => {
self.bump();
brace_depth == 0 &&
bracket_depth == 0 {
debug!("recover_stmt_ return - Semi");
- return;
+ break;
+ }
+ }
+ token::Comma => {
+ if break_on_semi == SemiColonMode::Comma &&
+ brace_depth == 0 &&
+ bracket_depth == 0 {
+ debug!("recover_stmt_ return - Semi");
+ break;
+ } else {
+ self.bump();
}
}
_ => {
--- /dev/null
+struct Foo { bar: f64, baz: i64, bat: i64 }
+
+fn main() {
+ let _ = Foo { bar: .5, baz: 42 };
+ //~^ ERROR expected expression
+ //~| ERROR missing field `bat` in initializer of `Foo`
+ let bar = 1.5f32;
+ let _ = Foo { bar.into(), bat: -1, . };
+ //~^ ERROR expected one of
+ //~| ERROR mismatched types
+ //~| ERROR missing field `baz` in initializer of `Foo`
+ //~| ERROR expected identifier, found `.`
+}
--- /dev/null
+error: expected expression, found `.`
+ --> $DIR/issue-52496.rs:4:24
+ |
+LL | let _ = Foo { bar: .5, baz: 42 };
+ | --- ^ expected expression
+ | |
+ | while parsing this struct
+
+error: expected one of `,` or `}`, found `.`
+ --> $DIR/issue-52496.rs:8:22
+ |
+LL | let _ = Foo { bar.into(), bat: -1, . };
+ | --- ^ expected one of `,` or `}` here
+ | |
+ | while parsing this struct
+
+error: expected identifier, found `.`
+ --> $DIR/issue-52496.rs:8:40
+ |
+LL | let _ = Foo { bar.into(), bat: -1, . };
+ | --- ^ expected identifier
+ | |
+ | while parsing this struct
+
+error[E0063]: missing field `bat` in initializer of `Foo`
+ --> $DIR/issue-52496.rs:4:13
+ |
+LL | let _ = Foo { bar: .5, baz: 42 };
+ | ^^^ missing `bat`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-52496.rs:8:19
+ |
+LL | let _ = Foo { bar.into(), bat: -1, . };
+ | ^^^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+ |
+LL | let _ = Foo { bar: bar.into().into(), bat: -1, . };
+ | ^^^^^^^^^^^^^^^
+
+error[E0063]: missing field `baz` in initializer of `Foo`
+ --> $DIR/issue-52496.rs:8:13
+ |
+LL | let _ = Foo { bar.into(), bat: -1, . };
+ | ^^^ missing `baz`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0063, E0308.
+For more information about an error, try `rustc --explain E0063`.
--> $DIR/removed-syntax-with-1.rs:8:25
|
LL | let b = S { foo: () with a };
- | ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+ | - ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+ | |
+ | while parsing this struct
error[E0063]: missing field `bar` in initializer of `main::S`
--> $DIR/removed-syntax-with-1.rs:8:13
--> $DIR/removed-syntax-with-2.rs:8:31
|
LL | let b = S { foo: (), with a };
- | ^ expected one of `,` or `}` here
+ | - ^ expected one of `,` or `}` here
+ | |
+ | while parsing this struct
error[E0425]: cannot find value `with` in this scope
--> $DIR/removed-syntax-with-2.rs:8:26
struct Rgb(u8, u8, u8);
fn main() {
- let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
- //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
+ let _ = Rgb { 0, 1, 2 };
+ //~^ ERROR expected identifier, found `0`
+ //~| ERROR expected identifier, found `1`
+ //~| ERROR expected identifier, found `2`
+ //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
}
error: expected identifier, found `0`
--> $DIR/struct-field-numeric-shorthand.rs:4:19
|
-LL | let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
+LL | let _ = Rgb { 0, 1, 2 };
| --- ^ expected identifier
| |
| while parsing this struct
+error: expected identifier, found `1`
+ --> $DIR/struct-field-numeric-shorthand.rs:4:22
+ |
+LL | let _ = Rgb { 0, 1, 2 };
+ | --- ^ expected identifier
+ | |
+ | while parsing this struct
+
+error: expected identifier, found `2`
+ --> $DIR/struct-field-numeric-shorthand.rs:4:25
+ |
+LL | let _ = Rgb { 0, 1, 2 };
+ | --- ^ expected identifier
+ | |
+ | while parsing this struct
+
error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb`
--> $DIR/struct-field-numeric-shorthand.rs:4:13
|
-LL | let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
+LL | let _ = Rgb { 0, 1, 2 };
| ^^^ missing `0`, `1`, `2`
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0063`.