Need help for explanation of simple piece of code (beginner)

I’m trying to learn and understand ownership in rust. And i stuck on this piece of code. I know three rules of ownership one of which is “only one mutual ref at a time”. But why is this code works fine if change &mut foo.vec to &mut foo1.vec, the result and type of let vec = &mut foo.vec; are the same but one compiles when the other is not. Thanks in advance.

#[derive(Debug)]
struct Foo {
    vec: Vec<String>,
};

let mut foo = Foo { vec: vec!["Hello".to_string()] };
let foo1 = &mut foo;
let vec = &mut foo.vec; // this doesn't work
// but with    foo1.vec - works fine
vec.push("World".to_string());
foo1.vec.push("Lorem".to_string());
println!("{:?}", foo1);
let foo1 = &mut foo;
let vec = &mut foo.vec; // this doesn't work

with the above code, foo.vec can be mutably access via foo1 and vec,
which fails due to the rule “one one mutatable reference at a time”.

" foo.vec can be mutably access via foo1 and vec" Yes. But the same can be performed if change this:

let foo1 = &mut foo;
let vec = &mut foo.vec;

to this:

let foo1 = &mut foo;
let vec = &mut foo1.vec;

As i understand result is the same from both pieces of code, but first doesn’t compiles while second compiles fine. That was the point of question.

Another way to think about this is that with:

let foo1 = &mut foo;
let vec = &mut foo.vec;

If you mutate vec, then you’re changing foo out from under foo1, who is holding a mutable (exclusive!) reference.

With the other way:

let foo1 = &mut foo;
let vec = &mut foo1.vec;

The vec reference is derived from foo1, in some sense it’s a “finer-grained” reference. Importantly, this only works because you don’t interleave uses of vec and foo1. You can only use the foo1 after the mutable borrow of vec is over (vec.push("World".to_string());).

2 Likes

Sorry I jumped ahead. Is this to do with Non-Lexical-Lifetime added in 2018 edition ? Originally I too had the same understanding, as in, the lifetime is tied to the scope.

1 Like

This is indeed due to non-lexical lifetimes. Before that feature, the borrow of vec would last until the end of the scope (even though it’s not used!), and you’d get an error when you tried to use the foo1 reference on the second-to-last line.

1 Like

A big thanks to the NLL team, this benefits us a lot.

Thanks.This explanation give me clearer understanding of whats happening.

Yeah. Especially from beginners)