Skip to content
Select theme

How to change what a mutable reference points at

Short answer: To put a new value where a &mut reference points, write through it: *r = other;. The mut does not go on the binding — let r = &mut total; is already writable, because the mutability lives in the reference’s type, &mut, not in the variable that holds it. Adding mut to the binding means something else entirely: that the reference itself may be re-pointed at a different place.

Start from a fresh project — cargo new ref-point, then replace src/main.rs with the whole of each file below.

total = 10

The assignment *r = 10 does not touch r at all. r still holds the same address; what changed is the memory it aims at. And note the bindings: total is mut, r is not, yet the write compiles without a murmur.

That is what mut on a binding actually controls: whether the name can be assigned again. *r = 10 never assigns to r — it dereferences and assigns through it, so mut r would be beside the point.

For the borrow to be a &mut at all, the owner must allow mutation:

error[E0596]: cannot borrow `total` as mutable, as it is not declared as mutable
--> src/main.rs:3:13
|
3 | let r = &mut total;
| ^^^^^^^^^^ cannot borrow as mutable
|
help: consider changing this to be mutable
|
2 | let mut total = 3;
| +++
For more information about this error, try `rustc --explain E0596`.

The complaint is about total, not r: a value that has promised never to change cannot hand out a write handle. So the mutability is anchored in two places — the owner’s mut makes the value writable, the &mut type makes this particular borrow a writer — and the binding that holds the reference stays out of it.

Making the reference aim somewhere else is an assignment to r, and that is the case where the binding’s mut matters:

error[E0384]: cannot assign twice to immutable variable `r`
--> src/main.rs:5:5
|
4 | let r = &mut a;
| - first assignment to `r`
5 | r = &mut b;
| ^^^^^^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
4 | let mut r = &mut a;
| +++
For more information about this error, try `rustc --explain E0384`.

Declare the binding mut and both operations work side by side:

a = 10, b = 102

Up to r = &mut b;, the reference aims at a, so *r = 10 sets a. After the re-pointing it aims at b, so *r += 100 sets b. Two different jobs — writing through the pointer, and moving the pointer — and only the second one needs mut on the binding.

The everyday use: a function that replaces a value

Section titled “The everyday use: a function that replaces a value”

Most *r = ... in real code sits inside functions that take a &mut parameter:

top = winner

*slot = value behaves exactly like assigning to the variable itself: the old "b" is dropped in place and the new value takes over the same memory. The caller keeps owning the String — the function only ever held a write handle to the slot, and when it returns, the handle is gone.