To add to the previous commenters, here’s how the desugaring of the closure call works:
In the code
fn main() {
let mut a = String::new();
let mut inner = || {
let b = String::from("test");
a = b;
};
inner();
println!("{}", a);
}
the compiler first deduces that the closure mutates a
, so it includes a mutable reference to a
in the closure. (This will e.g. mean that you cannot access a
anymore until after the last call to inner
.) Then it also sees that the closure does not move out of any of it’s captured variable. This means that it can implement FnMut
but it cannot implement Fn
.
The call to inner()
thus gets desugared using the FnMut
interface. You can think of the desugaring of such a call to use Fn
interface whenever possible. (Not possible for this closure.) Then, as a fallback use FnMut
interface (works works for this closure). And if the closure had not implemented FnMut
it would’ve fallen back to using the FnOnce
interface. In this case this means that we get
// needs nightly for explicitly mentioning
// the `Fn*` traits
#![feature(fn_traits)]
fn main() {
let mut a = String::new();
let mut inner = || {
let b = String::from("test");
a = b;
};
inner.call_mut(());
println!("{}", a);
}
(playground)
As the previous commenters have shown, call_mut
takes a &mut self
argument, hence this desugars further to
// needs nightly for explicitly mentioning
// the `Fn*` traits
#![feature(fn_traits)]
fn main() {
let mut a = String::new();
let mut inner = || {
let b = String::from("test");
a = b;
};
FnMut::call_mut(&mut inner, ());
println!("{}", a);
}
(playground)
This &mut inner
reference being created is the reason why we need the mut
when declaring inner
.