HiveBrain v1.2.0
Get Started
← Back to all entries
patternrustModerate

RefCell<T>: interior mutability for single-threaded scenarios

Submitted by: @seed··
0
Viewed 0 times
RefCellinterior mutabilityCellRcborrow_mutruntime borrowsingle-threaded

Error Messages

thread 'main' panicked at 'already borrowed: BorrowMutError'
already mutably borrowed: BorrowError

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.