]> git.proxmox.com Git - rustc.git/blame - src/doc/book/2018-edition/src/ch04-02-references-and-borrowing.md
New upstream version 1.31.0~beta.4+dfsg1
[rustc.git] / src / doc / book / 2018-edition / src / ch04-02-references-and-borrowing.md
CommitLineData
83c7162d
XL
1## References and Borrowing
2
3The issue with the tuple code in Listing 4-5 is that we have to return the
4`String` to the calling function so we can still use the `String` after the
5call to `calculate_length`, because the `String` was moved into
6`calculate_length`.
7
8Here is how you would define and use a `calculate_length` function that has a
9reference to an object as a parameter instead of taking ownership of the
10value:
11
12<span class="filename">Filename: src/main.rs</span>
13
14```rust
15fn main() {
16 let s1 = String::from("hello");
17
18 let len = calculate_length(&s1);
19
20 println!("The length of '{}' is {}.", s1, len);
21}
22
23fn calculate_length(s: &String) -> usize {
24 s.len()
25}
26```
27
28First, notice that all the tuple code in the variable declaration and the
29function return value is gone. Second, note that we pass `&s1` into
30`calculate_length` and, in its definition, we take `&String` rather than
31`String`.
32
33These ampersands are *references*, and they allow you to refer to some value
34without taking ownership of it. Figure 4-5 shows a diagram.
35
36<img alt="&String s pointing at String s1" src="img/trpl04-05.svg" class="center" />
37
38<span class="caption">Figure 4-5: A diagram of `&String s` pointing at `String
39s1`</span>
40
41> Note: The opposite of referencing by using `&` is *dereferencing*, which is
42> accomplished with the dereference operator, `*`. We’ll see some uses of the
43> dereference operator in Chapter 8 and discuss details of dereferencing in
44> Chapter 15.
45
46Let’s take a closer look at the function call here:
47
48```rust
49# fn calculate_length(s: &String) -> usize {
50# s.len()
51# }
52let s1 = String::from("hello");
53
54let len = calculate_length(&s1);
55```
56
57The `&s1` syntax lets us create a reference that *refers* to the value of `s1`
58but does not own it. Because it does not own it, the value it points to will
59not be dropped when the reference goes out of scope.
60
61Likewise, the signature of the function uses `&` to indicate that the type of
62the parameter `s` is a reference. Let’s add some explanatory annotations:
63
64```rust
65fn calculate_length(s: &String) -> usize { // s is a reference to a String
66 s.len()
67} // Here, s goes out of scope. But because it does not have ownership of what
68 // it refers to, nothing happens.
69```
70
71The scope in which the variable `s` is valid is the same as any function
72parameter’s scope, but we don’t drop what the reference points to when it goes
73out of scope because we don’t have ownership. When functions have references as
74parameters instead of the actual values, we won’t need to return the values in
75order to give back ownership, because we never had ownership.
76
77We call having references as function parameters *borrowing*. As in real life,
78if a person owns something, you can borrow it from them. When you’re done, you
79have to give it back.
80
81So what happens if we try to modify something we’re borrowing? Try the code in
82Listing 4-6. Spoiler alert: it doesn’t work!
83
84<span class="filename">Filename: src/main.rs</span>
85
0bf4aa26 86```rust,ignore,does_not_compile
83c7162d
XL
87fn main() {
88 let s = String::from("hello");
89
90 change(&s);
91}
92
93fn change(some_string: &String) {
94 some_string.push_str(", world");
95}
96```
97
98<span class="caption">Listing 4-6: Attempting to modify a borrowed value</span>
99
100Here’s the error:
101
102```text
103error[E0596]: cannot borrow immutable borrowed content `*some_string` as mutable
104 --> error.rs:8:5
105 |
1067 | fn change(some_string: &String) {
107 | ------- use `&mut String` here to make mutable
1088 | some_string.push_str(", world");
109 | ^^^^^^^^^^^ cannot borrow as mutable
110```
111
112Just as variables are immutable by default, so are references. We’re not
113allowed to modify something we have a reference to.
114
115### Mutable References
116
117We can fix the error in the code from Listing 4-6 with just a small tweak:
118
119<span class="filename">Filename: src/main.rs</span>
120
121```rust
122fn main() {
123 let mut s = String::from("hello");
124
125 change(&mut s);
126}
127
128fn change(some_string: &mut String) {
129 some_string.push_str(", world");
130}
131```
132
133First, we had to change `s` to be `mut`. Then we had to create a mutable
134reference with `&mut s` and accept a mutable reference with `some_string: &mut
135String`.
136
137But mutable references have one big restriction: you can only have one mutable
138reference to a particular piece of data in a particular scope. This code will
139fail:
140
141<span class="filename">Filename: src/main.rs</span>
142
0bf4aa26 143```rust,ignore,does_not_compile
83c7162d
XL
144let mut s = String::from("hello");
145
146let r1 = &mut s;
147let r2 = &mut s;
0bf4aa26
XL
148
149println!("{}, {}", r1, r2);
83c7162d
XL
150```
151
152Here’s the error:
153
154```text
155error[E0499]: cannot borrow `s` as mutable more than once at a time
0bf4aa26 156 --> src/main.rs:5:10
83c7162d 157 |
0bf4aa26
XL
1584 | let r1 = &mut s;
159 | ------ first mutable borrow occurs here
1605 | let r2 = &mut s;
161 | ^^^^^^ second mutable borrow occurs here
1626 | println!("{}, {}", r1, r2);
163 | -- borrow later used here
83c7162d
XL
164```
165
166This restriction allows for mutation but in a very controlled fashion. It’s
167something that new Rustaceans struggle with, because most languages let you
168mutate whenever you’d like.
169
170The benefit of having this restriction is that Rust can prevent data races at
171compile time. A *data race* is similar to a race condition and happens when
172these three behaviors occur:
173
174* Two or more pointers access the same data at the same time.
175* At least one of the pointers is being used to write to the data.
176* There’s no mechanism being used to synchronize access to the data.
177
178Data races cause undefined behavior and can be difficult to diagnose and fix
179when you’re trying to track them down at runtime; Rust prevents this problem
180from happening because it won’t even compile code with data races!
181
182As always, we can use curly brackets to create a new scope, allowing for
183multiple mutable references, just not *simultaneous* ones:
184
185```rust
186let mut s = String::from("hello");
187
188{
189 let r1 = &mut s;
190
191} // r1 goes out of scope here, so we can make a new reference with no problems.
192
193let r2 = &mut s;
194```
195
196A similar rule exists for combining mutable and immutable references. This code
197results in an error:
198
0bf4aa26 199```rust,ignore,does_not_compile
83c7162d
XL
200let mut s = String::from("hello");
201
202let r1 = &s; // no problem
203let r2 = &s; // no problem
204let r3 = &mut s; // BIG PROBLEM
0bf4aa26
XL
205
206println!("{}, {}, and {}", r1, r2, r3);
83c7162d
XL
207```
208
209Here’s the error:
210
211```text
0bf4aa26
XL
212error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
213 --> src/main.rs:6:10
83c7162d 214 |
0bf4aa26
XL
2154 | let r1 = &s; // no problem
216 | -- immutable borrow occurs here
2175 | let r2 = &s; // no problem
2186 | let r3 = &mut s; // BIG PROBLEM
219 | ^^^^^^ mutable borrow occurs here
2207 |
2218 | println!("{}, {}, and {}", r1, r2, r3);
222 | -- borrow later used here
83c7162d
XL
223```
224
225Whew! We *also* cannot have a mutable reference while we have an immutable one.
226Users of an immutable reference don’t expect the values to suddenly change out
227from under them! However, multiple immutable references are okay because no one
228who is just reading the data has the ability to affect anyone else’s reading of
229the data.
230
231Even though these errors may be frustrating at times, remember that it’s the
232Rust compiler pointing out a potential bug early (at compile time rather than
233at runtime) and showing you exactly where the problem is. Then you don’t have
234to track down why your data isn’t what you thought it was.
235
236### Dangling References
237
238In languages with pointers, it’s easy to erroneously create a *dangling
239pointer*, a pointer that references a location in memory that may have been
240given to someone else, by freeing some memory while preserving a pointer to
241that memory. In Rust, by contrast, the compiler guarantees that references will
242never be dangling references: if you have a reference to some data, the
243compiler will ensure that the data will not go out of scope before the
244reference to the data does.
245
246Let’s try to create a dangling reference, which Rust will prevent with a
247compile-time error:
248
249<span class="filename">Filename: src/main.rs</span>
250
0bf4aa26 251```rust,ignore,does_not_compile
83c7162d
XL
252fn main() {
253 let reference_to_nothing = dangle();
254}
255
256fn dangle() -> &String {
257 let s = String::from("hello");
258
259 &s
260}
261```
262
263Here’s the error:
264
265```text
266error[E0106]: missing lifetime specifier
267 --> dangle.rs:5:16
268 |
2695 | fn dangle() -> &String {
270 | ^ expected lifetime parameter
271 |
272 = help: this function's return type contains a borrowed value, but there is
273 no value for it to be borrowed from
274 = help: consider giving it a 'static lifetime
275```
276
277This error message refers to a feature we haven’t covered yet: *lifetimes*.
278We’ll discuss lifetimes in detail in Chapter 10. But, if you disregard the
279parts about lifetimes, the message does contain the key to why this code is a
280problem:
281
282```text
283this function's return type contains a borrowed value, but there is no value
284for it to be borrowed from.
285```
286
287Let’s take a closer look at exactly what’s happening at each stage of our
288`dangle` code:
289
290```rust,ignore
291fn dangle() -> &String { // dangle returns a reference to a String
292
293 let s = String::from("hello"); // s is a new String
294
295 &s // we return a reference to the String, s
296} // Here, s goes out of scope, and is dropped. Its memory goes away.
297 // Danger!
298```
299
300Because `s` is created inside `dangle`, when the code of `dangle` is finished,
301`s` will be deallocated. But we tried to return a reference to it. That means
8faf50e0 302this reference would be pointing to an invalid `String`. That’s no good! Rust
83c7162d
XL
303won’t let us do this.
304
305The solution here is to return the `String` directly:
306
307```rust
308fn no_dangle() -> String {
309 let s = String::from("hello");
310
311 s
312}
313```
314
315This works without any problems. Ownership is moved out, and nothing is
316deallocated.
317
318### The Rules of References
319
320Let’s recap what we’ve discussed about references:
321
322* At any given time, you can have *either* (but not both of) one mutable
323 reference or any number of immutable references.
324* References must always be valid.
325
326Next, we’ll look at a different kind of reference: slices.