let mut x = 10;
let mut closure: Box<dyn FnMut() -> i32> = Box::new(|| {
println!("x = {}", x);
x += 5;
x
});
let value1 = closure(); // x = 10
let value2 = closure(); // x = 15
let value3 = closure(); // x = 20
println!(
"value1 = {}, value2 = {}, value3 = {}",
value1, value2, value3
);
// println!("After closure call, x = {}", x); // error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
let mut x = 10;
let mut closure = || {
println!("x = {}", x);
x += 5;
x
};
let value1 = closure(); // x = 10
let value2 = closure(); // x = 15
let value3 = closure(); // x = 20
println!(
"value1 = {}, value2 = {}, value3 = {}",
value1, value2, value3
);
println!("After closure call, x = {}", x); // x is ok for printing.
My questions:
what type of closure in 2nd code?
Why closure wrapped by Box pointer in first code is different with closure alone in second one?
How can i use x after closure? the right way is?
what type of closure in 2nd code?
As documented in the Rust Reference chapter on Closure Types:
A closure expression produces a closure value with a unique, anonymous type that cannot be written out.
Why closure wrapped by Box pointer in first code is different with closure alone in second one?
Both closures exclusively borrow x
. So long as they're "alive", x
cannot be accessed from elsewhere.
Prior to Rust v1.63, both closures remained alive until the end of the lexical scope—causing their borrows of x
also to continue beyond your println!
statements. However, thanks to non-lexical lifetimes, Rust is now able to determine that closure
ceases to be alive (and its borrows end) after its last use.
In the non-Box
case, closure
is last used in the assignment to value3
.
In the Box
case, closure
is last used when it is destroyed (implicitly at the end of the lexical scope): Box
has a Drop
handler (that frees its heap allocation) that could theoretically make use of the exclusive borrow of x
. Therefore, in that case, closure
's borrows must continue until then.
How can i use x after closure? the right way is?
Once you've finished using closure
, you could explicitly drop(closure);
. Its exclusive borrow of x
would then end, permitting you to use x
again thereafter.