]> git.proxmox.com Git - rustc.git/blob - src/doc/trpl/ownership.md
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / doc / trpl / ownership.md
1 % Ownership
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, which you’re reading now
10 * [borrowing][borrowing], and their associated feature ‘references’
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 [borrowing]: references-and-borrowing.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 ownership.
41
42 # Ownership
43
44 [Variable bindings][bindings] have a property in Rust: they ‘have ownership’
45 of what they’re bound to. This means that when a binding goes out of scope,
46 Rust will free the bound resources. For example:
47
48 ```rust
49 fn foo() {
50 let v = vec![1, 2, 3];
51 }
52 ```
53
54 When `v` comes into scope, a new [`Vec<T>`][vect] is created. In this case, the
55 vector also allocates space on [the heap][heap], for the three elements. When
56 `v` goes out of scope at the end of `foo()`, Rust will clean up everything
57 related to the vector, even the heap-allocated memory. This happens
58 deterministically, at the end of the scope.
59
60 [vect]: ../std/vec/struct.Vec.html
61 [heap]: the-stack-and-the-heap.html
62 [bindings]: variable-bindings.html
63
64 # Move semantics
65
66 There’s some more subtlety here, though: Rust ensures that there is _exactly
67 one_ binding to any given resource. For example, if we have a vector, we can
68 assign it to another binding:
69
70 ```rust
71 let v = vec![1, 2, 3];
72
73 let v2 = v;
74 ```
75
76 But, if we try to use `v` afterwards, we get an error:
77
78 ```rust,ignore
79 let v = vec![1, 2, 3];
80
81 let v2 = v;
82
83 println!("v[0] is: {}", v[0]);
84 ```
85
86 It looks like this:
87
88 ```text
89 error: use of moved value: `v`
90 println!("v[0] is: {}", v[0]);
91 ^
92 ```
93
94 A similar thing happens if we define a function which takes ownership, and
95 try to use something after we’ve passed it as an argument:
96
97 ```rust,ignore
98 fn take(v: Vec<i32>) {
99 // what happens here isn’t important.
100 }
101
102 let v = vec![1, 2, 3];
103
104 take(v);
105
106 println!("v[0] is: {}", v[0]);
107 ```
108
109 Same error: ‘use of moved value’. When we transfer ownership to something else,
110 we say that we’ve ‘moved’ the thing we refer to. You don’t need some sort of
111 special annotation here, it’s the default thing that Rust does.
112
113 ## The details
114
115 The reason that we cannot use a binding after we’ve moved it is subtle, but
116 important. When we write code like this:
117
118 ```rust
119 let v = vec![1, 2, 3];
120
121 let v2 = v;
122 ```
123
124 The first line allocates memory for the vector object, `v`, and for the data it
125 contains. The vector object is stored on the [stack][sh] and contains a pointer
126 to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`,
127 it creates a copy of that pointer, for `v2`. Which means that there would be two
128 pointers to the content of the vector on the heap. It would violate Rust’s
129 safety guarantees by introducing a data race. Therefore, Rust forbids using `v`
130 after we’ve done the move.
131
132 [sh]: the-stack-and-the-heap.html
133
134 It’s also important to note that optimizations may remove the actual copy of
135 the bytes on the stack, depending on circumstances. So it may not be as
136 inefficient as it initially seems.
137
138 ## `Copy` types
139
140 We’ve established that when ownership is transferred to another binding, you
141 cannot use the original binding. However, there’s a [trait][traits] that changes this
142 behavior, and it’s called `Copy`. We haven’t discussed traits yet, but for now,
143 you can think of them as an annotation to a particular type that adds extra
144 behavior. For example:
145
146 ```rust
147 let v = 1;
148
149 let v2 = v;
150
151 println!("v is: {}", v);
152 ```
153
154 In this case, `v` is an `i32`, which implements the `Copy` trait. This means
155 that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
156 But, unlike a move, we can still use `v` afterward. This is because an `i32`
157 has no pointers to data somewhere else, copying it is a full copy.
158
159 All primitive types implement the `Copy` trait and their ownership is
160 therefore not moved like one would assume, following the ´ownership rules´.
161 To give an example, the two following snippets of code only compile because the
162 `i32` and `bool` types implement the `Copy` trait.
163
164 ```rust
165 fn main() {
166 let a = 5;
167
168 let _y = double(a);
169 println!("{}", a);
170 }
171
172 fn double(x: i32) -> i32 {
173 x * 2
174 }
175 ```
176
177 ```rust
178 fn main() {
179 let a = true;
180
181 let _y = change_truth(a);
182 println!("{}", a);
183 }
184
185 fn change_truth(x: bool) -> bool {
186 !x
187 }
188 ```
189
190 If we would have used types that do not implement the `Copy` trait,
191 we would have gotten a compile error because we tried to use a moved value.
192
193 ```text
194 error: use of moved value: `a`
195 println!("{}", a);
196 ^
197 ```
198
199 We will discuss how to make your own types `Copy` in the [traits][traits]
200 section.
201
202 [traits]: traits.html
203
204 # More than ownership
205
206 Of course, if we had to hand ownership back with every function we wrote:
207
208 ```rust
209 fn foo(v: Vec<i32>) -> Vec<i32> {
210 // do stuff with v
211
212 // hand back ownership
213 v
214 }
215 ```
216
217 This would get very tedious. It gets worse the more things we want to take ownership of:
218
219 ```rust
220 fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
221 // do stuff with v1 and v2
222
223 // hand back ownership, and the result of our function
224 (v1, v2, 42)
225 }
226
227 let v1 = vec![1, 2, 3];
228 let v2 = vec![1, 2, 3];
229
230 let (v1, v2, answer) = foo(v1, v2);
231 ```
232
233 Ugh! The return type, return line, and calling the function gets way more
234 complicated.
235
236 Luckily, Rust offers a feature, borrowing, which helps us solve this problem.
237 It’s the topic of the next section!
238
239
240
241
242
243
244
245
246
247
248