]> git.proxmox.com Git - rustc.git/blob - src/doc/book/references-and-borrowing.md
New upstream version 1.16.0+dfsg1
[rustc.git] / src / doc / book / references-and-borrowing.md
1 % References and Borrowing
2
3 This is the second of three sections presenting Rust’s ownership system. This is one of
4 Rust’s most distinct and compelling features, with which Rust developers should
5 become quite acquainted. Ownership is how Rust achieves its largest goal,
6 memory safety. There are a few distinct concepts, each with its own
7 chapter:
8
9 * [ownership][ownership], the key concept
10 * borrowing, which you’re reading now
11 * [lifetimes][lifetimes], an advanced concept of borrowing
12
13 These three chapters are related, and in order. You’ll need all three to fully
14 understand the ownership system.
15
16 [ownership]: ownership.html
17 [lifetimes]: lifetimes.html
18
19 # Meta
20
21 Before we get to the details, two important notes about the ownership system.
22
23 Rust has a focus on safety and speed. It accomplishes these goals through many
24 ‘zero-cost abstractions’, which means that in Rust, abstractions cost as little
25 as possible in order to make them work. The ownership system is a prime example
26 of a zero-cost abstraction. All of the analysis we’ll talk about in this guide
27 is _done at compile time_. You do not pay any run-time cost for any of these
28 features.
29
30 However, this system does have a certain cost: learning curve. Many new users
31 to Rust experience something we like to call ‘fighting with the borrow
32 checker’, where the Rust compiler refuses to compile a program that the author
33 thinks is valid. This often happens because the programmer’s mental model of
34 how ownership should work doesn’t match the actual rules that Rust implements.
35 You probably will experience similar things at first. There is good news,
36 however: more experienced Rust developers report that once they work with the
37 rules of the ownership system for a period of time, they fight the borrow
38 checker less and less.
39
40 With that in mind, let’s learn about borrowing.
41
42 # Borrowing
43
44 At the end of the [ownership][ownership] section, we had a nasty function that looked
45 like this:
46
47 ```rust
48 fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
49 // Do stuff with `v1` and `v2`.
50
51 // Hand back ownership, and the result of our function.
52 (v1, v2, 42)
53 }
54
55 let v1 = vec![1, 2, 3];
56 let v2 = vec![1, 2, 3];
57
58 let (v1, v2, answer) = foo(v1, v2);
59 ```
60
61 This is not idiomatic Rust, however, as it doesn’t take advantage of borrowing. Here’s
62 the first step:
63
64 ```rust
65 fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
66 // Do stuff with `v1` and `v2`.
67
68 // Return the answer.
69 42
70 }
71
72 let v1 = vec![1, 2, 3];
73 let v2 = vec![1, 2, 3];
74
75 let answer = foo(&v1, &v2);
76
77 // We can use `v1` and `v2` here!
78 ```
79
80 A more concrete example:
81
82 ```rust
83 fn main() {
84 // Don't worry if you don't understand how `fold` works, the point here is that an immutable reference is borrowed.
85 fn sum_vec(v: &Vec<i32>) -> i32 {
86 return v.iter().fold(0, |a, &b| a + b);
87 }
88 // Borrow two vectors and sum them.
89 // This kind of borrowing does not allow mutation through the borrowed reference.
90 fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
91 // Do stuff with `v1` and `v2`.
92 let s1 = sum_vec(v1);
93 let s2 = sum_vec(v2);
94 // Return the answer.
95 s1 + s2
96 }
97
98 let v1 = vec![1, 2, 3];
99 let v2 = vec![4, 5, 6];
100
101 let answer = foo(&v1, &v2);
102 println!("{}", answer);
103 }
104 ```
105
106 Instead of taking `Vec<i32>`s as our arguments, we take a reference:
107 `&Vec<i32>`. And instead of passing `v1` and `v2` directly, we pass `&v1` and
108 `&v2`. We call the `&T` type a ‘reference’, and rather than owning the resource,
109 it borrows ownership. A binding that borrows something does not deallocate the
110 resource when it goes out of scope. This means that after the call to `foo()`,
111 we can use our original bindings again.
112
113 References are immutable, like bindings. This means that inside of `foo()`,
114 the vectors can’t be changed at all:
115
116 ```rust,ignore
117 fn foo(v: &Vec<i32>) {
118 v.push(5);
119 }
120
121 let v = vec![];
122
123 foo(&v);
124 ```
125
126 will give us this error:
127
128 ```text
129 error: cannot borrow immutable borrowed content `*v` as mutable
130 v.push(5);
131 ^
132 ```
133
134 Pushing a value mutates the vector, and so we aren’t allowed to do it.
135
136 # &mut references
137
138 There’s a second kind of reference: `&mut T`. A ‘mutable reference’ allows you
139 to mutate the resource you’re borrowing. For example:
140
141 ```rust
142 let mut x = 5;
143 {
144 let y = &mut x;
145 *y += 1;
146 }
147 println!("{}", x);
148 ```
149
150 This will print `6`. We make `y` a mutable reference to `x`, then add one to
151 the thing `y` points at. You’ll notice that `x` had to be marked `mut` as well.
152 If it wasn’t, we couldn’t take a mutable borrow to an immutable value.
153
154 You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
155 this is because `y` is a `&mut` reference. You'll need to use asterisks to
156 access the contents of a reference as well.
157
158 Otherwise, `&mut` references are like references. There _is_ a large
159 difference between the two, and how they interact, though. You can tell
160 something is fishy in the above example, because we need that extra scope, with
161 the `{` and `}`. If we remove them, we get an error:
162
163 ```text
164 error: cannot borrow `x` as immutable because it is also borrowed as mutable
165 println!("{}", x);
166 ^
167 note: previous borrow of `x` occurs here; the mutable borrow prevents
168 subsequent moves, borrows, or modification of `x` until the borrow ends
169 let y = &mut x;
170 ^
171 note: previous borrow ends here
172 fn main() {
173
174 }
175 ^
176 ```
177
178 As it turns out, there are rules.
179
180 # The Rules
181
182 Here are the rules for borrowing in Rust:
183
184 First, any borrow must last for a scope no greater than that of the owner.
185 Second, you may have one or the other of these two kinds of borrows, but not
186 both at the same time:
187
188 * one or more references (`&T`) to a resource,
189 * exactly one mutable reference (`&mut T`).
190
191
192 You may notice that this is very similar to, though not exactly the same as,
193 the definition of a data race:
194
195 > There is a ‘data race’ when two or more pointers access the same memory
196 > location at the same time, where at least one of them is writing, and the
197 > operations are not synchronized.
198
199 With references, you may have as many as you’d like, since none of them are
200 writing. However, as we can only have one `&mut` at a time, it is impossible to
201 have a data race. This is how Rust prevents data races at compile time: we’ll
202 get errors if we break the rules.
203
204 With this in mind, let’s consider our example again.
205
206 ## Thinking in scopes
207
208 Here’s the code:
209
210 ```rust,ignore
211 fn main() {
212 let mut x = 5;
213 let y = &mut x;
214
215 *y += 1;
216
217 println!("{}", x);
218 }
219 ```
220
221 This code gives us this error:
222
223 ```text
224 error: cannot borrow `x` as immutable because it is also borrowed as mutable
225 println!("{}", x);
226 ^
227 ```
228
229 This is because we’ve violated the rules: we have a `&mut T` pointing to `x`,
230 and so we aren’t allowed to create any `&T`s. It's one or the other. The note
231 hints at how to think about this problem:
232
233 ```text
234 note: previous borrow ends here
235 fn main() {
236
237 }
238 ^
239 ```
240
241 In other words, the mutable borrow is held through the rest of our example. What
242 we want is for the mutable borrow by `y` to end so that the resource can be
243 returned to the owner, `x`. `x` can then provide an immutable borrow to `println!`.
244 In Rust, borrowing is tied to the scope that the borrow is valid for. And our
245 scopes look like this:
246
247 ```rust,ignore
248 fn main() {
249 let mut x = 5;
250
251 let y = &mut x; // -+ &mut borrow of `x` starts here.
252 // |
253 *y += 1; // |
254 // |
255 println!("{}", x); // -+ - Try to borrow `x` here.
256 } // -+ &mut borrow of `x` ends here.
257
258 ```
259
260 The scopes conflict: we can’t make an `&x` while `y` is in scope.
261
262 So when we add the curly braces:
263
264 ```rust
265 let mut x = 5;
266
267 {
268 let y = &mut x; // -+ &mut borrow starts here.
269 *y += 1; // |
270 } // -+ ... and ends here.
271
272 println!("{}", x); // <- Try to borrow `x` here.
273 ```
274
275 There’s no problem. Our mutable borrow goes out of scope before we create an
276 immutable one. So scope is the key to seeing how long a borrow lasts for.
277
278 ## Issues borrowing prevents
279
280 Why have these restrictive rules? Well, as we noted, these rules prevent data
281 races. What kinds of issues do data races cause? Here are a few.
282
283 ### Iterator invalidation
284
285 One example is ‘iterator invalidation’, which happens when you try to mutate a
286 collection that you’re iterating over. Rust’s borrow checker prevents this from
287 happening:
288
289 ```rust
290 let mut v = vec![1, 2, 3];
291
292 for i in &v {
293 println!("{}", i);
294 }
295 ```
296
297 This prints out one through three. As we iterate through the vector, we’re
298 only given references to the elements. And `v` is itself borrowed as immutable,
299 which means we can’t change it while we’re iterating:
300
301 ```rust,ignore
302 let mut v = vec![1, 2, 3];
303
304 for i in &v {
305 println!("{}", i);
306 v.push(34);
307 }
308 ```
309
310 Here’s the error:
311
312 ```text
313 error: cannot borrow `v` as mutable because it is also borrowed as immutable
314 v.push(34);
315 ^
316 note: previous borrow of `v` occurs here; the immutable borrow prevents
317 subsequent moves or mutable borrows of `v` until the borrow ends
318 for i in &v {
319 ^
320 note: previous borrow ends here
321 for i in &v {
322 println!(“{}”, i);
323 v.push(34);
324 }
325 ^
326 ```
327
328 We can’t modify `v` because it’s borrowed by the loop.
329
330 ### Use after free
331
332 References must not live longer than the resource they refer to. Rust will
333 check the scopes of your references to ensure that this is true.
334
335 If Rust didn’t check this property, we could accidentally use a reference
336 which was invalid. For example:
337
338 ```rust,ignore
339 let y: &i32;
340 {
341 let x = 5;
342 y = &x;
343 }
344
345 println!("{}", y);
346 ```
347
348 We get this error:
349
350 ```text
351 error: `x` does not live long enough
352 y = &x;
353 ^
354 note: reference must be valid for the block suffix following statement 0 at
355 2:16...
356 let y: &i32;
357 {
358 let x = 5;
359 y = &x;
360 }
361
362 note: ...but borrowed value is only valid for the block suffix following
363 statement 0 at 4:18
364 let x = 5;
365 y = &x;
366 }
367 ```
368
369 In other words, `y` is only valid for the scope where `x` exists. As soon as
370 `x` goes away, it becomes invalid to refer to it. As such, the error says that
371 the borrow ‘doesn’t live long enough’ because it’s not valid for the right
372 amount of time.
373
374 The same problem occurs when the reference is declared _before_ the variable it
375 refers to. This is because resources within the same scope are freed in the
376 opposite order they were declared:
377
378 ```rust,ignore
379 let y: &i32;
380 let x = 5;
381 y = &x;
382
383 println!("{}", y);
384 ```
385
386 We get this error:
387
388 ```text
389 error: `x` does not live long enough
390 y = &x;
391 ^
392 note: reference must be valid for the block suffix following statement 0 at
393 2:16...
394 let y: &i32;
395 let x = 5;
396 y = &x;
397
398 println!("{}", y);
399 }
400
401 note: ...but borrowed value is only valid for the block suffix following
402 statement 1 at 3:14
403 let x = 5;
404 y = &x;
405
406 println!("{}", y);
407 }
408 ```
409
410 In the above example, `y` is declared before `x`, meaning that `y` lives longer
411 than `x`, which is not allowed.