Why is it legal to borrow a temporary?

Why is it legal to borrow a temporary?

It's legal for the same reason it's illegal in C++ — because someone said that's how it should be.

How long does the temporary live in Rust? And since x is only a borrow, who is the owner of the string?

The reference says:

the temporary scope of an expression is the smallest scope that contains the expression and is for one of the following:

  • The entire function body.
  • A statement.
  • The body of a if, while or loop expression.
  • The else block of an if expression.
  • The condition expression of an if or while expression, or a match guard.
  • The expression for a match arm.
  • The second operand of a lazy boolean expression.

Essentially, you can treat your code as:

let mut a_variable_you_cant_see = String::new();
let x = &mut a_variable_you_cant_see;
x.push_str("Hello!");

See also:

  • Why can I return a reference to a local literal but not a variable?
  • What is the scope of unnamed values?
  • Are raw pointers to temporaries ok in Rust?

From the Rust Reference:

Temporary lifetimes

When using a value expression in most place expression contexts, a temporary unnamed memory location is created initialized to that value and the expression evaluates to that location instead

This applies, because String::new() is a value expression and being just below &mut it is in a place expression context. Now the reference operator only has to pass through this temporary memory location, so it becomes the value of the whole right side (including the &mut).

When a temporary value expression is being created that is assigned into a let declaration, however, the temporary is created with the lifetime of the enclosing block instead

Since it is assigned to the variable it gets a lifetime until the end of the enclosing block.

This also answers this question about the difference between

let a = &String::from("abcdefg"); // ok!

and

let a = String::from("abcdefg").as_str(); // compile error

In the second variant the temporary is passed into as_str(), so its lifetime ends at the end of the statement.

Tags:

Temporary

Rust