RefCell<T>
- Rust course
- Intermediate
- Lesson 36/115
- 4 min
Learn runtime borrowing with RefCell<T>.
RefCell<T>
Borrowing rules are normally checked at compile time. RefCell<T> checks the same rules at runtime, so even data behind an immutable reference can be changed. This is called interior mutability:
use std::cell::RefCell;
let c = RefCell::new(vec![1, 2]); // c isn't mut!
c.borrow_mut().push(3);
println!("{:?}", c.borrow()); // [1, 2, 3]The rules are the same (either many readers or one writer); the difference is that a violation is a panic instead of a compile error.
Ref and RefMut
borrow() returns a Ref<T> and borrow_mut() a RefMut<T>. When these go out of scope, the borrow record is cleared. That's why keeping borrows short matters:
let c = RefCell::new(String::from("a"));
c.borrow_mut().push('b'); // temporary RefMut, ends at the end of the line
let uzunluk = c.borrow().len(); // a new read
println!("{uzunluk}"); // 2Practice Changing an immutable variable
Declare let c = RefCell::new(vec![1, 2]); (without mut). Add 3 with borrow_mut; then print the vector and its length with borrow, separated by a space.
Starter code
use std::cell::RefCell;
fn main() {
// buraya yaz
}Sample solution
use std::cell::RefCell;
fn main() {
let c = RefCell::new(vec![1, 2]);
c.borrow_mut().push(3);
println!("{:?} {}", c.borrow(), c.borrow().len());
}Expected output
[1, 2, 3] 3
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 When is RefCell preferred?
- Never
- For mutations the compiler can't prove but you know are safe Correct answer
- Always, because it's faster
- For sharing across threads
Explanation: RefCell has a small runtime cost and is single-threaded; its cross-thread counterpart is Mutex.
2 Mutable borrow
let c = RefCell::new(vec![1, 2]);
c.____().push(3);
let c = RefCell::new(vec![1, 2]);
c.borrow_mut().push(3);
Explanation: borrow_mut gives a runtime-checked mutable borrow.
3 Method and return
| Term | Meaning |
|---|---|
c.borrow() |
Ref<T> |
c.borrow_mut() |
RefMut<T> |
Two borrow_mut at once |
Panic |
c.into_inner() |
T (ownership) |