Rollup merge of #84793 - estebank:parse-struct-field-default, r=davidtwco
Recover from invalid `struct` item syntax Parse unsupported "default field const values": ```rust struct S { field: Type = const_val, } ``` Recover from small `:` typo and provide suggestion: ```rust struct S { field; Type, field2= Type, } ```
This commit is contained in:
commit
94617802a1
4 changed files with 207 additions and 1 deletions
|
@ -1399,6 +1399,37 @@ impl<'a> Parser<'a> {
|
||||||
Ok(a_var)
|
Ok(a_var)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
|
||||||
|
if let Err(mut err) = self.expect(&token::Colon) {
|
||||||
|
let sm = self.sess.source_map();
|
||||||
|
let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start());
|
||||||
|
let semi_typo = self.token.kind == token::Semi
|
||||||
|
&& self.look_ahead(1, |t| {
|
||||||
|
t.is_path_start()
|
||||||
|
// We check that we are in a situation like `foo; bar` to avoid bad suggestions
|
||||||
|
// when there's no type and `;` was used instead of a comma.
|
||||||
|
&& match (sm.lookup_line(self.token.span.hi()), sm.lookup_line(t.span.lo())) {
|
||||||
|
(Ok(l), Ok(r)) => l.line == r.line,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if eq_typo || semi_typo {
|
||||||
|
self.bump();
|
||||||
|
// Gracefully handle small typos.
|
||||||
|
err.span_suggestion_short(
|
||||||
|
self.prev_token.span,
|
||||||
|
"field names and their types are separated with `:`",
|
||||||
|
":".to_string(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
|
} else {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses a structure field.
|
/// Parses a structure field.
|
||||||
fn parse_name_and_ty(
|
fn parse_name_and_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -1408,8 +1439,21 @@ impl<'a> Parser<'a> {
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
) -> PResult<'a, FieldDef> {
|
) -> PResult<'a, FieldDef> {
|
||||||
let name = self.parse_field_ident(adt_ty, lo)?;
|
let name = self.parse_field_ident(adt_ty, lo)?;
|
||||||
self.expect(&token::Colon)?;
|
self.expect_field_ty_separator()?;
|
||||||
let ty = self.parse_ty()?;
|
let ty = self.parse_ty()?;
|
||||||
|
if self.token.kind == token::Eq {
|
||||||
|
self.bump();
|
||||||
|
let const_expr = self.parse_anon_const_expr()?;
|
||||||
|
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
|
||||||
|
self.struct_span_err(sp, "default values on `struct` fields aren't supported")
|
||||||
|
.span_suggestion(
|
||||||
|
sp,
|
||||||
|
"remove this unsupported default value",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
Ok(FieldDef {
|
Ok(FieldDef {
|
||||||
span: lo.to(self.prev_token.span),
|
span: lo.to(self.prev_token.span),
|
||||||
ident: Some(name),
|
ident: Some(name),
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
enum E {
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
field1: i32, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field2: E, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field3: i32, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field4: i32, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field5: E, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field6: E, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S1 {
|
||||||
|
field1: i32, //~ ERROR expected `,`, or `}`, found `field2`
|
||||||
|
field2: E, //~ ERROR expected `,`, or `}`, found `field3`
|
||||||
|
field3: i32, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field4: i32, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field5: E, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field6: E, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S2 {
|
||||||
|
field1 : i32, //~ ERROR expected `:`, found `=`
|
||||||
|
field2: E, //~ ERROR expected `:`, found `;`
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn foo(_: i32) -> E {
|
||||||
|
E::A
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,35 @@
|
||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
enum E {
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S {
|
||||||
|
field1: i32 = 42, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field2: E = E::A, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field3: i32 = 1 + 2, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field4: i32 = { 1 + 2 }, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field5: E = foo(42), //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field6: E = { foo(42) }, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S1 {
|
||||||
|
field1: i32 //~ ERROR expected `,`, or `}`, found `field2`
|
||||||
|
field2: E //~ ERROR expected `,`, or `}`, found `field3`
|
||||||
|
field3: i32 = 1 + 2, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field4: i32 = { 1 + 2 }, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field5: E = foo(42), //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
field6: E = { foo(42) }, //~ ERROR default values on `struct` fields aren't supported
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S2 {
|
||||||
|
field1 = i32, //~ ERROR expected `:`, found `=`
|
||||||
|
field2; E, //~ ERROR expected `:`, found `;`
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn foo(_: i32) -> E {
|
||||||
|
E::A
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,92 @@
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:9:16
|
||||||
|
|
|
||||||
|
LL | field1: i32 = 42,
|
||||||
|
| ^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:10:14
|
||||||
|
|
|
||||||
|
LL | field2: E = E::A,
|
||||||
|
| ^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:11:16
|
||||||
|
|
|
||||||
|
LL | field3: i32 = 1 + 2,
|
||||||
|
| ^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:12:16
|
||||||
|
|
|
||||||
|
LL | field4: i32 = { 1 + 2 },
|
||||||
|
| ^^^^^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:13:14
|
||||||
|
|
|
||||||
|
LL | field5: E = foo(42),
|
||||||
|
| ^^^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:14:14
|
||||||
|
|
|
||||||
|
LL | field6: E = { foo(42) },
|
||||||
|
| ^^^^^^^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: expected `,`, or `}`, found `field2`
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:18:16
|
||||||
|
|
|
||||||
|
LL | field1: i32
|
||||||
|
| ^ help: try adding a comma: `,`
|
||||||
|
|
||||||
|
error: expected `,`, or `}`, found `field3`
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:19:14
|
||||||
|
|
|
||||||
|
LL | field2: E
|
||||||
|
| ^ help: try adding a comma: `,`
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:20:16
|
||||||
|
|
|
||||||
|
LL | field3: i32 = 1 + 2,
|
||||||
|
| ^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:21:16
|
||||||
|
|
|
||||||
|
LL | field4: i32 = { 1 + 2 },
|
||||||
|
| ^^^^^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:22:14
|
||||||
|
|
|
||||||
|
LL | field5: E = foo(42),
|
||||||
|
| ^^^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: default values on `struct` fields aren't supported
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:23:14
|
||||||
|
|
|
||||||
|
LL | field6: E = { foo(42) },
|
||||||
|
| ^^^^^^^^^^^^^^ help: remove this unsupported default value
|
||||||
|
|
||||||
|
error: expected `:`, found `=`
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:27:12
|
||||||
|
|
|
||||||
|
LL | field1 = i32,
|
||||||
|
| ^
|
||||||
|
| |
|
||||||
|
| expected `:`
|
||||||
|
| help: field names and their types are separated with `:`
|
||||||
|
|
||||||
|
error: expected `:`, found `;`
|
||||||
|
--> $DIR/struct-default-values-and-missing-field-separator.rs:28:11
|
||||||
|
|
|
||||||
|
LL | field2; E,
|
||||||
|
| ^
|
||||||
|
| |
|
||||||
|
| expected `:`
|
||||||
|
| help: field names and their types are separated with `:`
|
||||||
|
|
||||||
|
error: aborting due to 14 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue