2
votes

I do not understand why the function fn1 doesn't compile, i.e. why "let z = &mut x;" cannot be assigned while previously taken reference stored in "y" is not used anymore ("y" is reassigned to something else).

Moreover, why both fn2 and fn3 do compile ok while they are doing "logically" the same thing?

fn2 differs from fn1 in fact, that "y" goes out of scope instead of reassigning, but that is different only in respect to "y" pointer storage, not in respect to what is "y" pointing to.

fn3 differs from fn1 in fact, that "z" is assigned from "y" instead of directly from "&mut x".

fn fn1() {
    let mut x = 1i32;
    let mut somethingelse = 7i32;
    let mut y = &mut x;
    *y = *y + 1;
    println!("y = {}", *y);
    y = &mut somethingelse;
    println!("just something: {}", *y);
    // y is not used anymore...
    let z = &mut x;
    *z = *z + 1;
    println!("z = {}", *z);
}

fn fn2() {
    let mut x = 1i32;
    {
        let y = &mut x;
        *y = *y + 1;
        println!("y = {}", *y);
    }
    let z = &mut x;
    *z = *z + 1;
    println!("z = {}", *z);
}

fn fn3() {
    let mut x = 1i32;
    let z;
    let y = &mut x;
    *y = *y + 1;
    println!("y = {}", *y);
    z = y;
    *z = *z + 1;
    println!("z = {}", *z);
}
1

1 Answers

2
votes

Currently, borrow scopes are lexical, that is, they correspond to the braces in the code. There's a bug to change this to account for cases like your fn1, but like you see in fn2, there are workarounds for now.

For fn3, if you try to use y again, you will get this error:

error: use of moved value: `*y`

This is because the compiler can tell (via the statement z = y) that y is no longer needed and thus moves the mutable borrow to z, making y invalid.