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