mutability (or the ability to change something) is not a default

let x = 5;
 
x = 6; // ERROR!!

but with mut

let mut x = 5;
 
x = 6; // no problem

the x variable has a full name of “mutable variable binding” in Rust

when a binding in mutable, you can change what the binding is pointing to.

so in the last example above: the value of x is not changing, it’s just pointing to a new i32.

you can also create a reference to a binding

let mut x = 5;
 
let y = &mut x;

but if you want to use the reference to change it (write; not just read):

you need a mutable reference: &mut

but here’s the distinction;

y is an immutable binding to a mutable reference. so you can’t change what y is pointing to like: y = &mut z; but you can edit the x’s value like this: *y = 5; (accessing x’s value by dereferencing)

but if you need both;

let mut x = 5;
 
let mut y = &mut x;

the use of mut is part of a pattern.

so it’s uses are pretty widespread:

let (mut x, y) = (5, 6);
fn foo(mut x: i32) {}

Interior vs Exterior Mutability


this comparison and difference boils down to:

The Reference rules from borrowing:

  • one of more references (&T) to a resource
  • exactly one mutable reference (&mut T)

the real definition of immutability: is this safe to have two pointers to?

take this for example:

use std::sync::Arc;
 
let x = Arc::new(5);
let y = x.clone();

when we call clone(), Arc needs to update the reference count ([[Arc|Arc is just a reference counter.]])

Arc is able to hand out a reference (&T) to y with clone() but if it handed out &mut T then there would be a problem.

but here is an example of interior mutability

use std::cell::RefCell;
 
let x = RefCell::new(42);
 
let y = x.borrow_mut();

in this case RefCell hands out a &mut but if you tried to use x.borrow_mut again with new variable binding then the program would panic!

RefCell enforces Rust’s borrowing rules at runtime, and panic’s if they’re violated.

Field-Level Mutability


mutability is either a property of a borrow (&mut T) or a binding (let mut).

for example you cannot have a immutable and mutable field inside a struct definition.

struct Point {
	x: i32,
	mut y: i32, // Nope this will not compile
}

the mutability of a struct is in it’s binding:

struct Point {
    x: i32,
    y: i32,
}
 
let mut a = Point { x: 5, y: 6 };
 
a.x = 10;
 
let b = Point { x: 5, y: 6 };
 
b.x = 10; // Error: cannot assign to immutable field `b.x`.

however by using [[Cell]], you can emulate field-level mutability

use std::cell::Cell;
 
struct Point {
    x: i32,
    y: Cell<i32>,
}
 
let point = Point { x: 5, y: Cell::new(6) };
 
point.y.set(7);
 
println!("y: {:?}", point.y);