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

困惑:这段Rust代码编译报错,为何提示借用仍被使用?

Rust 借用检查器报错分析

问题代码

struct Node {
    next: Option<RefCell<Box<Node>>>
}

impl Node {
    fn print_nodes(head: &Node) {
        let mut next = Some(head);
        let next2;
        if let Some(n) = next {
            match &n.next {
                Some(n2) => {
                    next2 = n2.borrow();
                    next = Some(next2.as_ref());
                },
                _ => {
                }
            }
        }
    }
}

编译器报错信息

src/main.rs:114:33
|
109 | let next2;
| ----- binding next2 declared here
...
114 | next = Some(next2.as_ref());
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
120 | }
| -
| |
| next2 dropped here while still borrowed
| borrow might be used here, when next2 is dropped and runs the destructor for type Ref<'_, Box<Node>>

问题解析

你误以为next2和next同作用域就会同时销毁,但Rust的变量销毁规则是先声明的后销毁:

  • next先被声明,next2后声明,所以函数结束时,next2会先被销毁,之后才轮到next。
  • 你把next重新赋值为next2.as_ref()的引用,这个引用依赖next2持有的Ref<Box<Node>>。当next2销毁时,它的Ref会被释放,对应的Box<Node>的借用权限被收回,但此时next还未销毁,里面的引用就变成了悬垂引用——哪怕next马上也要被销毁,Rust的借用检查器也不允许这种“短暂无效引用”存在,因为销毁顺序是明确的,引用的有效性必须持续到它不再被使用。

修复示例

正确的遍历方式应避免存储跨生命周期的引用,改用循环内临时借用:

use std::cell::RefCell;

struct Node {
    next: Option<RefCell<Box<Node>>>
}

impl Node {
    fn print_nodes(head: &Node) {
        let mut current = Some(head);
        while let Some(node) = current {
            // 可在此添加节点处理逻辑,如打印信息
            current = node.next.as_ref().map(|n| n.borrow().as_ref());
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 02:20:29