Skip to content

Commit 760338b

Browse files
committed
Add docs for field default values
1 parent 48ad733 commit 760338b

File tree

2 files changed

+100
-24
lines changed

2 files changed

+100
-24
lines changed

src/expressions/struct-expr.md

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ StructExprField ->
2121
| (IDENTIFIER | TUPLE_INDEX) `:` Expression
2222
)
2323
24-
StructBase -> `..` Expression
24+
StructBase -> `..` Expression?
2525
2626
StructExprTuple -> CallExpression
2727
@@ -61,29 +61,6 @@ The field name is separated from its value with a colon.
6161
r[expr.struct.field.union-constraint]
6262
A value of a [union] type can only be created using this syntax, and it must specify exactly one field.
6363

64-
r[expr.struct.update]
65-
## Functional update syntax
66-
67-
r[expr.struct.update.intro]
68-
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.
69-
70-
r[expr.struct.update.base-same-type]
71-
The expression following `..` (the base) must have the same struct type as the new struct type being formed.
72-
73-
r[expr.struct.update.fields]
74-
The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression.
75-
76-
r[expr.struct.update.visibility-constraint]
77-
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
78-
79-
```rust
80-
# struct Point3d { x: i32, y: i32, z: i32 }
81-
let mut base = Point3d {x: 1, y: 2, z: 3};
82-
let y_ref = &mut base.y;
83-
Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed
84-
drop(y_ref);
85-
```
86-
8764
r[expr.struct.brace-restricted-positions]
8865
Struct expressions with curly braces can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression.
8966
However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses].
@@ -178,6 +155,52 @@ let d = ColorSpace::Oklch {};
178155
> <Enum as Tr>::T::Unit; // OK
179156
> ```
180157
158+
r[expr.struct.update]
159+
## Functional update syntax
160+
161+
r[expr.struct.update.intro]
162+
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.
163+
164+
r[expr.struct.update.base-same-type]
165+
The expression following `..` (the base) must have the same struct type as the new struct type being formed.
166+
167+
r[expr.struct.update.fields]
168+
The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression.
169+
170+
r[expr.struct.update.visibility-constraint]
171+
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
172+
173+
```rust
174+
# struct Point3d { x: i32, y: i32, z: i32 }
175+
let mut base = Point3d {x: 1, y: 2, z: 3};
176+
let y_ref = &mut base.y;
177+
Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed
178+
drop(y_ref);
179+
```
180+
181+
r[expr.struct.default]
182+
## Default field syntax
183+
184+
r[expr.struct.default.intro]
185+
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].
186+
187+
r[expr.struct.default.fields]
188+
All fields without defualt values must be listed in the expression.
189+
The entire expression uses the given values for the fields that were specified and initializes the remaining fields with their respective default values.
190+
191+
r[expr.struct.default.visibility-constraint]
192+
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
193+
194+
```rust
195+
struct Pet {
196+
name: Option<String>,
197+
age: i128 = 42,
198+
}
199+
200+
let pet = Pet { name: None, .. };
201+
assert_eq!(valid.age, 42);
202+
```
203+
181204
[call expression]: call-expr.md
182205
[enum variant]: ../items/enumerations.md
183206
[if let]: if-expr.md#if-let-expressions
@@ -189,3 +212,4 @@ let d = ColorSpace::Oklch {};
189212
[union]: ../items/unions.md
190213
[visible]: ../visibility-and-privacy.md
191214
[scrutinee]: ../glossary.md#scrutinee
215+
[default values]: ../items/structs.md#default-field-values

src/items/structs.md

Lines changed: 52 additions & 0 deletions
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)