Quick Contact

✉
fahimkhan20148@gmail.com
📱
+971 507 286 133
Back to Notes
August 18, 2026
rustinterior-mutability

Interior Mutability in Rust

Interior mutability lets you mutate a value via a shared/read reference.

Normally, the type system guarantees there cannot be an active read reference while a write reference exists to the same value. Interior mutability enables mutating values behind a shared reference by either copying/replacing values (single-threaded cell types) or tracking borrows at runtime (borrow-checked cells or thread-safe locks).

Cell

std::cell::Cell<T> lets you mutate a value via a shared/read reference to avoid undefined behaviour; it only lets you copy T if T implements Copy or replace T. It can also be used only in a single thread.

fn f(a: &i32, b: &mut i32) {
	let before = *a;
	*b += 1;
	let after = *a;
	if before != after {
		x(); // never happens
	}
}

x is never called because Rust guarantees that both a and b can't reference the same number, as there can't be a read reference &a while we have a write reference &mut b to the same value.

But with Cell:

use std::cell::Cell;

fn f(a: &Cell<i32>, b: &Cell<i32>) {
	let before = a.get();
	b.set(b.get() + 1);
	let after = a.get();
	if before != after {
		x();
	}
}

x might be called now, as both a and b can point to the same value.

Use cell.take() when T doesn't implement Copy.

use std::cell::Cell;

fn f(vec: &Cell<Vec<i32>>) {
	let mut v = vec.take();
	v.push(4);
	vec.set(v);
}

take replaces the internal vector with an empty vector.

RefCell

std::cell::RefCell lets you take a mutable reference to the value without cloning it, at a small runtime cost. It maintains a count along with the value, and taking a mutable reference while there are shared references, or vice versa, causes a panic.

use std::cell::RefCell;

fn f(vec: &RefCell<Vec<i32>>) {
	vec.borrow_mut().push(1);
}

But both Cell and RefCell can't be sent across threads.