Why does the assigment to a reference kill the loan that was previous assigned to the reference?

โš“ Rust    ๐Ÿ“… 2025-07-30    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 10      

surdeus

Warning

This post was published 126 days ago. The information described in this article may have changed.

Consider this example:

fn main() {
    let mut data = vec![1, 2, 3];
    let mut x = &data[0];
    println!("{}", x); // #0
    data.push(4);  // #1
    x = &data[3]; // #2
    println!("{}", x); // #3
}

If there were no #2, #1 would cause the borrowing checker error. This example is a bit like the example in 2094-nll - The Rust RFC Book

let mut foo: T = ...;
let mut bar: T = ...;
let mut p: &T;

p = &foo;
// (0)
if condition {
    print(*p);
    // (1)
    p = &bar;
    // (2)
}
// (3)
print(*p);
// (4)

The RFC comments on this example as:

The key point of this example is that the variable foo should only be considered borrowed at points 0 and 3, but not point 1.

However, it seems there is no wording that says why foo is not considered to be used at (1). If completing the example as the following like this:

fn main() {
    let mut foo = 0;
    let mut bar = 1;
    let mut p: & /*'p*/ i32;
    //      --
    p = &/*'foo*/ foo;
    //   ----
    if false {
        println!("{}",*p);
        // (1)
        foo = 2;
        p = &/*'bar*/ bar;
        //   ----
    }
    //foo = 2;
    println!("{}",*p);
}

foo = 2; won't cause the borrowing checker error. That implies, the loan ('foo,shared, foo) is not in the point (1) in the CFG, so, it's not considered as a relevant borrowing for the access foo = 2.

The rules for computing loans in the scope are:

For a statement at point P in the graph, we define the โ€œtransfer functionโ€ โ€“ that is, which loans it brings into or out of scope โ€“ as follows:

  • any loans whose region does not include P are killed;
  • if this is a borrow statement, the corresponding loan is generated;
  • if this is an assignment lv = <rvalue>, then any loan for some path P of which lv is a prefix is killed.

I don't think the third bullet is saying about p = &/*'bar*/ bar, it intends to say the loan for some path P of which p is prefix. For the loan ('foo,shared, foo), it is not the case.

So, the relevant bullet should be the first one. However, NLL does not define why the region of the loan ('foo,shared, foo) does not include (1)? How to understand this point?

4 posts - 2 participants

Read full topic

๐Ÿท๏ธ Rust_feed