Is image this showing ownership is lost when borrowed ? Or what?

Here there is an image from the interactive book, and their permissions model, which I found very cool but can't get this feature.

The problem is: why does the variable num makes v lose ownership when it's borrowed, and not just read and optionally write permissions (when the reference is mutable.) ?

Note that in the book this happens regardless of the borrowing being mut or not. All cases use the same for O (just changes W)

In the image, I am hovering over the scratched O. The book section is here.

Oh, I think I understand it. It does have ownership, but can't be transferred / moved likely?

That'd mess with the borrow.

Correct, the ownership doesn't change when you take a reference. The owning object is just temporarily restricted while it is borrowed. When the scope of the loans ends, the owning object can be moved or destroyed again.

1 Like

Just a follow up on that, if instead I write:

fn main() {
    let mut v: Vec<i32> = vec![1, 2, 3];
    let vc= &mut v;
    vc.push(5);
    println!("Vector is now {:?}", v);// 1,2,3,5
}

This isn't just updating v but pushing to it, so if the data has to be moved to a different location in the heap, is v's pointer to the relocated array updated? (and I think both vc and v always use the same pointer, just vc has an extra hop to v)

Pushing to a Vec is one way to update the Vec.

Correct.

1 Like

And even if it's not moved, the length is updated.

Here's a related diagram.

1 Like

What would be the problem though, to update x directly given that no mutable borrow has been done ?

let mut x = 1;
let y = &x;
// cant update x, lost **W** privileges

You only "lose W privileges" so long as borrow is active. Once you stop using y, x can be updated again.

Being borrowed[1] conflicts with being overwrote, moved, or taking a &mut.

The problem with pushing while y is active is that pushing requires a &mut, which is an exclusive reference. If it weren't exclusive, you could say launch a scoped thread to continuously read the length and/or existing data and capacity through y while the push happens, creating a data race (which is UB).


  1. be it a shared & borrow or an exclusive &mut borrow â†Šī¸Ž

1 Like

But I meant x+=1, not *y+=1?

Oh I see that I missed that we're no longer talking about Vec. But += requires a &mut too. And this complies.

If something is still confusing, can you be more specific?

The "head" v of the Vec is stored separately from its data on the heap. The data on the heap can be reallocated (move) if the individual elements there aren't borrowed.

More precisely, the place where v exists must remain valid and can't be moved or destroyed while its borrowed, but the content of that place (byte values that are in there, and other data reachable from there) can change if something has a mutable access to it.

There is a confusing special case of std::mem::swap that swaps two values, which effectively moves the objects, but doesn't affect the places where they're stored. This is a case where Rust's terminology gets tricky, because swapped values are moved, but they're not moved out of the place they're in. It's a move from perspective of objects changing their location, but not a move from the perspective of the borrow checker!