Expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`

Viewed 444
fn main() {
    let mut x = String::new();
    let y = || {
        let t = x;
    };
    let mut ww = Box::new(y);
    ww();
}

I expect it to run without any error as this implementation exist

impl<Args, F, A> FnOnce<Args> for Box<F, A> 

But I am getting some weird errors which I am unable to understand why?

error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
  --> src/main.rs:22:13
   |
22 |     let y = || {
   |             ^^ this closure implements `FnOnce`, not `FnMut`
23 |         let t = x;
   |                 - closure is `FnOnce` because it moves the variable `x` out of its environment
...
26 |     ww();
   |     ---- the requirement to implement `FnMut` derives from here

error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
  --> src/main.rs:22:13
   |
22 |     let y = || {
   |             ^^ this closure implements `FnOnce`, not `Fn`
23 |         let t = x;
   |                 - closure is `FnOnce` because it moves the variable `x` out of its environment
...
26 |     ww();
   |     ---- the requirement to implement `Fn` derives from here
1 Answers

[Community Work In Progress]

A solution is to dereference yourself:

(*ww)();

Now why the compiler do that:

Box impl FnOnce but by default it's seem to call FnMut See How does Boxed closure calls work just like closure calls?

When you do:

let mut ww = Box::new(y);
ww();

It's suppose to call deref and Deref is implemented for box but return a &T by borowing the box. FnOnce require a move of the box. Why by doing (*ww) this work ? ww.deref() and ww.deref_mut() doesn't work. It's strange. * could call a magic trait instead ? https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html ? https://doc.rust-lang.org/std/ops/trait.DispatchFromDyn.html ?

Related