xm lian
xm lian

Reputation: 107

Can't understand how did the unique immutable borrows in captures work

I've been reading the section Unique immutable borrows in captures of the book The Rust Reference and can't figure out why the code is illegal:

let mut b = false;
let x = &mut b;
{
    let mut c = || { *x = true; };
    // The following line is an error:
    // let y = &x;
    c();
}
let z = &x;

The book's explanation points out that type of variable y is & &mut which might not be unique. I'm confused about why & &mut can't guarantee uniqueness? I mean, both x and y are immutable and there is only one place that can change, which is the value of variable b.

I guess the reason(not sure) is:

let mut b = false;
let x = &mut b; // There is a guarantee that the value of `*x` is can't change because there no mutable reference.
let y = &x; // There is a guarantee that the value of `*y` and `**y` is can't change, but I don't know that rust needs to guarantee `**y` is can't change.

Upvotes: 0

Views: 109

Answers (2)

Taraxtix
Taraxtix

Reputation: 71

The fact the variable x is not declared as mutable doesn't implies that it's not a mutable borrow and is actually a mutable borrow.

As an example, this is valid code and does in fact modify b :

let mut b = false;
let x = &mut b;
*x = true;
println!("{x}"); // true

So in the example you provided, x is borrow as mutable by the closure as it modifies the value it containes by doing *x = true. While this closures is in scope, the variable x will be borrowed.

So step by step :

let mut b = false; // Creates the variable b as mutable.
let x = &mut b; // x borrows b as mutable. 
{
    // c is created, using x to modify b thus borrowing x as mutable
    let mut c = || { *x = true; };
    
    // This tries to borrow x but it is still borrowed as mutable by c which is not allowed
    let y = &x; 
    c();
} // c goes out of scope freeing the borrow of x
let z = &x; // x not being borrowed by anyone here, it can be borrowed

Hoping this helps making it clearer

Upvotes: 1

cafce25
cafce25

Reputation: 27552

The closure is the first borrow and y would be the second, therefore x would be borrowed multiple times, that however cannot be allowed because the closure modifies the value pointed to by x.

In other words, the closure holds an exclusive borrow (even if it's not mutable in this case) to x, nothing outside can take an additional borrow.

Upvotes: 0

Related Questions