Skip to content

Commit 9e4a554

Browse files
committed
Add docs for field default values
1 parent 3340922 commit 9e4a554

File tree

2 files changed

+100
-24
lines changed

2 files changed

+100
-24
lines changed

src/expressions/struct-expr.md

+48-24
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 ->
2727
PathInExpression `(`
@@ -62,29 +62,6 @@ The field name is separated from its value with a colon.
6262
r[expr.struct.field.union-constraint]
6363
A value of a [union] type can only be created using this syntax, and it must specify exactly one field.
6464

65-
r[expr.struct.update]
66-
## Functional update syntax
67-
68-
r[expr.struct.update.intro]
69-
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.
70-
71-
r[expr.struct.update.base-same-type]
72-
The expression following `..` (the base) must have the same struct type as the new struct type being formed.
73-
74-
r[expr.struct.update.fields]
75-
The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression.
76-
77-
r[expr.struct.update.visibility-constraint]
78-
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
79-
80-
```rust
81-
# struct Point3d { x: i32, y: i32, z: i32 }
82-
let mut base = Point3d {x: 1, y: 2, z: 3};
83-
let y_ref = &mut base.y;
84-
Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed
85-
drop(y_ref);
86-
```
87-
8865
r[expr.struct.brace-restricted-positions]
8966
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.
9067
However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses].
@@ -142,6 +119,52 @@ let a = Gamma; // Gamma unit value.
142119
let b = Gamma{}; // Exact same value as `a`.
143120
```
144121

122+
r[expr.struct.update]
123+
## Functional update syntax
124+
125+
r[expr.struct.update.intro]
126+
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.
127+
128+
r[expr.struct.update.base-same-type]
129+
The expression following `..` (the base) must have the same struct type as the new struct type being formed.
130+
131+
r[expr.struct.update.fields]
132+
The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression.
133+
134+
r[expr.struct.update.visibility-constraint]
135+
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
136+
137+
```rust
138+
# struct Point3d { x: i32, y: i32, z: i32 }
139+
let mut base = Point3d {x: 1, y: 2, z: 3};
140+
let y_ref = &mut base.y;
141+
Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed
142+
drop(y_ref);
143+
```
144+
145+
r[expr.struct.default]
146+
## Default field syntax
147+
148+
r[expr.struct.default.intro]
149+
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].
150+
151+
r[expr.struct.default.fields]
152+
All fields without defualt values must be listed in the expression.
153+
The entire expression uses the given values for the fields that were specified and initializes the remaining fields with their respective default values.
154+
155+
r[expr.struct.default.visibility-constraint]
156+
As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named.
157+
158+
```rust
159+
struct Pet {
160+
name: Option<String>,
161+
age: i128 = 42,
162+
}
163+
164+
let pet = Pet { name: None, .. };
165+
assert_eq!(valid.age, 42);
166+
```
167+
145168
[call expression]: call-expr.md
146169
[enum variant]: ../items/enumerations.md
147170
[if let]: if-expr.md#if-let-expressions
@@ -153,3 +176,4 @@ let b = Gamma{}; // Exact same value as `a`.
153176
[union]: ../items/unions.md
154177
[visible]: ../visibility-and-privacy.md
155178
[scrutinee]: ../glossary.md#scrutinee
179+
[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)