Skip to content

Commit 252b208

Browse files
committed
Add docs for field default values
1 parent cc1d51c commit 252b208

File tree

2 files changed

+103
-25
lines changed

2 files changed

+103
-25
lines changed

Diff for: src/expressions/struct-expr.md

+48-24
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ r[expr.struct.syntax]
2222
>    )
2323
>
2424
> _StructBase_ :\
25-
>    `..` [_Expression_]
25+
> &nbsp;&nbsp; `..` [_Expression_]<sup>?</sup>
2626
>
2727
> _StructExprTuple_ :\
2828
> &nbsp;&nbsp; [_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
[_OuterAttribute_]: ../attributes.md
146169
[IDENTIFIER]: ../identifiers.md
147170
[TUPLE_INDEX]: ../tokens.md#tuple-index
@@ -158,3 +181,4 @@ let b = Gamma{}; // Exact same value as `a`.
158181
[union]: ../items/unions.md
159182
[visible]: ../visibility-and-privacy.md
160183
[scrutinee]: ../glossary.md#scrutinee
184+
[default values]: ../items/structs.md#default-field-values

Diff for: src/items/structs.md

+55-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ r[items.struct.syntax]
2828
> _StructField_ :\
2929
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>\
3030
> &nbsp;&nbsp; [_Visibility_]<sup>?</sup>\
31-
> &nbsp;&nbsp; [IDENTIFIER] `:` [_Type_]
31+
> &nbsp;&nbsp; [IDENTIFIER] `:` [_Type_]\
32+
> &nbsp;&nbsp; _StructFieldDefault_<sup>?</sup>
33+
>
34+
> _StructFieldDefault_ :\
35+
> &nbsp;&nbsp; `=` [_Expression_]
3236
>
3337
> _TupleFields_ :\
3438
> &nbsp;&nbsp; _TupleField_ (`,` _TupleField_)<sup>\*</sup> `,`<sup>?</sup>
@@ -86,6 +90,52 @@ r[items.struct.layout]
8690
The precise memory layout of a struct is not specified. One can specify a
8791
particular layout using the [`repr` attribute].
8892

93+
r[items.struct.default]
94+
## Default field values
95+
96+
r[items.struct.default.intro]
97+
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]:
98+
99+
```rust
100+
struct Pet {
101+
name: Option<String>,
102+
age: i128 = 42,
103+
}
104+
105+
let pet = Pet { name: None, .. };
106+
assert_eq!(valid.age, 42);
107+
```
108+
109+
r[items.struct.default.const]
110+
A default field value must be a [constant expression]:
111+
112+
```rust,compile_fail
113+
struct Pet {
114+
name: Option<String>,
115+
age: i128 = { println!("calculating age"); 42 },
116+
// ERROR: cannot call non-const function `_print` in constants
117+
}
118+
```
119+
120+
r[item.struct.default.derive]
121+
The [derive macro] for the [`Default`] trait will use default field values in the implementation:
122+
123+
```rust
124+
#[derive(Default)]
125+
struct Pet {
126+
name: Option<String>, // impl Default for Pet will use Default::default() for name
127+
age: i128 = 42, // impl Default for Pet will use the literal 42 for age
128+
}
129+
130+
let default = Pet::default();
131+
assert_eq!(default.name, None);
132+
assert_eq!(default.age, 42);
133+
```
134+
135+
Any fields without a default field value must have an implementation of [`Default`],
136+
whose `default` method will be used for these fields instead.
137+
138+
[_Expression_]: ../expressions.md
89139
[_GenericParams_]: generics.md
90140
[_OuterAttribute_]: ../attributes.md
91141
[_Type_]: ../types.md#type-expressions
@@ -95,6 +145,10 @@ particular layout using the [`repr` attribute].
95145
[IDENTIFIER]: ../identifiers.md
96146
[constant]: constant-items.md
97147
[struct type]: ../types/struct.md
148+
[struct expression]: ../expressions/struct-expr.md
98149
[tuple type]: ../types/tuple.md
99150
[type namespace]: ../names/namespaces.md
100151
[value namespace]: ../names/namespaces.md
152+
[constant expression]: ../const_eval.md
153+
[derive macro]: ../procedural-macros.md#derive-macros
154+
[default field syntax]: ../expressions/struct-expr.md#default-field-syntax

0 commit comments

Comments
 (0)