diff options
| author | bors <bors@rust-lang.org> | 2024-12-10 00:07:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-12-10 00:07:00 +0000 |
| commit | 974ccc12e6b4fdf38407258071e3d794d383ce3a (patch) | |
| tree | 13ea18466fe3e5912cff4fbdebe6433619ac37de /compiler/rustc_parse/src/parser | |
| parent | a224f3807e58afc9353510f1d556c607d367545d (diff) | |
| parent | fa331f4d0d2d7657c76972574868c5c00afae459 (diff) | |
| download | rust-974ccc12e6b4fdf38407258071e3d794d383ce3a.tar.gz rust-974ccc12e6b4fdf38407258071e3d794d383ce3a.zip | |
Auto merge of #129514 - estebank:default-field-values, r=compiler-errors
Introduce `default_field_values` feature
Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681.
We now parse const expressions after a `=` in a field definition, to specify a `struct` field default value.
We now allow `Struct { field, .. }` where there's no base after `..`.
`#[derive(Default)]` now uses the default value if present, continuing to use `Default::default()` if not.
```rust
#[derive(Debug)]
pub struct S;
#[derive(Debug, Default)]
pub struct Foo {
pub bar: S = S,
pub baz: i32 = 42 + 3,
}
fn main () {
let x = Foo { .. };
let y = Foo::default();
let z = Foo { baz: 1, .. };
assert_eq!(45, x.baz);
assert_eq!(45, y.baz);
assert_eq!(1, z.baz);
}
```
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 27 |
2 files changed, 25 insertions, 4 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 3a9e9b480ec..eeb83a85e59 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3533,7 +3533,7 @@ impl<'a> Parser<'a> { 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)) { - base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi()); + base = ast::StructRest::Rest(self.prev_token.span); break; } match self.parse_expr() { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 475cd09147f..58b4bf8980b 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1836,6 +1836,22 @@ impl<'a> Parser<'a> { return Err(err); } }; + let mut default = None; + if p.token == token::Eq { + let mut snapshot = p.create_snapshot_for_diagnostic(); + snapshot.bump(); + match snapshot.parse_expr_anon_const() { + Ok(const_expr) => { + let sp = ty.span.shrink_to_hi().to(const_expr.value.span); + p.psess.gated_spans.gate(sym::default_field_values, sp); + p.restore_snapshot(snapshot); + default = Some(const_expr); + } + Err(err) => { + err.cancel(); + } + } + } Ok(( FieldDef { @@ -1845,6 +1861,7 @@ impl<'a> Parser<'a> { ident: None, id: DUMMY_NODE_ID, ty, + default, attrs, is_placeholder: false, }, @@ -2024,12 +2041,15 @@ impl<'a> Parser<'a> { if self.token == token::Colon && self.look_ahead(1, |t| *t != token::Colon) { self.dcx().emit_err(errors::SingleColonStructType { span: self.token.span }); } - if self.token == token::Eq { + let default = if self.token == token::Eq { self.bump(); let const_expr = self.parse_expr_anon_const()?; let sp = ty.span.shrink_to_hi().to(const_expr.value.span); - self.dcx().emit_err(errors::EqualsStructDefault { span: sp }); - } + self.psess.gated_spans.gate(sym::default_field_values, sp); + Some(const_expr) + } else { + None + }; Ok(FieldDef { span: lo.to(self.prev_token.span), ident: Some(name), @@ -2037,6 +2057,7 @@ impl<'a> Parser<'a> { safety, id: DUMMY_NODE_ID, ty, + default, attrs, is_placeholder: false, }) |
