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