You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中直接返回current.borrow().val报错,绑定变量则正常的原因

Rust中E0597错误:为何绑定变量能解决生命周期问题?

我实现了一个接收二叉树根节点TreeNodeRef的函数,目标是返回树最底层最右侧节点的值。当直接返回current.borrow().val时,编译器抛出E0597错误:current does not live long enough;但将该值先绑定到一个let变量再返回,错误就消失了,代码能正常运行。


二叉树节点定义

/// 二叉树节点结构
#[derive(Debug, Clone)]
pub struct TreeNode {
    val: i32,
    left: Option<TreeNodeRef>,
    right: Option<TreeNodeRef>,
}

type TreeNodeRef = Rc<RefCell<TreeNode>>;

原报错函数实现

/// 示例树结构:
///        -1
///      /    \
///    -6     -5
///   /  \      \
/// -3   -4    -13
///     / \    /    
///    -2  6  7
/// 最底层最右侧节点值为7
pub fn bottom_right_value(root: TreeNodeRef) -> i32 {
    let mut current = root.clone();
    let mut queue: VecDeque<TreeNodeRef> = VecDeque::new();
    queue.push_back(root);
    while !queue.is_empty() {
        current = queue.pop_front().unwrap();

        if let Some(left) = &current.borrow().left {
            queue.push_back(left.clone());
        };
        if let Some(right) = &current.borrow().right {
            queue.push_back(right.clone());
        };
    }
   
    current.borrow().val // 此处报错E0597
}

报错信息

error[E0597]: `current` does not live long enough
  --> src/lib.rs:50:5
   |
37 |     let mut current = root.clone();
   |         ----------- 绑定`current`的位置
...
50 |     current.borrow().val
   |     ^^^^^^^^^^^^^^^^
   |     |
   |     被借用的值生命周期不足
   |     此处创建了一个持有借用权限的临时对象...
51 | }
   | -
   | |
   | `current`在此处被销毁,但此时仍处于被借用状态
   | ...当临时对象被销毁时,其`Ref<'_, TreeNode>`类型的析构函数可能会用到这个借用
   |
   = note: 临时对象属于块末尾的表达式;
           考虑让临时对象更早销毁,在块内局部变量被销毁之前
help: 例如,可以将表达式的值保存到新的局部变量`x`中,再让`x`作为块末尾的表达式
   |
50 |     let x = current.borrow().val; x
   |     +++++++                     +++

修改后正常运行的代码

let result = current.borrow().val;
    result

错误原因与解决方案解析

核心在于临时对象的生命周期和局部变量的销毁顺序:

  1. 直接返回的情况:
    当你直接写current.borrow().val作为函数返回值时,current.borrow()会生成一个Ref<'_, TreeNode>临时对象(用于安全访问RefCell内部数据)。这个临时对象会一直存活到函数块结束才会被销毁。
    而current作为函数内的局部变量,会在函数结尾(})处被销毁。此时Ref临时对象还持有对current的引用,就造成了“被引用的对象先于引用者销毁”的生命周期冲突,触发E0597错误。

  2. 绑定变量后返回的情况:
    当你用let result = current.borrow().val时,current.borrow()生成的Ref临时对象只需要存活到完成val的拷贝即可——因为i32是Copy类型,val会被直接拷贝到result中。
    拷贝完成后,Ref临时对象就会被立即销毁,此时current还未被销毁,不存在引用冲突。最后返回的是独立的i32值,和current的生命周期完全无关,因此编译器不会报错。

内容的提问来源于stack exchange,提问作者Anup

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 20:24:33