Email me

Rust errors / Ownership and borrowing

Rust compiler error · checked with rustc 1.99.0

Rust error E0716: temporary value dropped while borrowed

What it meansYou borrowed from a temporary (a value that only lives for one statement) and kept the borrow. Bind the temporary to a variable first so it lives longer.

What rustc prints

error[E0716]: temporary value dropped while borrowed
 --> main.rs:5:14
  |
5 | let p = bar(&foo());
  |              ^^^^^ - temporary value is freed at the end of this statement
  |              |
  |              creates a temporary value which is freed while still in use
6 |          // ------ creates a temporary
7 | let q = *p;
  |         -- borrow later used here
  |
help: consider using a `let` binding to create a longer lived value
  |
5 + let binding = foo();
6 ~ let p = bar(&binding);
  |

Real output of rustc 1.99.0 compiling the official example below (2021 edition). Your names and line numbers will differ; the first line is the part to match.

Why it happens

  • let parts = line.trim().to_lowercase().split(' ');
  • Chaining a borrowing method onto a function call that returns an owned value.

How to fix it

1. Bind the temporary

Give the owned value a name, then borrow from it.

let lower = line.trim().to_lowercase();
let parts: Vec<&str> = lower.split(' ').collect();

Other wordings of this error

temporary value dropped while borrowed, creates a temporary value which is freed while still in use, temporary value is freed at the end of this statement

E0716Ownership and borrowing
Activein rustc 1.99.0
8related errors linked below

The compiler team's explanation

A temporary value is being dropped while a borrow is still in active use.

Erroneous code example:

fn foo() -> i32 { 22 }
fn bar(x: &i32) -> &i32 { x }
let p = bar(&foo());
         // ------ creates a temporary
let q = *p;

Here, the expression &foo() is borrowing the expression foo(). As foo() is a call to a function, and not the name of a variable, this creates a **temporary** -- that temporary stores the return value from foo() so that it can be borrowed. You could imagine that let p = bar(&foo()); is equivalent to the following, which uses an explicit temporary variable.

Erroneous code example:

let p = {
  let tmp = foo(); // the temporary
  bar(&tmp) // error: `tmp` does not live long enough
}; // <-- tmp is freed as we exit this block
let q = p;

Whenever a temporary is created, it is automatically dropped (freed) according to fixed rules. Ordinarily, the temporary is dropped at the end of the enclosing statement -- in this case, after the let p. This is illustrated in the example above by showing that tmp would be freed as we exit the block.

To fix this problem, you need to create a local variable to store the value in rather than relying on a temporary. For example, you might change the original program to the following:

fn foo() -> i32 { 22 }
fn bar(x: &i32) -> &i32 { x }
let value = foo(); // dropped at the end of the enclosing block
let p = bar(&value);
let q = *p;

By introducing the explicit let value, we allocate storage that will last until the end of the enclosing block (when value goes out of scope). When we borrow &value, we are borrowing a local variable that already exists, and hence no temporary is created.

Temporaries are not always dropped at the end of the enclosing statement. In simple cases where the & expression is immediately stored into a variable, the compiler will automatically extend the lifetime of the temporary until the end of the enclosing block. Therefore, an alternative way to fix the original program is to write let tmp = &foo() and not let tmp = foo():

fn foo() -> i32 { 22 }
fn bar(x: &i32) -> &i32 { x }
let value = &foo();
let p = bar(value);
let q = *p;

Here, we are still borrowing foo(), but as the borrow is assigned directly into a variable, the temporary will not be dropped until the end of the enclosing block. Similar rules apply when temporaries are stored into aggregate structures like a tuple or struct:

// Here, two temporaries are created, but
// as they are stored directly into `value`,
// they are not dropped until the end of the
// enclosing block.
fn foo() -> i32 { 22 }
let value = (&foo(), &foo());

From rustc --explain E0716 (1.99.0), part of the Rust project, MIT or Apache-2.0. Official page.

Related errors

All 518 Rust error codes · Rust crate data · Glossary

Up next

Often hit nextE0382: borrow of moved valueA related error from the same family.Read it next →

Did this answer your question?

Get the receipts by email.

What my AI agents tried this week, with the real numbers: what worked, what flopped, what made money. One email when there is something worth reading.

No spam, never sold. Every email has a one-click unsubscribe.

Popular in the shop

All 124 tools →

Browse: Bundles and kitsHome, family and schoolMoney and businessAI toolsSports and fitnessMaking and hobbiesFood and drinkIndie dev and launchTrading and quant

Free: Landing page teardown iPhone app cost calculator LLM API cost calculator Paid online: $49 Launch Check App builds Articles FAQ