]>
Commit | Line | Data |
---|---|---|
83c7162d XL |
1 | ## References and Borrowing |
2 | ||
3 | The 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 | |
5 | call to `calculate_length`, because the `String` was moved into | |
6 | `calculate_length`. | |
7 | ||
8 | Here is how you would define and use a `calculate_length` function that has a | |
9 | reference to an object as a parameter instead of taking ownership of the | |
10 | value: | |
11 | ||
12 | <span class="filename">Filename: src/main.rs</span> | |
13 | ||
14 | ```rust | |
15 | fn 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 | ||
23 | fn calculate_length(s: &String) -> usize { | |
24 | s.len() | |
25 | } | |
26 | ``` | |
27 | ||
28 | First, notice that all the tuple code in the variable declaration and the | |
29 | function 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 | ||
33 | These ampersands are *references*, and they allow you to refer to some value | |
34 | without 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 | |
39 | s1`</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 | ||
46 | Let’s take a closer look at the function call here: | |
47 | ||
48 | ```rust | |
49 | # fn calculate_length(s: &String) -> usize { | |
50 | # s.len() | |
51 | # } | |
52 | let s1 = String::from("hello"); | |
53 | ||
54 | let len = calculate_length(&s1); | |
55 | ``` | |
56 | ||
57 | The `&s1` syntax lets us create a reference that *refers* to the value of `s1` | |
58 | but does not own it. Because it does not own it, the value it points to will | |
59 | not be dropped when the reference goes out of scope. | |
60 | ||
61 | Likewise, the signature of the function uses `&` to indicate that the type of | |
62 | the parameter `s` is a reference. Let’s add some explanatory annotations: | |
63 | ||
64 | ```rust | |
65 | fn 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 | ||
71 | The scope in which the variable `s` is valid is the same as any function | |
72 | parameter’s scope, but we don’t drop what the reference points to when it goes | |
73 | out of scope because we don’t have ownership. When functions have references as | |
74 | parameters instead of the actual values, we won’t need to return the values in | |
75 | order to give back ownership, because we never had ownership. | |
76 | ||
77 | We call having references as function parameters *borrowing*. As in real life, | |
78 | if a person owns something, you can borrow it from them. When you’re done, you | |
79 | have to give it back. | |
80 | ||
81 | So what happens if we try to modify something we’re borrowing? Try the code in | |
82 | Listing 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 |
87 | fn main() { |
88 | let s = String::from("hello"); | |
89 | ||
90 | change(&s); | |
91 | } | |
92 | ||
93 | fn 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 | ||
100 | Here’s the error: | |
101 | ||
102 | ```text | |
103 | error[E0596]: cannot borrow immutable borrowed content `*some_string` as mutable | |
104 | --> error.rs:8:5 | |
105 | | | |
106 | 7 | fn change(some_string: &String) { | |
107 | | ------- use `&mut String` here to make mutable | |
108 | 8 | some_string.push_str(", world"); | |
109 | | ^^^^^^^^^^^ cannot borrow as mutable | |
110 | ``` | |
111 | ||
112 | Just as variables are immutable by default, so are references. We’re not | |
113 | allowed to modify something we have a reference to. | |
114 | ||
115 | ### Mutable References | |
116 | ||
117 | We 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 | |
122 | fn main() { | |
123 | let mut s = String::from("hello"); | |
124 | ||
125 | change(&mut s); | |
126 | } | |
127 | ||
128 | fn change(some_string: &mut String) { | |
129 | some_string.push_str(", world"); | |
130 | } | |
131 | ``` | |
132 | ||
133 | First, we had to change `s` to be `mut`. Then we had to create a mutable | |
134 | reference with `&mut s` and accept a mutable reference with `some_string: &mut | |
135 | String`. | |
136 | ||
137 | But mutable references have one big restriction: you can only have one mutable | |
138 | reference to a particular piece of data in a particular scope. This code will | |
139 | fail: | |
140 | ||
141 | <span class="filename">Filename: src/main.rs</span> | |
142 | ||
0bf4aa26 | 143 | ```rust,ignore,does_not_compile |
83c7162d XL |
144 | let mut s = String::from("hello"); |
145 | ||
146 | let r1 = &mut s; | |
147 | let r2 = &mut s; | |
0bf4aa26 XL |
148 | |
149 | println!("{}, {}", r1, r2); | |
83c7162d XL |
150 | ``` |
151 | ||
152 | Here’s the error: | |
153 | ||
154 | ```text | |
155 | error[E0499]: cannot borrow `s` as mutable more than once at a time | |
0bf4aa26 | 156 | --> src/main.rs:5:10 |
83c7162d | 157 | | |
0bf4aa26 XL |
158 | 4 | let r1 = &mut s; |
159 | | ------ first mutable borrow occurs here | |
160 | 5 | let r2 = &mut s; | |
161 | | ^^^^^^ second mutable borrow occurs here | |
162 | 6 | println!("{}, {}", r1, r2); | |
163 | | -- borrow later used here | |
83c7162d XL |
164 | ``` |
165 | ||
166 | This restriction allows for mutation but in a very controlled fashion. It’s | |
167 | something that new Rustaceans struggle with, because most languages let you | |
168 | mutate whenever you’d like. | |
169 | ||
170 | The benefit of having this restriction is that Rust can prevent data races at | |
171 | compile time. A *data race* is similar to a race condition and happens when | |
172 | these 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 | ||
178 | Data races cause undefined behavior and can be difficult to diagnose and fix | |
179 | when you’re trying to track them down at runtime; Rust prevents this problem | |
180 | from happening because it won’t even compile code with data races! | |
181 | ||
182 | As always, we can use curly brackets to create a new scope, allowing for | |
183 | multiple mutable references, just not *simultaneous* ones: | |
184 | ||
185 | ```rust | |
186 | let 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 | ||
193 | let r2 = &mut s; | |
194 | ``` | |
195 | ||
196 | A similar rule exists for combining mutable and immutable references. This code | |
197 | results in an error: | |
198 | ||
0bf4aa26 | 199 | ```rust,ignore,does_not_compile |
83c7162d XL |
200 | let mut s = String::from("hello"); |
201 | ||
202 | let r1 = &s; // no problem | |
203 | let r2 = &s; // no problem | |
204 | let r3 = &mut s; // BIG PROBLEM | |
0bf4aa26 XL |
205 | |
206 | println!("{}, {}, and {}", r1, r2, r3); | |
83c7162d XL |
207 | ``` |
208 | ||
209 | Here’s the error: | |
210 | ||
211 | ```text | |
0bf4aa26 XL |
212 | error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable |
213 | --> src/main.rs:6:10 | |
83c7162d | 214 | | |
0bf4aa26 XL |
215 | 4 | let r1 = &s; // no problem |
216 | | -- immutable borrow occurs here | |
217 | 5 | let r2 = &s; // no problem | |
218 | 6 | let r3 = &mut s; // BIG PROBLEM | |
219 | | ^^^^^^ mutable borrow occurs here | |
220 | 7 | | |
221 | 8 | println!("{}, {}, and {}", r1, r2, r3); | |
222 | | -- borrow later used here | |
83c7162d XL |
223 | ``` |
224 | ||
225 | Whew! We *also* cannot have a mutable reference while we have an immutable one. | |
226 | Users of an immutable reference don’t expect the values to suddenly change out | |
227 | from under them! However, multiple immutable references are okay because no one | |
228 | who is just reading the data has the ability to affect anyone else’s reading of | |
229 | the data. | |
230 | ||
231 | Even though these errors may be frustrating at times, remember that it’s the | |
232 | Rust compiler pointing out a potential bug early (at compile time rather than | |
233 | at runtime) and showing you exactly where the problem is. Then you don’t have | |
234 | to track down why your data isn’t what you thought it was. | |
235 | ||
236 | ### Dangling References | |
237 | ||
238 | In languages with pointers, it’s easy to erroneously create a *dangling | |
239 | pointer*, a pointer that references a location in memory that may have been | |
240 | given to someone else, by freeing some memory while preserving a pointer to | |
241 | that memory. In Rust, by contrast, the compiler guarantees that references will | |
242 | never be dangling references: if you have a reference to some data, the | |
243 | compiler will ensure that the data will not go out of scope before the | |
244 | reference to the data does. | |
245 | ||
246 | Let’s try to create a dangling reference, which Rust will prevent with a | |
247 | compile-time error: | |
248 | ||
249 | <span class="filename">Filename: src/main.rs</span> | |
250 | ||
0bf4aa26 | 251 | ```rust,ignore,does_not_compile |
83c7162d XL |
252 | fn main() { |
253 | let reference_to_nothing = dangle(); | |
254 | } | |
255 | ||
256 | fn dangle() -> &String { | |
257 | let s = String::from("hello"); | |
258 | ||
259 | &s | |
260 | } | |
261 | ``` | |
262 | ||
263 | Here’s the error: | |
264 | ||
265 | ```text | |
266 | error[E0106]: missing lifetime specifier | |
267 | --> dangle.rs:5:16 | |
268 | | | |
269 | 5 | 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 | ||
277 | This error message refers to a feature we haven’t covered yet: *lifetimes*. | |
278 | We’ll discuss lifetimes in detail in Chapter 10. But, if you disregard the | |
279 | parts about lifetimes, the message does contain the key to why this code is a | |
280 | problem: | |
281 | ||
282 | ```text | |
283 | this function's return type contains a borrowed value, but there is no value | |
284 | for it to be borrowed from. | |
285 | ``` | |
286 | ||
287 | Let’s take a closer look at exactly what’s happening at each stage of our | |
288 | `dangle` code: | |
289 | ||
290 | ```rust,ignore | |
291 | fn 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 | ||
300 | Because `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 | 302 | this reference would be pointing to an invalid `String`. That’s no good! Rust |
83c7162d XL |
303 | won’t let us do this. |
304 | ||
305 | The solution here is to return the `String` directly: | |
306 | ||
307 | ```rust | |
308 | fn no_dangle() -> String { | |
309 | let s = String::from("hello"); | |
310 | ||
311 | s | |
312 | } | |
313 | ``` | |
314 | ||
315 | This works without any problems. Ownership is moved out, and nothing is | |
316 | deallocated. | |
317 | ||
318 | ### The Rules of References | |
319 | ||
320 | Let’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 | ||
326 | Next, we’ll look at a different kind of reference: slices. |