Essentially, this is a consequence of one of Rust's soundness rules – you can't modify anything through a shared reference to a mutable reference. All the references in your chain of references need to be mutable for this to be possible.
Let's translate the closure in your example into roughly equivalent code using a struct:
struct Closure<'a> {
x: &'a mut i32,
}
impl Closure<'_> {
fn call(&mut self) {
*self.x += 1;
}
}
The closure captures x
by mutable reference – it has to to be able to modify it. When the closure is called, it receives self
by mutable reference – it has to to be able to mutate x
through the self
pointer.
Now if you want to call this closure, you need to make it mutable as well:
let mut x = 1;
let mut y = Closure { x: &mut x };
y.call();
If you don't make y
mutable, you can't pass a mutable reference to y
to the call()
method.
The reason for the soundness rule mentioned at the beginning is easy to see: If you could mutate through a shared reference to a mutable reference, it would be easy to write code with multiple players holding mutable references to the same memory location, which violates one of the fundamental rules about Rust references.