Can not "late" binding a local variable

Why compiler disallow "late" binding ? I think the compiler should know there is a reference to 3 and does not drop it until the end of b. And I know A and B have different semantics, A is in fact a binding and B is in fact an assign. But if we allow B , we will be more flexible.

fn main () {
  // case A
  let a = &mut 1;
  *a = 2;     // works
 // case B
  let b;
  b = &mut 3;
  *b = 2;     // not works
}

why does the compiler even allow a? O_o

Yeah, looks like compiler magic.

My guess is that:

let a = &mut 1;

compiles to:

let tmp = 1;
let a = &mut tmp;

(there's an obscure let ref mut a = 1 syntax that does the same)

so it gets a lifetime of the whole scope.

And b = &mut 3 compiles to:

b = {
   let tmp = 3;
   &mut tmp
};

so it gets an unusable temporary lifetime.

This is "temporary lifetime extension", specified in more detail in the reference: https://doc.rust-lang.org/reference/destructors.html#temporary-lifetime-extension

Basically, when the initializer of a let-statement is a mutable or immutable borrow expression, the lifetime of the created temporary is extended to last until the end of the block containing the let-statement.

8 Likes