Sometimes struct follows NLL rules. For example, this code is compilable (playground). In its main function:
fn main() {
let mut i = 3;
let foo = Foo{r: &i, v: vec![123]};
let bar = Bar{f: foo, v: vec![222]};
let r2 = &mut i;
*r2 = 5;
println!("{}", i);
}
That *r2 = 5;
is legal implies the lifetime of foo
ends before it, so foo
follows NLL.
But this code is erroneous (playground). In it:
fn main() {
let mut a = Vec::new();
let mut foo = Foo::new(|v| {
for i in v {
a.push(i);
}
});
foo.fun(1);
println!("{:?}", a);
}
results in a compilation error:
error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
--> src/main.rs:24:22
|
18 | let mut foo = Foo::new(|v| {
| --- mutable borrow occurs here
19 | for i in v {
20 | a.push(i);
| - first borrow occurs due to use of `a` in closure
...
24 | println!("{:?}", a);
| ^ immutable borrow occurs here
25 | }
| - mutable borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_, i32>`
which means that the lifetime of foo
ends after println!("{:?}", a);
, showing that foo
here follows lexical rules instead of NLL.
Why is the difference, and how exactly NLL for struct works?