Reassigned reference still has limited lifetime?

Considering the following code:

fn main() {

    let y = 6;
    let mut r;
    
    {
        let x = 5;
        r = &x;
        println!("r in scope: {}", r);
        r = &y;
    }
    println!("r: {}", r);
}

We can see that at the end of block r doesn't hold reference to x, since it was unconditionally reassigned. Although, this code doesn't compile, since r has to live no longer then x. Is this intentional?

Yes. x lives only within its scope and by definition can't live any longer than that.

Everything borrowed from x in any way, no matter how weirdly or indirectly, has to be as limited as x itself.

Once you borrow something, there's no direct way to extend lifetime of that borrow. You can either change the program to create a longer lifetime (e.g. create an object earlier, in outer scope), or create a copy (.clone() or derive Copy).

The question is, why the lifetime is still limited when borrow is released? As you can see, x is not referenced in any way, directly or indirectly, after the block, but compiler ignores this fact.

With non-lexical lifetimes enabled the compiler is able to reason about lifetime in dimension of time, rather than scopes, so this works in nightly:

#![feature(nll)]

fn main() {

    let y = 6;
    let mut r;
    
    {
        let x = 5;
        r = &x;
        println!("r in scope: {}", r);
        r = &y;
    }
    println!("r: {}", r);
}
3 Likes