In Rust, mutability is at the core of its design philosophy. Mutability refers to the ability to modify a value after it has been created. Rust has two types of mutability - interior mutability and exterior mutability.
1) Interior Mutability: Interior mutability allows us to change the content of a value even if its immutable. In simpler words, we can modify a value through a shared reference without invalidating other references to the same value. Rust provides the βcellβ and βsyncβ modules to implement interior mutability.
For example, the βCell<T>β type uses interior mutability to allow us to mutate a value through a shared reference:
use std::cell::Cell;
let x = Cell::new(42);
let y = &x;
let z = &x;
x.set(24);
assert_eq!(x.get(), 24);
assert_eq!(y.get(), 24);
assert_eq!(z.get(), 24);
In this example, βxβ is a βCell<T>β that contains the value β42β. We can create multiple shared references to βxβ by binding βyβ and βzβ to it. Then we can use the βset()β method to mutate the value of βxβ. Note that the immutable shared references βyβ and βzβ are not invalidated by the mutation of βxβ.
2) Exterior Mutability: Exterior mutability differs from interior mutability in that it allows us to mutate a value through a mutable reference. Exterior mutability is the traditional form of mutability found in most programming languages. Rust requires us to explicitly mark a value as mutable to mutate its contents.
For example, the following code uses exterior mutability to mutate a value:
let mut x = 42;
let y = &mut x; // mutable reference here
*y = 13; // mutate x through y
assert_eq!(x, 13);
Here, βxβ is a mutable integer and is explicitly marked as βmutβ. We create a mutable reference to βxβ with βlet y = &mut xβ. Finally, we mutate βxβ through the mutable reference βyβ with β*y = 13β. The value of βxβ is now β13β.
The key difference between the two is that interior mutability allows runtime borrow checks while exterior mutability only allows compile-time borrows checks. Interior mutability also allows us to modify immutable data types without copying, which can be beneficial for performance reasons. While exterior mutability can make mutation more explicit and easier to reason about.