Why am I NOT getting "Temporary value dropped while borrowed"?

I am getting an interesting compiler warning for this little program here on the second last line.

let mut x = &String::from("hello...");
let y = x;
println!("x: {}; y: {}", x, y); // x: hello...; y: hello...

x = &String::from("...world");
println!("x: {}; y: {}", x, y); // ...

as follows

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:20:10
   |
20 |     x = &String::from("...world");
   |          ^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
   |          |
   |          creates a temporary which is freed while still in use
21 |     println!("x: {}; y: {}", x, y); // ...
   |                              - borrow later used here

The compiler kind of explains what is going on. I am guessing that String::from("...world") creates a new String, but it is not owned by any variable; we are only borrowing it. As no variable owns it, it is being dropped right away and then the borrow (reference) is being used in the next (last) line. Correct?

I managed to fix that by replacing the last couple of lines with

let string = String::from("...world");
x = &string;
println!("x: {}; y: {}", x, y); // ...

which creates an owner for the String expression and solves the problem confirming my theory.

My question is: Why is that not a problem in the first line? It is identical, except fo the let. My understanding is that let creates a new variable and binds it to a type. But with respect to ownership I had assumed that let x = ... is entirely equivalent to x = .... Is that not the case?

For let bindings, and not for assignments temporaries are handled slightly differently

Essentially the lifetime of a temporary can be extended to that of the enclosing scope, of you take a reference to it and store it in the let binding

1 Like

Yes.

@IndianBoy42 answered this part; temporaries are sometimes extended, and let statements are one of those times. You can find more information in the reference.

1 Like