]> git.proxmox.com Git - rustc.git/blame - src/doc/book/ownership.md
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / doc / book / ownership.md
CommitLineData
85aaf69f 1% Ownership
1a4d82fc 2
bd371182
AL
3This guide is one of three presenting Rust’s ownership system. This is one of
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, which you’re reading now
10* [borrowing][borrowing], and their associated feature ‘references’
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[borrowing]: references-and-borrowing.html
17[lifetimes]: lifetimes.html
1a4d82fc
JJ
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
bd371182 24‘zero-cost abstractions’, which means that in Rust, abstractions cost as little
1a4d82fc 25as possible in order to make them work. The ownership system is a prime example
bd371182 26of a zero-cost abstraction. All of the analysis we’ll talk about in this guide
1a4d82fc
JJ
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
bd371182
AL
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.
1a4d82fc
JJ
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
bd371182 40With that in mind, let’s learn about ownership.
1a4d82fc
JJ
41
42# Ownership
43
bd371182 44[Variable bindings][bindings] have a property in Rust: they ‘have ownership’
b039eaaf 45of what they’re bound to. This means that when a binding goes out of scope,
c1a9b12d 46Rust will free the bound resources. For example:
1a4d82fc
JJ
47
48```rust
bd371182
AL
49fn foo() {
50 let v = vec![1, 2, 3];
1a4d82fc
JJ
51}
52```
53
54a0048b 54When `v` comes into scope, a new [vector][vectors] is created on [the stack][stack],
7453a54e
SL
55and it allocates space on [the heap][heap] for its elements. When `v` goes out
56of scope at the end of `foo()`, Rust will clean up everything related to the
57vector, even the heap-allocated memory. This happens deterministically, at the
58end of the scope.
1a4d82fc 59
9cc50fc6
SL
60We'll cover [vectors] in detail later in this chapter; we only use them
61here as an example of a type that allocates space on the heap at runtime. They
62behave like [arrays], except their size may change by `push()`ing more
63elements onto them.
64
65Vectors have a [generic type][generics] `Vec<T>`, so in this example `v` will have type
66`Vec<i32>`. We'll cover generics in detail later in this chapter.
67
68[arrays]: primitive-types.html#arrays
69[vectors]: vectors.html
bd371182 70[heap]: the-stack-and-the-heap.html
7453a54e 71[stack]: the-stack-and-the-heap.html#the-stack
bd371182 72[bindings]: variable-bindings.html
9cc50fc6 73[generics]: generics.html
1a4d82fc 74
bd371182 75# Move semantics
1a4d82fc 76
bd371182
AL
77There’s some more subtlety here, though: Rust ensures that there is _exactly
78one_ binding to any given resource. For example, if we have a vector, we can
79assign it to another binding:
1a4d82fc
JJ
80
81```rust
bd371182 82let v = vec![1, 2, 3];
1a4d82fc 83
bd371182 84let v2 = v;
1a4d82fc
JJ
85```
86
bd371182 87But, if we try to use `v` afterwards, we get an error:
1a4d82fc 88
bd371182
AL
89```rust,ignore
90let v = vec![1, 2, 3];
1a4d82fc 91
bd371182 92let v2 = v;
1a4d82fc 93
bd371182 94println!("v[0] is: {}", v[0]);
1a4d82fc
JJ
95```
96
bd371182 97It looks like this:
85aaf69f 98
bd371182
AL
99```text
100error: use of moved value: `v`
101println!("v[0] is: {}", v[0]);
102 ^
1a4d82fc
JJ
103```
104
bd371182
AL
105A similar thing happens if we define a function which takes ownership, and
106try to use something after we’ve passed it as an argument:
1a4d82fc 107
bd371182
AL
108```rust,ignore
109fn take(v: Vec<i32>) {
110 // what happens here isn’t important.
1a4d82fc 111}
1a4d82fc 112
bd371182 113let v = vec![1, 2, 3];
1a4d82fc 114
bd371182 115take(v);
1a4d82fc 116
bd371182 117println!("v[0] is: {}", v[0]);
1a4d82fc
JJ
118```
119
bd371182
AL
120Same error: ‘use of moved value’. When we transfer ownership to something else,
121we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of
122special annotation here, it’s the default thing that Rust does.
1a4d82fc 123
bd371182 124## The details
1a4d82fc 125
bd371182 126The reason that we cannot use a binding after we’ve moved it is subtle, but
54a0048b 127important.
7453a54e
SL
128
129When we write code like this:
130
131```rust
132let x = 10;
133```
134
135Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit
136pattern representing the value of 10 to the allocated memory and binds the
137variable name x to this memory region for future reference.
138
139Now consider the following code fragment:
1a4d82fc
JJ
140
141```rust
bd371182 142let v = vec![1, 2, 3];
1a4d82fc 143
7453a54e
SL
144let mut v2 = v;
145```
146
147The first line allocates memory for the vector object `v` on the stack like
148it does for `x` above. But in addition to that it also allocates some memory
149on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address
150of this heap allocation to an internal pointer, which is part of the vector
54a0048b 151object placed on the stack (let's call it the data pointer).
7453a54e
SL
152
153It is worth pointing out (even at the risk of stating the obvious) that the
154vector object and its data live in separate memory regions instead of being a
155single contiguous memory allocation (due to reasons we will not go into at
156this point of time). These two parts of the vector (the one on the stack and
157one on the heap) must agree with each other at all times with regards to
158things like the length, capacity etc.
159
160When we move `v` to `v2`, Rust actually does a bitwise copy of the vector
161object `v` into the stack allocation represented by `v2`. This shallow copy
162does not create a copy of the heap allocation containing the actual data.
163Which means that there would be two pointers to the contents of the vector
164both pointing to the same memory allocation on the heap. It would violate
165Rust’s safety guarantees by introducing a data race if one could access both
54a0048b 166`v` and `v2` at the same time.
7453a54e
SL
167
168For example if we truncated the vector to just two elements through `v2`:
169
170```rust
171# let v = vec![1, 2, 3];
172# let mut v2 = v;
173v2.truncate(2);
1a4d82fc
JJ
174```
175
7453a54e
SL
176and `v1` were still accessible we'd end up with an invalid vector since `v1`
177would not know that the heap data has been truncated. Now, the part of the
178vector `v1` on the stack does not agree with the corresponding part on the
179heap. `v1` still thinks there are three elements in the vector and will
180happily let us access the non existent element `v1[2]` but as you might
181already know this is a recipe for disaster. Especially because it might lead
182to a segmentation fault or worse allow an unauthorized user to read from
183memory to which they don't have access.
184
185This is why Rust forbids using `v` after we’ve done the move.
1a4d82fc 186
bd371182 187[sh]: the-stack-and-the-heap.html
1a4d82fc 188
bd371182
AL
189It’s also important to note that optimizations may remove the actual copy of
190the bytes on the stack, depending on circumstances. So it may not be as
191inefficient as it initially seems.
1a4d82fc 192
bd371182 193## `Copy` types
1a4d82fc 194
bd371182
AL
195We’ve established that when ownership is transferred to another binding, you
196cannot use the original binding. However, there’s a [trait][traits] that changes this
197behavior, and it’s called `Copy`. We haven’t discussed traits yet, but for now,
198you can think of them as an annotation to a particular type that adds extra
199behavior. For example:
1a4d82fc
JJ
200
201```rust
bd371182 202let v = 1;
1a4d82fc 203
bd371182 204let v2 = v;
1a4d82fc 205
bd371182 206println!("v is: {}", v);
1a4d82fc
JJ
207```
208
bd371182
AL
209In this case, `v` is an `i32`, which implements the `Copy` trait. This means
210that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
211But, unlike a move, we can still use `v` afterward. This is because an `i32`
212has no pointers to data somewhere else, copying it is a full copy.
1a4d82fc 213
62682a34
SL
214All primitive types implement the `Copy` trait and their ownership is
215therefore not moved like one would assume, following the ´ownership rules´.
b039eaaf
SL
216To give an example, the two following snippets of code only compile because the
217`i32` and `bool` types implement the `Copy` trait.
62682a34
SL
218
219```rust
220fn main() {
221 let a = 5;
222
223 let _y = double(a);
224 println!("{}", a);
225}
226
227fn double(x: i32) -> i32 {
228 x * 2
229}
230```
231
232```rust
233fn main() {
234 let a = true;
235
236 let _y = change_truth(a);
237 println!("{}", a);
238}
239
240fn change_truth(x: bool) -> bool {
241 !x
242}
243```
244
92a42be0 245If we had used types that do not implement the `Copy` trait,
62682a34
SL
246we would have gotten a compile error because we tried to use a moved value.
247
248```text
249error: use of moved value: `a`
250println!("{}", a);
251 ^
252```
253
bd371182
AL
254We will discuss how to make your own types `Copy` in the [traits][traits]
255section.
1a4d82fc 256
bd371182 257[traits]: traits.html
1a4d82fc 258
bd371182 259# More than ownership
1a4d82fc 260
bd371182 261Of course, if we had to hand ownership back with every function we wrote:
1a4d82fc
JJ
262
263```rust
bd371182
AL
264fn foo(v: Vec<i32>) -> Vec<i32> {
265 // do stuff with v
1a4d82fc 266
bd371182
AL
267 // hand back ownership
268 v
1a4d82fc
JJ
269}
270```
271
bd371182 272This would get very tedious. It gets worse the more things we want to take ownership of:
1a4d82fc
JJ
273
274```rust
bd371182
AL
275fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
276 // do stuff with v1 and v2
1a4d82fc 277
bd371182
AL
278 // hand back ownership, and the result of our function
279 (v1, v2, 42)
1a4d82fc
JJ
280}
281
bd371182
AL
282let v1 = vec![1, 2, 3];
283let v2 = vec![1, 2, 3];
1a4d82fc 284
bd371182 285let (v1, v2, answer) = foo(v1, v2);
1a4d82fc
JJ
286```
287
bd371182
AL
288Ugh! The return type, return line, and calling the function gets way more
289complicated.
1a4d82fc 290
bd371182
AL
291Luckily, Rust offers a feature, borrowing, which helps us solve this problem.
292It’s the topic of the next section!
1a4d82fc 293