]> git.proxmox.com Git - rustc.git/blob - src/doc/book/src/ch15-05-interior-mutability.md
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / src / ch15-05-interior-mutability.md
1 ## `RefCell<T>` and the Interior Mutability Pattern
2
3 *Interior mutability* is a design pattern in Rust that allows you to mutate
4 data even when there are immutable references to that data; normally, this
5 action is disallowed by the borrowing rules. To mutate data, the pattern uses
6 `unsafe` code inside a data structure to bend Rust’s usual rules that govern
7 mutation and borrowing. Unsafe code indicates to the compiler that we’re
8 checking the rules manually instead of relying on the compiler to check them
9 for us; we will discuss unsafe code more in Chapter 19.
10
11 We can use types that use the interior mutability pattern only when we can
12 ensure that the borrowing rules will be followed at runtime, even though the
13 compiler can’t guarantee that. The `unsafe` code involved is then wrapped in a
14 safe API, and the outer type is still immutable.
15
16 Let’s explore this concept by looking at the `RefCell<T>` type that follows the
17 interior mutability pattern.
18
19 ### Enforcing Borrowing Rules at Runtime with `RefCell<T>`
20
21 Unlike `Rc<T>`, the `RefCell<T>` type represents single ownership over the data
22 it holds. So, what makes `RefCell<T>` different from a type like `Box<T>`?
23 Recall the borrowing rules you learned in Chapter 4:
24
25 * At any given time, you can have *either* (but not both) one mutable reference
26 or any number of immutable references.
27 * References must always be valid.
28
29 With references and `Box<T>`, the borrowing rules’ invariants are enforced at
30 compile time. With `RefCell<T>`, these invariants are enforced *at runtime*.
31 With references, if you break these rules, you’ll get a compiler error. With
32 `RefCell<T>`, if you break these rules, your program will panic and exit.
33
34 The advantages of checking the borrowing rules at compile time are that errors
35 will be caught sooner in the development process, and there is no impact on
36 runtime performance because all the analysis is completed beforehand. For those
37 reasons, checking the borrowing rules at compile time is the best choice in the
38 majority of cases, which is why this is Rust’s default.
39
40 The advantage of checking the borrowing rules at runtime instead is that
41 certain memory-safe scenarios are then allowed, where they would’ve been
42 disallowed by the compile-time checks. Static analysis, like the Rust compiler,
43 is inherently conservative. Some properties of code are impossible to detect by
44 analyzing the code: the most famous example is the Halting Problem, which is
45 beyond the scope of this book but is an interesting topic to research.
46
47 Because some analysis is impossible, if the Rust compiler can’t be sure the
48 code complies with the ownership rules, it might reject a correct program; in
49 this way, it’s conservative. If Rust accepted an incorrect program, users
50 wouldn’t be able to trust in the guarantees Rust makes. However, if Rust
51 rejects a correct program, the programmer will be inconvenienced, but nothing
52 catastrophic can occur. The `RefCell<T>` type is useful when you’re sure your
53 code follows the borrowing rules but the compiler is unable to understand and
54 guarantee that.
55
56 Similar to `Rc<T>`, `RefCell<T>` is only for use in single-threaded scenarios
57 and will give you a compile-time error if you try using it in a multithreaded
58 context. We’ll talk about how to get the functionality of `RefCell<T>` in a
59 multithreaded program in Chapter 16.
60
61 Here is a recap of the reasons to choose `Box<T>`, `Rc<T>`, or `RefCell<T>`:
62
63 * `Rc<T>` enables multiple owners of the same data; `Box<T>` and `RefCell<T>`
64 have single owners.
65 * `Box<T>` allows immutable or mutable borrows checked at compile time; `Rc<T>`
66 allows only immutable borrows checked at compile time; `RefCell<T>` allows
67 immutable or mutable borrows checked at runtime.
68 * Because `RefCell<T>` allows mutable borrows checked at runtime, you can
69 mutate the value inside the `RefCell<T>` even when the `RefCell<T>` is
70 immutable.
71
72 Mutating the value inside an immutable value is the *interior mutability*
73 pattern. Let’s look at a situation in which interior mutability is useful and
74 examine how it’s possible.
75
76 ### Interior Mutability: A Mutable Borrow to an Immutable Value
77
78 A consequence of the borrowing rules is that when you have an immutable value,
79 you can’t borrow it mutably. For example, this code won’t compile:
80
81 ```rust,ignore,does_not_compile
82 {{#rustdoc_include ../listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/src/main.rs}}
83 ```
84
85 If you tried to compile this code, you’d get the following error:
86
87 ```console
88 {{#include ../listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/output.txt}}
89 ```
90
91 However, there are situations in which it would be useful for a value to mutate
92 itself in its methods but appear immutable to other code. Code outside the
93 value’s methods would not be able to mutate the value. Using `RefCell<T>` is
94 one way to get the ability to have interior mutability, but `RefCell<T>`
95 doesn’t get around the borrowing rules completely: the borrow checker in the
96 compiler allows this interior mutability, and the borrowing rules are checked
97 at runtime instead. If you violate the rules, you’ll get a `panic!` instead of
98 a compiler error.
99
100 Let’s work through a practical example where we can use `RefCell<T>` to mutate
101 an immutable value and see why that is useful.
102
103 #### A Use Case for Interior Mutability: Mock Objects
104
105 Sometimes during testing a programmer will use a type in place of another type,
106 in order to observe particular behavior and assert it's implemented correctly.
107 This placeholder type is called a *test double*. Think of it in the sense of a
108 "stunt double" in filmmaking, where a person steps in and substitutes for an
109 actor to do a particular tricky scene. Test doubles stand in for other types
110 when we're running tests. *Mock objects* are specific types of test doubles
111 that record what happens during a test so you can assert that the correct
112 actions took place.
113
114 Rust doesn’t have objects in the same sense as other languages have objects,
115 and Rust doesn’t have mock object functionality built into the standard library
116 as some other languages do. However, you can definitely create a struct that
117 will serve the same purposes as a mock object.
118
119 Here’s the scenario we’ll test: we’ll create a library that tracks a value
120 against a maximum value and sends messages based on how close to the maximum
121 value the current value is. This library could be used to keep track of a
122 user’s quota for the number of API calls they’re allowed to make, for example.
123
124 Our library will only provide the functionality of tracking how close to the
125 maximum a value is and what the messages should be at what times. Applications
126 that use our library will be expected to provide the mechanism for sending the
127 messages: the application could put a message in the application, send an
128 email, send a text message, or something else. The library doesn’t need to know
129 that detail. All it needs is something that implements a trait we’ll provide
130 called `Messenger`. Listing 15-20 shows the library code:
131
132 <span class="filename">Filename: src/lib.rs</span>
133
134 ```rust,noplayground
135 {{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-20/src/lib.rs}}
136 ```
137
138 <span class="caption">Listing 15-20: A library to keep track of how close a
139 value is to a maximum value and warn when the value is at certain levels</span>
140
141 One important part of this code is that the `Messenger` trait has one method
142 called `send` that takes an immutable reference to `self` and the text of the
143 message. This trait is the interface our mock object needs to implement so that
144 the mock can be used in the same way a real object is. The other important part
145 is that we want to test the behavior of the `set_value` method on the
146 `LimitTracker`. We can change what we pass in for the `value` parameter, but
147 `set_value` doesn’t return anything for us to make assertions on. We want to be
148 able to say that if we create a `LimitTracker` with something that implements
149 the `Messenger` trait and a particular value for `max`, when we pass different
150 numbers for `value`, the messenger is told to send the appropriate messages.
151
152 We need a mock object that, instead of sending an email or text message when we
153 call `send`, will only keep track of the messages it’s told to send. We can
154 create a new instance of the mock object, create a `LimitTracker` that uses the
155 mock object, call the `set_value` method on `LimitTracker`, and then check that
156 the mock object has the messages we expect. Listing 15-21 shows an attempt to
157 implement a mock object to do just that, but the borrow checker won’t allow it:
158
159 <span class="filename">Filename: src/lib.rs</span>
160
161 ```rust,ignore,does_not_compile
162 {{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-21/src/lib.rs:here}}
163 ```
164
165 <span class="caption">Listing 15-21: An attempt to implement a `MockMessenger`
166 that isn’t allowed by the borrow checker</span>
167
168 This test code defines a `MockMessenger` struct that has a `sent_messages`
169 field with a `Vec` of `String` values to keep track of the messages it’s told
170 to send. We also define an associated function `new` to make it convenient to
171 create new `MockMessenger` values that start with an empty list of messages. We
172 then implement the `Messenger` trait for `MockMessenger` so we can give a
173 `MockMessenger` to a `LimitTracker`. In the definition of the `send` method, we
174 take the message passed in as a parameter and store it in the `MockMessenger`
175 list of `sent_messages`.
176
177 In the test, we’re testing what happens when the `LimitTracker` is told to set
178 `value` to something that is more than 75 percent of the `max` value. First, we
179 create a new `MockMessenger`, which will start with an empty list of messages.
180 Then we create a new `LimitTracker` and give it a reference to the new
181 `MockMessenger` and a `max` value of 100. We call the `set_value` method on the
182 `LimitTracker` with a value of 80, which is more than 75 percent of 100. Then
183 we assert that the list of messages that the `MockMessenger` is keeping track
184 of should now have one message in it.
185
186 However, there’s one problem with this test, as shown here:
187
188 ```console
189 {{#include ../listings/ch15-smart-pointers/listing-15-21/output.txt}}
190 ```
191
192 We can’t modify the `MockMessenger` to keep track of the messages, because the
193 `send` method takes an immutable reference to `self`. We also can’t take the
194 suggestion from the error text to use `&mut self` instead, because then the
195 signature of `send` wouldn’t match the signature in the `Messenger` trait
196 definition (feel free to try and see what error message you get).
197
198 This is a situation in which interior mutability can help! We’ll store the
199 `sent_messages` within a `RefCell<T>`, and then the `send` method will be
200 able to modify `sent_messages` to store the messages we’ve seen. Listing 15-22
201 shows what that looks like:
202
203 <span class="filename">Filename: src/lib.rs</span>
204
205 ```rust,noplayground
206 {{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-22/src/lib.rs:here}}
207 ```
208
209 <span class="caption">Listing 15-22: Using `RefCell<T>` to mutate an inner
210 value while the outer value is considered immutable</span>
211
212 The `sent_messages` field is now of type `RefCell<Vec<String>>` instead of
213 `Vec<String>`. In the `new` function, we create a new `RefCell<Vec<String>>`
214 instance around the empty vector.
215
216 For the implementation of the `send` method, the first parameter is still an
217 immutable borrow of `self`, which matches the trait definition. We call
218 `borrow_mut` on the `RefCell<Vec<String>>` in `self.sent_messages` to get a
219 mutable reference to the value inside the `RefCell<Vec<String>>`, which is the
220 vector. Then we can call `push` on the mutable reference to the vector to keep
221 track of the messages sent during the test.
222
223 The last change we have to make is in the assertion: to see how many items are
224 in the inner vector, we call `borrow` on the `RefCell<Vec<String>>` to get an
225 immutable reference to the vector.
226
227 Now that you’ve seen how to use `RefCell<T>`, let’s dig into how it works!
228
229 #### Keeping Track of Borrows at Runtime with `RefCell<T>`
230
231 When creating immutable and mutable references, we use the `&` and `&mut`
232 syntax, respectively. With `RefCell<T>`, we use the `borrow` and `borrow_mut`
233 methods, which are part of the safe API that belongs to `RefCell<T>`. The
234 `borrow` method returns the smart pointer type `Ref<T>`, and `borrow_mut`
235 returns the smart pointer type `RefMut<T>`. Both types implement `Deref`, so we
236 can treat them like regular references.
237
238 The `RefCell<T>` keeps track of how many `Ref<T>` and `RefMut<T>` smart
239 pointers are currently active. Every time we call `borrow`, the `RefCell<T>`
240 increases its count of how many immutable borrows are active. When a `Ref<T>`
241 value goes out of scope, the count of immutable borrows goes down by one. Just
242 like the compile-time borrowing rules, `RefCell<T>` lets us have many immutable
243 borrows or one mutable borrow at any point in time.
244
245 If we try to violate these rules, rather than getting a compiler error as we
246 would with references, the implementation of `RefCell<T>` will panic at
247 runtime. Listing 15-23 shows a modification of the implementation of `send` in
248 Listing 15-22. We’re deliberately trying to create two mutable borrows active
249 for the same scope to illustrate that `RefCell<T>` prevents us from doing this
250 at runtime.
251
252 <span class="filename">Filename: src/lib.rs</span>
253
254 ```rust,ignore,panics
255 {{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-23/src/lib.rs:here}}
256 ```
257
258 <span class="caption">Listing 15-23: Creating two mutable references in the
259 same scope to see that `RefCell<T>` will panic</span>
260
261 We create a variable `one_borrow` for the `RefMut<T>` smart pointer returned
262 from `borrow_mut`. Then we create another mutable borrow in the same way in the
263 variable `two_borrow`. This makes two mutable references in the same scope,
264 which isn’t allowed. When we run the tests for our library, the code in Listing
265 15-23 will compile without any errors, but the test will fail:
266
267 ```console
268 {{#include ../listings/ch15-smart-pointers/listing-15-23/output.txt}}
269 ```
270
271 Notice that the code panicked with the message `already borrowed:
272 BorrowMutError`. This is how `RefCell<T>` handles violations of the borrowing
273 rules at runtime.
274
275 Choosing to catch borrowing errors at runtime rather than compile time, as
276 we've done here, means you'd potentially be finding mistakes in your code later
277 in the development process: possibly not until your code was deployed to
278 production. Also, your code would incur a small runtime performance penalty as
279 a result of keeping track of the borrows at runtime rather than compile time.
280 However, using `RefCell<T>` makes it possible to write a mock object that can
281 modify itself to keep track of the messages it has seen while you’re using it
282 in a context where only immutable values are allowed. You can use `RefCell<T>`
283 despite its trade-offs to get more functionality than regular references
284 provide.
285
286 ### Having Multiple Owners of Mutable Data by Combining `Rc<T>` and `RefCell<T>`
287
288 A common way to use `RefCell<T>` is in combination with `Rc<T>`. Recall that
289 `Rc<T>` lets you have multiple owners of some data, but it only gives immutable
290 access to that data. If you have an `Rc<T>` that holds a `RefCell<T>`, you can
291 get a value that can have multiple owners *and* that you can mutate!
292
293 For example, recall the cons list example in Listing 15-18 where we used
294 `Rc<T>` to allow multiple lists to share ownership of another list. Because
295 `Rc<T>` holds only immutable values, we can’t change any of the values in the
296 list once we’ve created them. Let’s add in `RefCell<T>` to gain the ability to
297 change the values in the lists. Listing 15-24 shows that by using a
298 `RefCell<T>` in the `Cons` definition, we can modify the value stored in all
299 the lists:
300
301 <span class="filename">Filename: src/main.rs</span>
302
303 ```rust
304 {{#rustdoc_include ../listings/ch15-smart-pointers/listing-15-24/src/main.rs}}
305 ```
306
307 <span class="caption">Listing 15-24: Using `Rc<RefCell<i32>>` to create a
308 `List` that we can mutate</span>
309
310 We create a value that is an instance of `Rc<RefCell<i32>>` and store it in a
311 variable named `value` so we can access it directly later. Then we create a
312 `List` in `a` with a `Cons` variant that holds `value`. We need to clone
313 `value` so both `a` and `value` have ownership of the inner `5` value rather
314 than transferring ownership from `value` to `a` or having `a` borrow from
315 `value`.
316
317 We wrap the list `a` in an `Rc<T>` so when we create lists `b` and `c`, they
318 can both refer to `a`, which is what we did in Listing 15-18.
319
320 After we’ve created the lists in `a`, `b`, and `c`, we want to add 10 to the
321 value in `value`. We do this by calling `borrow_mut` on `value`, which uses the
322 automatic dereferencing feature we discussed in Chapter 5 (see the section
323 [“Where’s the `->` Operator?”][wheres-the---operator]<!-- ignore -->) to
324 dereference the `Rc<T>` to the inner `RefCell<T>` value. The `borrow_mut`
325 method returns a `RefMut<T>` smart pointer, and we use the dereference operator
326 on it and change the inner value.
327
328 When we print `a`, `b`, and `c`, we can see that they all have the modified
329 value of 15 rather than 5:
330
331 ```console
332 {{#include ../listings/ch15-smart-pointers/listing-15-24/output.txt}}
333 ```
334
335 This technique is pretty neat! By using `RefCell<T>`, we have an outwardly
336 immutable `List` value. But we can use the methods on `RefCell<T>` that provide
337 access to its interior mutability so we can modify our data when we need to.
338 The runtime checks of the borrowing rules protect us from data races, and it’s
339 sometimes worth trading a bit of speed for this flexibility in our data
340 structures. Note that `RefCell<T>` does not work for multithreaded code!
341 `Mutex<T>` is the thread-safe version of `RefCell<T>` and we’ll discuss
342 `Mutex<T>` in Chapter 16.
343
344 [wheres-the---operator]: ch05-03-method-syntax.html#wheres-the---operator