Skip to content

Interior Mutability | Rust - Wyatt's Notes

flowchart TD
    A[Interior Mutability] --> B[Key Concepts]
    A --> C[Core Principles]
    A --> D[Practical Applications]
    B --> E[Fundamental definitions]
    C --> F[Design patterns]
    D --> G[Real-world usage]

Rust’s borrowing rules state that a shared reference (&T) is immutable — you cannot modify the Data through it. This is a compile-time guarantee that prevents data races and enables safe Concurrency. However, there are legitimate cases where you need to mutate data through a shared Reference. Interior mutability types provide this capability while maintaining safety guarantees.

The core tension: &T promises the caller that the data will not change, but sometimes the data Needs to change in response to operations that only have a shared reference available. Interior Mutability resolves this by moving the mutation check from compile time to runtime (for Single-threaded types) or by using synchronization primitives (for multi-threaded types).

UnsafeCell<T> is the foundation of all interior mutability in Rust. It is the only type in the Standard library that allows you to obtain a mutable reference to its interior through a shared Reference. All other interior mutability types (Cell``RefCell``Mutex``RwLock) are built on Top of UnsafeCell.

use std::cell::UnsafeCell;
struct Counter {
value: UnsafeCell<i32>,
}
impl Counter {
fn new(value: i32) -> Self {
Counter {
value: UnsafeCell::new(value),
}
}
fn increment(&self) {
unsafe {
*self.value.get() += 1;
}
}
fn get(&self) -> i32 {
unsafe { *self.value.get() }
}
}