Why interior mutability

Rust's usual rule is: you can have many `&T` or one `&mut T`, never both. That's great for safety but sometimes you need to mutate a field through `&self` — for caching, lazy initialisation, or implementing observer patterns. Interior-mutability cells move the borrow check from compile time to runtime, letting you mutate through `&` while still preventing aliased mutation.

Cell vs RefCell

`Cell<T>` works for `Copy` types (and `take` / `replace` for non-Copy): it lets you swap the entire value for a new one but never hands out a reference. `RefCell<T>` works for any type and hands out RAII borrow guards via `borrow` / `borrow_mut`; it tracks the borrow count at runtime and panics on aliasing violations.

For deeper background, see a complete cheat-sheet of std collection complexities for the broader context behind this section.

OnceCell and lazy init

`OnceCell<T>` is the single-threaded counterpart to `OnceLock<T>`. Use `get_or_init` to compute and cache a value the first time it's requested. Perfect for memoising expensive read-only state in a struct that doesn't need to be `Send`.

When to reach for unsafe instead

If you find yourself wrapping every field in `RefCell`, the design probably wants `&mut self` plumbed through more aggressively. Interior mutability is a precise tool for specific patterns; it's not a way to dodge ownership.

For deeper background, see the official Rust API guidelines for module-level design for the broader context behind this section.

Common pitfalls

Holding a `RefMut` across a function call that re-enters the cell (re-entrancy) panics at runtime. Cell types are `!Sync` — never share a `RefCell` across threads; use `Mutex` instead.