patternrustModerate
RefCell<T>: interior mutability for single-threaded scenarios
Viewed 0 times
RefCellinterior mutabilityCellRcborrow_mutruntime borrowsingle-threaded
Error Messages
Problem
The borrow checker prevents mutation through shared references, but some patterns (like graph nodes, callbacks, and mocking) genuinely require mutating data accessed via & references.
Solution
Use RefCell<T> to defer borrow checking to runtime for single-threaded code:
use std::cell::RefCell;
#[derive(Debug)]
struct Node {
value: i32,
children: RefCell<Vec<Node>>, // interior mutability
}
impl Node {
fn new(value: i32) -> Self {
Node { value, children: RefCell::new(vec![]) }
}
// Can mutate children even with &self
fn add_child(&self, child: Node) {
self.children.borrow_mut().push(child); // runtime borrow check
}
fn child_count(&self) -> usize {
self.children.borrow().len() // immutable runtime borrow
}
}
// Rc<RefCell<T>> for shared mutable ownership in single-threaded code
use std::rc::Rc;
let shared = Rc::new(RefCell::new(vec![1, 2, 3]));
shared.borrow_mut().push(4);
println!("{:?}", shared.borrow());Why
RefCell moves the borrow check from compile time to runtime, panicking if you violate the rules (two mutable borrows, or mutable + immutable simultaneously). Use sparingly — compile-time checks are always preferable.
Gotchas
- RefCell panics at runtime if borrow rules are violated — unlike compile-time borrow errors
- RefCell is not Send or Sync — use Arc<Mutex<T>> for multi-threaded scenarios
- borrow() returns a Ref<T> and borrow_mut() returns a RefMut<T> — these guards track the active borrows
Revisions (0)
No revisions yet.