Rc<RefCell<T>> combines shared ownership with checked interior mutation in single-threaded code.

Program

Play the program to choose an increment, clone a shared owner, and update the value through the clone.

delta
shared_refcell.rs
Replay: real traced execution (multi-file project)
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let delta = 4;
    let shared = Rc::new(RefCell::new(10));
    let owner = Rc::clone(&shared);
    *owner.borrow_mut() += delta;
    let value = *shared.borrow();
    println!("{value}");
}
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let delta = 2;
    let shared = Rc::new(RefCell::new(10));
    let owner = Rc::clone(&shared);
    *owner.borrow_mut() += delta;
    let value = *shared.borrow();
    println!("{value}");
}
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let delta = 6;
    let shared = Rc::new(RefCell::new(10));
    let owner = Rc::clone(&shared);
    *owner.borrow_mut() += delta;
    let value = *shared.borrow();
    println!("{value}");
}
  1. delta ← 4, shared ← RefCell { value: 10 }, owner ← RefCell { value: 10 }

    4fn main() {5    let delt→ 4a = 4; //@delta=4, 2, 66    let share→ RefCell { value: 10 }d = Rc::new(RefCell::new(10));7    let owne→ RefCell { value: 10 }r = Rc::clone(&shareRefCell { value: 10 }d);8    *owner.borrow_mut() += delt4a;9    let valu→ 14e = *shared.borrow();10    println!("{value}");11}
    output14
  1. delta ← 2, shared ← RefCell { value: 10 }, owner ← RefCell { value: 10 }

    4fn main() {5    let delt→ 2a = 2;6    let share→ RefCell { value: 10 }d = Rc::new(RefCell::new(10));7    let owne→ RefCell { value: 10 }r = Rc::clone(&shareRefCell { value: 10 }d);8    *owner.borrow_mut() += delt2a;9    let valu→ 12e = *shared.borrow();10    println!("{value}");11}
    output12
  1. delta ← 6, shared ← RefCell { value: 10 }, owner ← RefCell { value: 10 }

    4fn main() {5    let delt→ 6a = 6;6    let share→ RefCell { value: 10 }d = Rc::new(RefCell::new(10));7    let owne→ RefCell { value: 10 }r = Rc::clone(&shareRefCell { value: 10 }d);8    *owner.borrow_mut() += delt6a;9    let valu→ 16e = *shared.borrow();10    println!("{value}");11}
    output16
Rc<RefCell<T>> `Rc` shares ownership, while `RefCell` allows checked mutation of the inner value.
clone handle `Rc::clone` creates another owner of the same allocation.
mutable borrow `borrow_mut` temporarily opens the inner value for mutation.