Question: I don't understand the borrow checker behaviour here

I have the following code snippet; it is a simplification of a larger MutableVisitor that I have. I do not understand how borrow checking is affected by changing self, as depicted in this example. Can someone explain this to me? Thanks a lot in advance!

struct S {
    si: u32,
}

struct I<'a> {
    ii: &'a u32,
}

impl<'a> I<'a> {
    fn mut_borrow(&mut self, s: &'a mut S) {
        s.si = 4;
    }

    fn test(&mut self, s: &'a mut S) {
        self.ii = borrow(s); // This does not work
        //borrow(s); // If uncomment then it works.
        self.mut_borrow(s);
    }
}

fn borrow<'a>(s: &'a S) -> &'a u32 {
    println!("i: {}", s.si);
    &s.si
}

fn main() {
    let mut s = S { si: 1 };
    let ui = 34;
    let mut ii = I { ii: &ui };
    ii.test(&mut s);
    println!("Done!");
}

self.ii = borrow(s) creates an immutable borrow of s. While a value is borrowed immutably, it cannot be mutated.

A mutable references (&mut T) must have exclusive access to the value it references. You can’t create an exclusive/mutable reference while any other references to the same value are alive.

Can you clarify why self.ii = borrow(s) doesn't work but borrow(s) (without assigning to self.ii) works?

if you don't assign the value of borrow(s) anywhere, the compiler is free to end the lifetime of the borrow as soon as the function call returns, so there is no conflict with later uses of s.

edit: assign, not design.

Is there some literature to explain how long the borrow by a function call lasts? I would be interested to understand that better. It seems that in some cases, it lasts until the end of function sometimes when the call returns. Thanks!

Try rereading the section on lifetimes in the online book.

In short, if there is a borrow that is named in the return type of the function, the borrow must live as long as the returned value, but no longer than the borrow in the function parameter that it it's tied to. If the returned borrow isn't tired to one of the function arguments, it must be 'static. if the borrow doesn't appear in the return type, it can end as soon as it is no longer used. in order to fully understand it, though, you also need to understand which borrows are linked when the lifetime annotations are elided.

Basically it looks at where the borrow is used, and it lasts exactly as short as possible while still allowing those uses.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.