]> git.proxmox.com Git - rustc.git/blob - src/doc/book/references-and-borrowing.md
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / doc / book / references-and-borrowing.md
1 % References and Borrowing
2
3 This guide is two of three presenting Rust’s ownership system. This is one of
4 Rust’s most unique 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 Instead of taking `Vec<i32>`s as our arguments, we take a reference:
81 `&Vec<i32>`. And instead of passing `v1` and `v2` directly, we pass `&v1` and
82 `&v2`. We call the `&T` type a ‘reference’, and rather than owning the resource,
83 it borrows ownership. A binding that borrows something does not deallocate the
84 resource when it goes out of scope. This means that after the call to `foo()`,
85 we can use our original bindings again.
86
87 References are immutable, like bindings. This means that inside of `foo()`,
88 the vectors can’t be changed at all:
89
90 ```rust,ignore
91 fn foo(v: &Vec<i32>) {
92 v.push(5);
93 }
94
95 let v = vec![];
96
97 foo(&v);
98 ```
99
100 errors with:
101
102 ```text
103 error: cannot borrow immutable borrowed content `*v` as mutable
104 v.push(5);
105 ^
106 ```
107
108 Pushing a value mutates the vector, and so we aren’t allowed to do it.
109
110 # &mut references
111
112 There’s a second kind of reference: `&mut T`. A ‘mutable reference’ allows you
113 to mutate the resource you’re borrowing. For example:
114
115 ```rust
116 let mut x = 5;
117 {
118 let y = &mut x;
119 *y += 1;
120 }
121 println!("{}", x);
122 ```
123
124 This will print `6`. We make `y` a mutable reference to `x`, then add one to
125 the thing `y` points at. You’ll notice that `x` had to be marked `mut` as well.
126 If it wasn’t, we couldn’t take a mutable borrow to an immutable value.
127
128 You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
129 this is because `y` is a `&mut` reference. You'll also need to use them for
130 accessing the contents of a reference as well.
131
132 Otherwise, `&mut` references are like references. There _is_ a large
133 difference between the two, and how they interact, though. You can tell
134 something is fishy in the above example, because we need that extra scope, with
135 the `{` and `}`. If we remove them, we get an error:
136
137 ```text
138 error: cannot borrow `x` as immutable because it is also borrowed as mutable
139 println!("{}", x);
140 ^
141 note: previous borrow of `x` occurs here; the mutable borrow prevents
142 subsequent moves, borrows, or modification of `x` until the borrow ends
143 let y = &mut x;
144 ^
145 note: previous borrow ends here
146 fn main() {
147
148 }
149 ^
150 ```
151
152 As it turns out, there are rules.
153
154 # The Rules
155
156 Here’s the rules about borrowing in Rust:
157
158 First, any borrow must last for a scope no greater than that of the owner.
159 Second, you may have one or the other of these two kinds of borrows, but not
160 both at the same time:
161
162 * one or more references (`&T`) to a resource,
163 * exactly one mutable reference (`&mut T`).
164
165
166 You may notice that this is very similar to, though not exactly the same as,
167 the definition of a data race:
168
169 > There is a ‘data race’ when two or more pointers access the same memory
170 > location at the same time, where at least one of them is writing, and the
171 > operations are not synchronized.
172
173 With references, you may have as many as you’d like, since none of them are
174 writing. However, as we can only have one `&mut` at a time, it is impossible to
175 have a data race. This is how Rust prevents data races at compile time: we’ll
176 get errors if we break the rules.
177
178 With this in mind, let’s consider our example again.
179
180 ## Thinking in scopes
181
182 Here’s the code:
183
184 ```rust,ignore
185 let mut x = 5;
186 let y = &mut x;
187
188 *y += 1;
189
190 println!("{}", x);
191 ```
192
193 This code gives us this error:
194
195 ```text
196 error: cannot borrow `x` as immutable because it is also borrowed as mutable
197 println!("{}", x);
198 ^
199 ```
200
201 This is because we’ve violated the rules: we have a `&mut T` pointing to `x`,
202 and so we aren’t allowed to create any `&T`s. One or the other. The note
203 hints at how to think about this problem:
204
205 ```text
206 note: previous borrow ends here
207 fn main() {
208
209 }
210 ^
211 ```
212
213 In other words, the mutable borrow is held through the rest of our example. What
214 we want is for the mutable borrow by `y` to end so that the resource can be
215 returned to the owner, `x`. `x` can then provide a immutable borrow to `println!`.
216 In Rust, borrowing is tied to the scope that the borrow is valid for. And our
217 scopes look like this:
218
219 ```rust,ignore
220 let mut x = 5;
221
222 let y = &mut x; // -+ &mut borrow of x starts here
223 // |
224 *y += 1; // |
225 // |
226 println!("{}", x); // -+ - try to borrow x here
227 // -+ &mut borrow of x ends here
228 ```
229
230 The scopes conflict: we can’t make an `&x` while `y` is in scope.
231
232 So when we add the curly braces:
233
234 ```rust
235 let mut x = 5;
236
237 {
238 let y = &mut x; // -+ &mut borrow starts here
239 *y += 1; // |
240 } // -+ ... and ends here
241
242 println!("{}", x); // <- try to borrow x here
243 ```
244
245 There’s no problem. Our mutable borrow goes out of scope before we create an
246 immutable one. But scope is the key to seeing how long a borrow lasts for.
247
248 ## Issues borrowing prevents
249
250 Why have these restrictive rules? Well, as we noted, these rules prevent data
251 races. What kinds of issues do data races cause? Here’s a few.
252
253 ### Iterator invalidation
254
255 One example is ‘iterator invalidation’, which happens when you try to mutate a
256 collection that you’re iterating over. Rust’s borrow checker prevents this from
257 happening:
258
259 ```rust
260 let mut v = vec![1, 2, 3];
261
262 for i in &v {
263 println!("{}", i);
264 }
265 ```
266
267 This prints out one through three. As we iterate through the vector, we’re
268 only given references to the elements. And `v` is itself borrowed as immutable,
269 which means we can’t change it while we’re iterating:
270
271 ```rust,ignore
272 let mut v = vec![1, 2, 3];
273
274 for i in &v {
275 println!("{}", i);
276 v.push(34);
277 }
278 ```
279
280 Here’s the error:
281
282 ```text
283 error: cannot borrow `v` as mutable because it is also borrowed as immutable
284 v.push(34);
285 ^
286 note: previous borrow of `v` occurs here; the immutable borrow prevents
287 subsequent moves or mutable borrows of `v` until the borrow ends
288 for i in &v {
289 ^
290 note: previous borrow ends here
291 for i in &v {
292 println!(“{}”, i);
293 v.push(34);
294 }
295 ^
296 ```
297
298 We can’t modify `v` because it’s borrowed by the loop.
299
300 ### use after free
301
302 References must not live longer than the resource they refer to. Rust will
303 check the scopes of your references to ensure that this is true.
304
305 If Rust didn’t check this property, we could accidentally use a reference
306 which was invalid. For example:
307
308 ```rust,ignore
309 let y: &i32;
310 {
311 let x = 5;
312 y = &x;
313 }
314
315 println!("{}", y);
316 ```
317
318 We get this error:
319
320 ```text
321 error: `x` does not live long enough
322 y = &x;
323 ^
324 note: reference must be valid for the block suffix following statement 0 at
325 2:16...
326 let y: &i32;
327 {
328 let x = 5;
329 y = &x;
330 }
331
332 note: ...but borrowed value is only valid for the block suffix following
333 statement 0 at 4:18
334 let x = 5;
335 y = &x;
336 }
337 ```
338
339 In other words, `y` is only valid for the scope where `x` exists. As soon as
340 `x` goes away, it becomes invalid to refer to it. As such, the error says that
341 the borrow ‘doesn’t live long enough’ because it’s not valid for the right
342 amount of time.
343
344 The same problem occurs when the reference is declared _before_ the variable it
345 refers to. This is because resources within the same scope are freed in the
346 opposite order they were declared:
347
348 ```rust,ignore
349 let y: &i32;
350 let x = 5;
351 y = &x;
352
353 println!("{}", y);
354 ```
355
356 We get this error:
357
358 ```text
359 error: `x` does not live long enough
360 y = &x;
361 ^
362 note: reference must be valid for the block suffix following statement 0 at
363 2:16...
364 let y: &i32;
365 let x = 5;
366 y = &x;
367
368 println!("{}", y);
369 }
370
371 note: ...but borrowed value is only valid for the block suffix following
372 statement 1 at 3:14
373 let x = 5;
374 y = &x;
375
376 println!("{}", y);
377 }
378 ```
379
380 In the above example, `y` is declared before `x`, meaning that `y` lives longer
381 than `x`, which is not allowed.