← Debugging Guides

阅读中文版本

Rust — error[E0716]: temporary value dropped while borrowed

Resolve error[E0716] temporary value dropped while borrowed, see why let x = &foo().bar fails, and bind the intermediate value with let before borrowing.

intermediatedebuggingrustborrow-checkerlifetimes

Symptoms

  • error[E0716]: temporary value dropped while borrowed points at a function call result inside a let binding
  • The help text says the temporary value lives until the end of the statement and borrowing it beyond is invalid
  • The pattern usually involves taking a reference into a field of a freshly constructed or returned value

Possible causes

  • let x = &make().field borrows a field of a temporary that is destroyed at the semicolon
  • A match or if-let on a method result keeps a reference into a temporary scope that ends too early
  • Building a container inline and taking a reference to an element of it in one expression
  • Chaining calls where an intermediate value is unnamed, so nothing owns it past the statement

Diagnosis steps

Read the full error with notes

cargo build --message-format=short 2>&1 | head -20; cargo check 2>&1 | grep -A8 E0716

Interpretation

The note explains the exact temporary scope: created on the right side, dropped at the end of the statement — the borrow outlives it by construction.

Identify the unnamed intermediate

cargo check 2>&1 | grep -B2 -A6 "temporary value"

Interpretation

The error span highlights which subexpression is the temporary; every fix names that value explicitly.

Verify the fix compiles

cargo check && cargo test

Interpretation

A let binding for the intermediate makes ownership explicit and the borrow legal; a green check plus tests is the proof.

Root cause

Rust destroys unnamed temporary values at the end of the enclosing statement. Borrowing a part of such a temporary (a field or element) produces a reference whose lifetime exceeds the value it points into, so the compiler rejects it with E0716 rather than emit a dangling pointer.

Fix

Name the intermediate value with let before taking references to its parts, restructure functions to return owned values when callers need them to outlive one statement, and use owned types (String, Vec, clones of small data) where borrowing only saves copies that do not matter.

Risk note

Sprinkling clone() everywhere to escape the error multiplies allocations and hides the ownership design. Prefer explicit bindings first.

Verify the fix

cargo check passes on the previously failing function and the test suite exercises the code path without new clippy warnings about redundant clones.

Symptom walkthrough

E0716 arrives with a precise explanation if you read the whole diagnostic:

error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:4:13
  |
4 |     let s = &format!("{}-{}", a, b).to_uppercase();
  |             ^--------------------------------------
  |             |
  |             temporary value is freed at the end of this statement
  |             borrow later used here

The mechanism: a temporary created on the right side of a let is destroyed at the semicolon. The code wants to hold a reference to part of it (a field, an element, a slice) beyond that point — a dangling pointer by construction, which the compiler rejects.

Fix in practice

Name the intermediate, then borrow:

// from:
let s = &build().field;

// to:
let owned = build();
let s = &owned.field;   // borrow of a named, lasting binding

For return-position chains, make ownership flow instead of borrowing:

fn label(a: &str, b: &str) -> String {
    format!("{}-{}", a, b).to_uppercase() // owned: caller decides lifetime
}

When the value is small and copying is irrelevant to performance, owned types beat contorted lifetimes — clippy warnings about redundant clones will police the opposite extreme. The design rule: a borrow must point into something a named binding owns, never into an expression result scheduled for destruction.