fn main() {
let mut a: &mut i32 = &mut 1;
let mut closure = || {
a = &mut 2; //Error
};
closure();
}
Error:
error[E0521]: borrowed data escapes outside of closure
--> src\main.rs:5:9
|
2 | let mut a : &mut i32 = &mut 1;
| ----- `a` declared here, outside of the closure body
...
5 | a = &mut 2; // Error
| ^^^^------
| | |
| | borrow is only valid in the closure body
| reference escapes the closure body here
For more information about this error, try `rustc --explain E0521`.
I don't understand why reference escapes the closure ?
By default, the closure uses the weakest way to capture all its variables. Assignment to a requires only a &mut a, so that's what is captured. Thus you try to write a local &mut 2 into a nonlocal variable and get an error. You can force the closure to capture a by move using the move keyword:
let mut closure = move || { a = &mut 2; }
However, it also won't work, since a itself is a nonlocal reference &mut 1. You should declare
In order for the variable a of type &mut i32 to have a valid value, that value must be a pointer to some memory that can be mutated. That memory must be valid for as long as a is being used. The code in the closure, a = &mut 2, doesn't work because it's pointing to a temporary place that is deallocated at the end of its statement.
The reason that the original declaration let mut a: &mut i32 = &mut 1; is valid is because of a special convenience rule called βtemporary lifetime extensionβ, which says that inside of a let temporaries may be adjusted to live as long as a variable does. Specifically,
let mut a: &mut i32 = &mut 1;
acts as if it was
let mut tmp: i32 = 1;
let mut a: &mut i32 = &mut tmp;
However, maybe your goal is to change the value stored in the &mut i32? In that case, the correct code is:
let mut closure = || {
*a = 2;
};
That is, we are assigning to the referent of the mutable reference a, not replacing the mutable reference itself.