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
Rust has a concept of single ownership, i.e. a String type can have at most one owner. It can't exist in two places.
Moves preserve this single-ownership rule by allowing you to move a variable once and no more.
let t = x moves x to t every time the method is called, but because value can be moved only once, then the only correct way to use this closure is to call it once.
You need to capture &x inside the closure (not &mut, they're single-owned too). Shared references can be copied any number of times.
let mut x = String::new();
let x_ref = &x;
let y = || {
let t = x_ref;
};
Alternatively make it a move || closure that owns the x, but don't move or destroy it inside the closure, e.g. borrowing temporarily doesn't move it further move || { x.len() }.
If you want to use this string inside and outside of the closure, you'll need Arc<String>. If you want to also mutate it, then Arc<Mutex<String>>.