# `RefCell` - Interior Mutability Pattern `Interior Mutability` is a design pattern, mutate data even if there are immutable references. Normally would require `unsafe` code (Chapter 19). This pattern makes it safe and in compliance with the borrowing rules at runtime. ## Enforcing Borrowing Rules at Runtime `RefCell` Represent SINGLE ownership of the data. It is basically a `Box` but the borrowing rules are checked in runtime instead of compile time? Circumvent some operations that are not allowed at compile time, but safe at runtime. It is actually quite impossible to check for all possible states and errors a complex program may go through, given the amount of inputs and states it goes through, so some seemingly safe might be unsafe and some conservatively unsafe will be safe. `RefCell` is SingleThreaded only (Chapter 16 for multithreading). ### Box Rc or RefCell *Box* - Single Owner - Allows immutable and mutable borrows at compile time *Rc* - Multiple Owners - Only immutable borrows at compile time *RefCell* - Single Owner - Allows immutable and mutable borrows, checked in RUNTIME - Allows mutation of value even if it is immutable ## Interior Mutability: Mutable Borrow to Immutable Value ```rust let x = 5; // Immutable value let y = &mut x; // Illegal: Mutable borrow of immutable value ``` `RefCell` does not circumvent this, it will `panic!` if the rules are broken at runtime. Why and How is it useful? ### Ex: Mock Objects `test double` = Use a type in place of another. `Mock objects` are types that record what happens in a test. The exmaple implements the library that tracks the amount of messages a user has sent, limited by their quota. I will not delve deep in to implementation because it seems complicated but will try on things that seems hard to understand at first glance): ```rust pub trait Messenger { fn send(&self, msg: &str); } // LimitTracker Holds reference of a user(messenger), with a lifetime at least equal to the current tracker using it pub struct LimitTracker<'a, T: Messenger> { messenger: &'a T, value: usize, max: usize, } impl<'a, T> LimitTracker<'a, T> where T: Messenger, // Implementation specific for Types that implement Messenger trait { // New function for ease of use pub fn new(messenger: &T, max: usize) -> LimitTracker { LimitTracker { messenger, value: 0, max, } } // Checks that the user has not passed their quota and sends a warning pub fn set_value(&mut self, value: usize) { self.value = value; let percentage_of_max = self.value as f64 / self.max as f64; if percentage_of_max >= 1.0 { self.messenger.send("Error: You are over your quota!"); } else if percentage_of_max >= 0.9 { self.messenger .send("Urgent warning: You've used up over 90% of your quota!"); } else if percentage_of_max >= 0.75 { self.messenger .send("Warning: You've used up over 75% of your quota!"); } } } ``` Then the tests which will fail to compile: ```rust [cfg(test)] mod tests { use super::*; // Define test struct that holds the messages, not send them struct MockMessenger { sent_messages: Vec, } impl MockMessenger { fn new() -> MockMessenger { MockMessenger { sent_messages: vec![], } } } // Implement the Messenger trait // This does not compile, because &self is immutable and we are doing mutable operations to `sent_messages: Vec` impl Messenger for MockMessenger { fn send(&self, message: &str) { self.sent_messages.push(String::from(message)); } } #[test] fn it_sends_an_over_75_percent_warning_message() { let mock_messenger = MockMessenger::new(); let mut limit_tracker = LimitTracker::new(&mock_messenger, 100); limit_tracker.set_value(80); assert_eq!(mock_messenger.sent_messages.len(), 1); } } ``` At compile time this is illegal, we are mutating the `Vec` which does not have a mutable borrow. #### Allowing mutability the wrong way If we wanted to allow all of this, we would have to change almost every function declaration to use mutable borrows, which besides making it more verbose it would then limit other usages as a signle mutable borrow is not allowed if another variable holds any type of borrow. ```rust pub trait Messenger { fn send(&mut self, msg: &str); } pub struct LimitTracker<'a, T: Messenger> { messenger: &'a mut T, value: usize, max: usize, } impl<'a, T> LimitTracker<'a, T> where T: Messenger, { pub fn new(messenger: &mut T, max: usize) -> LimitTracker { LimitTracker { messenger, value: 0, max, } } pub fn set_value(&mut self, value: usize) { self.value = value; let percentage_of_max = self.value as f64 / self.max as f64; if percentage_of_max >= 1.0 { self.messenger.send("Error: You are over your quota!"); } else if percentage_of_max >= 0.9 { self.messenger .send("Urgent warning: You've used up over 90% of your quota!"); } else if percentage_of_max >= 0.75 { self.messenger .send("Warning: You've used up over 75% of your quota!"); } } } #[cfg(test)] mod tests { use super::*; struct MockMessenger { sent_messages: Vec, } impl MockMessenger { fn new() -> MockMessenger { MockMessenger { sent_messages: vec![], } } } impl Messenger for MockMessenger { fn send(&mut self, message: &str) { self.sent_messages.push(String::from(message)); } } #[test] fn it_sends_an_over_75_percent_warning_message() { let mut mock_messenger = MockMessenger::new(); let mut limit_tracker = LimitTracker::new(&mut mock_messenger, 100); limit_tracker.set_value(80); assert_eq!(mock_messenger.sent_messages.len(), 1); } } ``` #### Using `RefCell` ```rust ``` This does work, `RefCell` checks at runtime if the borrows are legal. ### How does `RefCell` Track Borrows? We use the `borrow` and `borrow_mut` methods, which return `Ref` and `RefMut` respectively which implement the `Deref` trait, aka being treated as regular references. The functions increase count of immutable borrows, which decreases when the `Ref/RefMut` go out of scope with `Drop` trait. If a mutable borrow is used, borrows in the same scope will be illegal and `panic!`. ### Multiple Owners of mutable data `Rc + RefCell` `Rc>` Can have multiple owners and each can get mutable borrow access of it. It will still be bound by the Runtime check thus being safe. ```rust // Update List example #[derive(Debug)] enum List { Cons(Rc>, Rc), Nil, } use List::*; use std::cell::RefCell; use std::rc::Rc; fn main() { let value = Rc::new(RefCell::new(5)); let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil))); let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a)); let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a)); *value.borrow_mut() += 10; println!("a after = {:?}", a); println!("b after = {:?}", b); println!("c after = {:?}", c); } ``` In the previous `List` example: a,b,c get immutable borrows of `Rc`, no one has actually borrowed the `RefCell`. Then we can still access the `RefCell` mutably, and be correct.