Why does a mutable reference need a mutable binding?


#1

From my understanding, bindings and references are different things with respect to mutability:

  1. A mutable variable binding can be reassigned
  2. A mutable reference references a value which is borrowed as mutable and hence can be mutated in place

Therefore I don’t understand why one must use a mutable binding to use the value as a mutable reference.

Example:

let mut s = String::from("Rust");
// OK, push_str requires a mutable reference,
// but why do we have to declare `s` a mutable binding,
// i.e. one that can be assigned a different value?
s.push_str("Fest Zurich");
println!("{}", s);

Wouldn’t an immutable binding – i.e. one we can’t reassign – also work in theory?


#2

Consider this:

fn main() {
    let v = 1;
    *&mut v = 2;
    println!("{}", v);
}

If mut wouldn’t be needed on a binding to make a mutable reference to it, it would be trivial to accidentally change immutable value (and be surprised about a change).

s.push_str("Fest Zurich") is a syntactic sugar for (&mut s).push_str("Fest Zurich") - as push_str method has &mut self parameter.


#3

Thanks a lot!

Using a stack allocated integer instead of a String was really helpful for my understanding. And even in the case of a String – which has a part on the stack (ptr, length, cap) and a part on the heap – the stack part is changed which means the associated binding is mutated.

With respect to the syntactic sugar, I don’t agree: the desugared function is push_str(&mut self, string: &str).


#4

UFCS Method syntax wise, you’re right. @xfix was showing you that rust autorefs for you.


#5

Good point, thanks! I didn‘t think about autorefing at all.


#6

Thanks for this question. It’s something I knew in the back of my head, but reading it like this and seeing @xfix’s response made it concrete!