`RefCell<T>` enables interior mutability when the borrow checker cannot establish that access to data inside a shared structure is safe. It allows references to be borrowed and checks borrowing at runtime. Use it for a specific need, not as a routine way around the borrow checker. section 5.6
Shared nodes in a doubly linked list
A single-threaded list can define `type ItemRef<T> = Rc<RefCell<ListItem<T>>>;` and create its head with `Rc::new(RefCell::new(ListItem::new(data)))`. `Rc` provides shared ownership; `RefCell` permits mutable access within the shared node. section 5.6
Listing 5.6 Code of a doubly linked list using Rc, RefCell, and Box
use std::cell::RefCell;
use std::rc::Rc;
struct ListItem<T> {
prev: Option<ItemRef<T>>, #1
data: Box<T>, #2
next: Option<ItemRef<T>>,
}
type ItemRef<T> = Rc<RefCell<ListItem<T>>>; #3
struct DoublyLinkedList<T> {
head: ItemRef<T>,
}
impl<T> ListItem<T> {
fn new(data: T) -> Self {
ListItem {
prev: None,
data: Box::new(data), #4
next: None,
}
}
fn data(&self) -> &T {
self.data.as_ref()
}
}
impl<T> DoublyLinkedList<T> {
fn new(data: T) -> Self {
DoublyLinkedList {
head: Rc::new(RefCell::new(ListItem::new(data))),
}
}
fn append(&mut self, data: T) {
let tail = Self::find_tail(self.head.clone()); #5
let new_item = Rc::new(RefCell::new(ListItem::new(data))); #6
new_item.borrow_mut().prev = Some(tail.clone()); #7
tail.borrow_mut().next = Some(new_item); #8
}
fn head(&self) -> ItemRef<T> {
self.head.clone()
}
fn tail(&self) -> ItemRef<T> {
Self::find_tail(self.head())
}
fn find_tail(item: ItemRef<T>) -> ItemRef<T> {
if let Some(next) = &item.borrow().next { #9
Self::find_tail(next.clone()) #10
} else {
item.clone() #11
}
}
}
The listing shows how `Rc<RefCell<ListItem<T>>>` fits into the list’s node links and head. section 5.6
Choose the smallest mechanism that meets the access requirement:
- Prefer `RefCell` over `Cell` when you need to borrow references; `Cell` moves values in and out. section 5.6
- Keep `RefCell` to single-threaded use. For interior mutability across threads, use `Mutex` or `RwLock`, typically with `Arc`. section 5.6


