error[E0594]: cannot assign to `x`, as it is not declared as mutable
--> src/main.rs:4:36
|
3 | let x = 0;
| - help: consider changing this to be mutable: `mut x`
4 | let mut captures_x = move || { x += 1; dbg!(x); };
| ^^^^^^ cannot assign
The mut-lint-ability of the initial binding should play no role in further mutability when the variable is moved elsewhere. For instance,
fn main ()
{
let x = PrintOnDrop(0);
{x}.0 += 1;
}
So, in this case, captures_x is the binding that requires mut, and in theory, it could even not require it (it only requires so to be callable), not x (by the way, whether x is Copy or not plays no role here).
This looks like a bug to me, but before opening an issue I would like to have your thoughts on it.
Temporary values are always mutable. Same does not apply to assigned closures. It's not worth trying to change how such items are specified. The argument would go onto dropping mut altogether.
Imaging two variables differing by mutability instead, you still have full specification of mutability. (Including to the closure variable.)
p.s. FnOnce don't need the mut for the closure. (To keep with my original sentence; Guess you could say they are moved into a temporary, just like fn drop (&mut self) also needs that unspecified mutable.)
Something could (and maybe should) be done in that direction: since &mut is a reference that is guaranteed to be unique, the actual purpose of the "mut-lint-ability" binding modifier is to make the binding non-unique aware. For basic examples this is fine, but with interior mutability or examples such as the one motivating this example, this design has its limits. I think that whilst this lint-guard can be useful, it should not hinder usability in more complex cases, with inconsistent patterns such as the aforementioned one. In other words: when in doubt, mut must not be required (like with temporaries being mut).