Skip to content

Commit 453d6d2

Browse files
committed
Add docs for field default values
1 parent eafe90c commit 453d6d2

File tree

2 files changed

+106
-24
lines changed

2 files changed

+106
-24
lines changed

src/expressions/struct-expr.md

+54-24
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
r[expr.struct]
2+
23
# Struct expressions
34

45
r[expr.struct.syntax]
6+
57
```grammar,expressions
68
StructExpression ->
79
PathInExpression `{` (StructExprFields | StructBase)? `}`
@@ -16,7 +18,7 @@ StructExprField ->
1618
| (IDENTIFIER | TUPLE_INDEX) `:` Expression
1719
)
1820
19-
StructBase -> `..` Expression
21+
StructBase -> `..` Expression?
2022
```
2123

2224
r[expr.struct.intro]
@@ -82,6 +84,7 @@ Enum::Variant {};
8284
> ```
8385
8486
r[expr.struct.field]
87+
8588
## Field struct expression
8689
8790
r[expr.struct.field.intro]
@@ -91,29 +94,6 @@ The field name is separated from its value with a colon.
9194
r[expr.struct.field.union-constraint]
9295
A value of a [union] type can only be created using this syntax, and it must specify exactly one field.
9396
94-
r[expr.struct.update]
95-
## Functional update syntax
96-
97-
r[expr.struct.update.intro]
98-
A struct expression that constructs a value of a struct type can terminate with the syntax `..` followed by an expression to denote a functional update.
99-
100-
r[expr.struct.update.base-same-type]
101-
The expression following `..` (the base) must have the same struct type as the new struct type being formed.
102-
103-
r[expr.struct.update.fields]
104-
The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression.
105-
106-
r[expr.struct.update.visibility-constraint]
107-
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
108-
109-
```rust
110-
# struct Point3d { x: i32, y: i32, z: i32 }
111-
let mut base = Point3d {x: 1, y: 2, z: 3};
112-
let y_ref = &mut base.y;
113-
Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed
114-
drop(y_ref);
115-
```
116-
11797
r[expr.struct.brace-restricted-positions]
11898
Struct expressions can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression.
11999
However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses].
@@ -130,6 +110,7 @@ let c3 = Color{1: 0, ..c2}; // Fill out all other fields using a base struct.
130110
```
131111
132112
r[expr.struct.field.named]
113+
133114
### Struct field init shorthand
134115

135116
When initializing a data structure (struct, enum, union) with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`.
@@ -145,6 +126,54 @@ Point3d { x: x, y: y_value, z: z };
145126
Point3d { x, y: y_value, z };
146127
```
147128

129+
r[expr.struct.update]
130+
131+
## Functional update syntax
132+
133+
r[expr.struct.update.intro]
134+
A struct expression that constructs a value of a struct type can terminate with the syntax `..` followed by an expression to denote a functional update.
135+
136+
r[expr.struct.update.base-same-type]
137+
The expression following `..` (the base) must have the same struct type as the new struct type being formed.
138+
139+
r[expr.struct.update.fields]
140+
The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression.
141+
142+
r[expr.struct.update.visibility-constraint]
143+
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
144+
145+
```rust
146+
# struct Point3d { x: i32, y: i32, z: i32 }
147+
let mut base = Point3d {x: 1, y: 2, z: 3};
148+
let y_ref = &mut base.y;
149+
Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed
150+
drop(y_ref);
151+
```
152+
153+
r[expr.struct.default]
154+
155+
## Default field syntax
156+
157+
r[expr.struct.default.intro]
158+
A struct expression that constructs a value of a struct type can terminate with the syntax `..` without a following expression to denote that unlisted fields should be set to their [default values].
159+
160+
r[expr.struct.default.fields]
161+
All fields without defualt values must be listed in the expression.
162+
The entire expression uses the given values for the fields that were specified and initializes the remaining fields with their respective default values.
163+
164+
r[expr.struct.default.visibility-constraint]
165+
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
166+
167+
```rust
168+
struct Pet {
169+
name: Option<String>,
170+
age: i128 = 42,
171+
}
172+
173+
let pet = Pet { name: None, .. };
174+
assert_eq!(valid.age, 42);
175+
```
176+
148177
[enum variant]: ../items/enumerations.md
149178
[if let]: if-expr.md#if-let-expressions
150179
[if]: if-expr.md#if-expressions
@@ -155,3 +184,4 @@ Point3d { x, y: y_value, z };
155184
[union]: ../items/unions.md
156185
[visible]: ../visibility-and-privacy.md
157186
[scrutinee]: ../glossary.md#scrutinee
187+
[default values]: ../items/structs.md#default-field-values

src/items/structs.md

+52
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ TupleStruct ->
1616
StructFields -> StructField (`,` StructField)* `,`?
1717
1818
StructField -> OuterAttribute* Visibility? IDENTIFIER `:` Type
19+
StructFieldDefault?
20+
21+
StructFieldDefault -> `=` Expression
1922
2023
TupleFields -> TupleField (`,` TupleField)* `,`?
2124
@@ -70,9 +73,58 @@ r[items.struct.layout]
7073
The precise memory layout of a struct is not specified. One can specify a
7174
particular layout using the [`repr` attribute].
7275

76+
r[items.struct.default]
77+
## Default field values
78+
79+
r[items.struct.default.intro]
80+
A field in a non-tuple struct can be assigned a default value, which can be used in a [struct expression] using the [default field syntax]:
81+
82+
```rust
83+
struct Pet {
84+
name: Option<String>,
85+
age: i128 = 42,
86+
}
87+
88+
let pet = Pet { name: None, .. };
89+
assert_eq!(valid.age, 42);
90+
```
91+
92+
r[items.struct.default.const]
93+
A default field value must be a [constant expression]:
94+
95+
```rust,compile_fail
96+
struct Pet {
97+
name: Option<String>,
98+
age: i128 = { println!("calculating age"); 42 },
99+
// ERROR: cannot call non-const function `_print` in constants
100+
}
101+
```
102+
103+
r[item.struct.default.derive]
104+
The [derive macro] for the [`Default`] trait will use default field values in the implementation:
105+
106+
```rust
107+
#[derive(Default)]
108+
struct Pet {
109+
name: Option<String>, // impl Default for Pet will use Default::default() for name
110+
age: i128 = 42, // impl Default for Pet will use the literal 42 for age
111+
}
112+
113+
let default = Pet::default();
114+
assert_eq!(default.name, None);
115+
assert_eq!(default.age, 42);
116+
```
117+
118+
Any fields without a default field value must have an implementation of [`Default`],
119+
whose `default` method will be used for these fields instead.
120+
73121
[`repr` attribute]: ../type-layout.md#representations
74122
[constant]: constant-items.md
75123
[struct type]: ../types/struct.md
124+
[struct expression]: ../expressions/struct-expr.md
76125
[tuple type]: ../types/tuple.md
77126
[type namespace]: ../names/namespaces.md
78127
[value namespace]: ../names/namespaces.md
128+
[constant expression]: ../const_eval.md
129+
[derive macro]: ../procedural-macros.md#derive-macros
130+
[default field syntax]: ../expressions/struct-expr.md#default-field-syntax

0 commit comments

Comments
 (0)