]> git.proxmox.com Git - rustc.git/blame - src/doc/book/first-edition/src/structs.md
New upstream version 1.19.0+dfsg1
[rustc.git] / src / doc / book / first-edition / src / structs.md
CommitLineData
8bb4bdeb 1# Structs
9346a6ac 2
e9174d1e 3`struct`s are a way of creating more complex data types. For example, if we were
9346a6ac
AL
4doing calculations involving coordinates in 2D space, we would need both an `x`
5and a `y` value:
6
7```rust
8let origin_x = 0;
9let origin_y = 0;
10```
11
9cc50fc6
SL
12A `struct` lets us combine these two into a single, unified datatype with `x`
13and `y` as field labels:
9346a6ac
AL
14
15```rust
16struct Point {
17 x: i32,
18 y: i32,
19}
20
21fn main() {
22 let origin = Point { x: 0, y: 0 }; // origin: Point
23
24 println!("The origin is at ({}, {})", origin.x, origin.y);
25}
26```
27
bd371182
AL
28There’s a lot going on here, so let’s break it down. We declare a `struct` with
29the `struct` keyword, and then with a name. By convention, `struct`s begin with
30a capital letter and are camel cased: `PointInSpace`, not `Point_In_Space`.
9346a6ac 31
e9174d1e 32We can create an instance of our `struct` via `let`, as usual, but we use a `key:
bd371182 33value` style syntax to set each field. The order doesn’t need to be the same as
9346a6ac
AL
34in the original declaration.
35
9cc50fc6 36Finally, because fields have names, we can access them through dot
9346a6ac
AL
37notation: `origin.x`.
38
e9174d1e 39The values in `struct`s are immutable by default, like other bindings in Rust.
9346a6ac
AL
40Use `mut` to make them mutable:
41
42```rust
43struct Point {
44 x: i32,
45 y: i32,
46}
47
48fn main() {
49 let mut point = Point { x: 0, y: 0 };
50
51 point.x = 5;
52
53 println!("The point is at ({}, {})", point.x, point.y);
54}
55```
56
57This will print `The point is at (5, 0)`.
58
59Rust does not support field mutability at the language level, so you cannot
60write something like this:
61
62```rust,ignore
63struct Point {
476ff2be 64 mut x: i32, // This causes an error.
9346a6ac
AL
65 y: i32,
66}
67```
68
69Mutability is a property of the binding, not of the structure itself. If you’re
70used to field-level mutability, this may seem strange at first, but it
9cc50fc6
SL
71significantly simplifies things. It even lets you make things mutable on a temporary
72basis:
9346a6ac
AL
73
74```rust,ignore
75struct Point {
76 x: i32,
77 y: i32,
78}
79
80fn main() {
81 let mut point = Point { x: 0, y: 0 };
82
83 point.x = 5;
84
476ff2be 85 let point = point; // `point` is now immutable.
9346a6ac 86
476ff2be 87 point.y = 6; // This causes an error.
9346a6ac
AL
88}
89```
bd371182 90
8bb4bdeb 91Your structure can still contain `&mut` references, which will let
9cc50fc6
SL
92you do some kinds of mutation:
93
94```rust
95struct Point {
96 x: i32,
97 y: i32,
98}
99
100struct PointRef<'a> {
101 x: &'a mut i32,
102 y: &'a mut i32,
103}
104
105fn main() {
106 let mut point = Point { x: 0, y: 0 };
107
108 {
109 let r = PointRef { x: &mut point.x, y: &mut point.y };
110
111 *r.x = 5;
112 *r.y = 6;
113 }
114
115 assert_eq!(5, point.x);
116 assert_eq!(6, point.y);
117}
118```
119
8bb4bdeb
XL
120Initialization of a data structure (struct, enum, union) can be simplified when
121fields of the data structure are initialized with variables of the same
122names as the fields.
123
7cac9316 124```rust
8bb4bdeb
XL
125#[derive(Debug)]
126struct Person<'a> {
127 name: &'a str,
128 age: u8
129}
130
131fn main() {
132 // Create struct with field init shorthand
133 let name = "Peter";
134 let age = 27;
135 let peter = Person { name, age };
136
137 // Debug-print struct
138 println!("{:?}", peter);
139}
140```
141
bd371182
AL
142# Update syntax
143
144A `struct` can include `..` to indicate that you want to use a copy of some
e9174d1e 145other `struct` for some of the values. For example:
bd371182
AL
146
147```rust
148struct Point3d {
149 x: i32,
150 y: i32,
151 z: i32,
152}
153
154let mut point = Point3d { x: 0, y: 0, z: 0 };
155point = Point3d { y: 1, .. point };
156```
157
158This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesn’t
159have to be the same `struct` either, you can use this syntax when making new
160ones, and it will copy the values you don’t specify:
161
162```rust
163# struct Point3d {
164# x: i32,
165# y: i32,
166# z: i32,
167# }
168let origin = Point3d { x: 0, y: 0, z: 0 };
169let point = Point3d { z: 1, x: 2, .. origin };
170```
171
172# Tuple structs
173
174Rust has another data type that’s like a hybrid between a [tuple][tuple] and a
9cc50fc6
SL
175`struct`, called a ‘tuple struct’. Tuple structs have a name, but their fields
176don't. They are declared with the `struct` keyword, and then with a name
177followed by a tuple:
178
179[tuple]: primitive-types.html#tuples
bd371182
AL
180
181```rust
182struct Color(i32, i32, i32);
183struct Point(i32, i32, i32);
bd371182 184
bd371182
AL
185let black = Color(0, 0, 0);
186let origin = Point(0, 0, 0);
187```
188
5bcae85e
SL
189Here, `black` and `origin` are not the same type, even though they contain the
190same values.
191
192The members of a tuple struct may be accessed by dot notation or destructuring
193`let`, just like regular tuples:
194
195```rust
196# struct Color(i32, i32, i32);
197# struct Point(i32, i32, i32);
198# let black = Color(0, 0, 0);
199# let origin = Point(0, 0, 0);
200let black_r = black.0;
201let Point(_, origin_y, origin_z) = origin;
202```
203
204Patterns like `Point(_, origin_y, origin_z)` are also used in
205[match expressions][match].
206
207One case when a tuple struct is very useful is when it has only one element.
208We call this the ‘newtype’ pattern, because it allows you to create a new type
209that is distinct from its contained value and also expresses its own semantic
210meaning:
211
212```rust
213struct Inches(i32);
214
215let length = Inches(10);
216
217let Inches(integer_length) = length;
218println!("length is {} inches", integer_length);
219```
220
221As above, you can extract the inner integer type through a destructuring `let`.
222In this case, the `let Inches(integer_length)` assigns `10` to `integer_length`.
223We could have used dot notation to do the same thing:
224
225```rust
226# struct Inches(i32);
227# let length = Inches(10);
228let integer_length = length.0;
229```
230
231It's always possible to use a `struct` instead of a tuple struct, and can be
232clearer. We could write `Color` and `Point` like this instead:
bd371182
AL
233
234```rust
235struct Color {
236 red: i32,
237 blue: i32,
238 green: i32,
239}
240
241struct Point {
242 x: i32,
243 y: i32,
244 z: i32,
245}
246```
247
9cc50fc6
SL
248Good names are important, and while values in a tuple struct can be
249referenced with dot notation as well, a `struct` gives us actual names,
250rather than positions.
bd371182 251
5bcae85e 252[match]: match.html
bd371182
AL
253
254# Unit-like structs
255
e9174d1e 256You can define a `struct` with no members at all:
bd371182 257
8bb4bdeb 258```rust,compile_fail,E0423
476ff2be
SL
259struct Electron {} // Use empty braces...
260struct Proton; // ...or just a semicolon.
b039eaaf 261
8bb4bdeb 262// Use the same notation when creating an instance.
5bcae85e
SL
263let x = Electron {};
264let y = Proton;
8bb4bdeb 265let z = Electron; // Error
bd371182
AL
266```
267
e9174d1e 268Such a `struct` is called ‘unit-like’ because it resembles the empty
bd371182
AL
269tuple, `()`, sometimes called ‘unit’. Like a tuple struct, it defines a
270new type.
271
272This is rarely useful on its own (although sometimes it can serve as a
273marker type), but in combination with other features, it can become
274useful. For instance, a library may ask you to create a structure that
275implements a certain [trait][trait] to handle events. If you don’t have
9cc50fc6 276any data you need to store in the structure, you can create a
e9174d1e 277unit-like `struct`.
d9579d0f
AL
278
279[trait]: traits.html