← 中文资源

简体中文版本

Rust — error[E0716]:临时值在借用期间被丢弃

解决 error[E0716] temporary value dropped while borrowed,弄清 let x = &foo().bar 为何失败,并在借用前用 let 绑定中间值。

阅读英文原文

症状

  E0716 附带的完整诊断很精确,前提是把整段读完:错误码指出临时值在借用期间被丢弃,note 说明“临时值在语句结束时释放、借用在此之后仍在使用”。机制是:let 右侧创建的临时对象在分号处销毁,而代码想持有它某部分(字段、元素、切片)的引用越过这个时点——这在构造上就是悬垂指针,编译器以 E0716 拒绝。典型形态是 let s = &make().field 与对函数返回值内部取引用的链式调用。

诊断思路

  先读完整错误(含 note)确认临时值的作用域边界;再从错误 span 识别哪个子表达式是临时值——所有修法都是给那个值命名;最后用 cargo check 验证绑定中间值后编译通过。match/if-let 对方法结果取引用、单表达式内联构造容器再取元素引用,是两个高频藏身处。

根因

  Rust 在所在语句结束时销毁未命名的临时值。借用这种临时值的组成部分会产生生命周期超过所指对象的引用,编译器以 E0716 拒绝,而不是放行一个悬垂指针。

修复与验证

  先命名再借用:let owned = build(); let s = &owned.field;——借用指向有名字、活得久的绑定。返回位置的链式调用改为所有权流动:直接返回 String 等拥有类型,把生命周期决定权交给调用者。值很小、拷贝无关性能时,拥有类型优于扭曲的生命周期;clippy 的 redundant clone 警告会看住相反的极端。验证时 cargo check 通过此前失败的函数,测试套件覆盖该路径,且没有新增 clone 警告。设计规则只有一条:借用必须指向某个命名绑定拥有的东西,绝不指向已排定销毁的表达式结果。

代码示例

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
// from:
let s = &build().field;

// to:
let owned = build();
let s = &owned.field;   // borrow of a named, lasting binding
fn label(a: &str, b: &str) -> String {
    format!("{}-{}", a, b).to_uppercase() // owned: caller decides lifetime
}