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

Rust中可变借用离开作用域后为何仍无法进行不可变借用?

你的理解疏漏点

你对借用规则的认知没有错,但搞错了闭包持有捕获变量借用的生命周期范围:
闭包对环境中变量的借用,是从闭包被创建的那一刻开始持有,一直持续到闭包自身被销毁(离开作用域)、或者最后一次被使用的位置为止,不是仅在闭包被调用的短暂时间内持有借用。

对应到你的代码里:

  • 你创建inspect闭包时,它就已经拿到了ball的不可变借用。因为你在代码最后还要调用一次inspect,所以这个不可变借用的活跃期会从inspect创建的位置一直持续到最后一次inspect调用结束,完整覆盖了后面edit闭包的创建和调用区间。
  • 你在内部作用域创建edit闭包时,它需要获取ball的可变借用,此时inspect持有的不可变借用还处于活跃状态,直接触发了借用检查错误:同一作用域内不能同时存在活跃的可变借用和不可变借用。
  • 你原本预期edit离开内部作用域就释放可变借用,这个判断本身是对的,但错误在edit创建的那一刻就已经触发了,和edit后续什么时候销毁没有关系。
  • 这也能解释为什么注释掉最后一行inspect()就能编译通过:此时inspect的最后一次使用就是第一次调用的位置,它持有的不可变借用在第一次调用结束后就被释放,后续创建edit时没有活跃的不可变借用冲突,自然可以正常编译。
可行修复方案

核心思路就是让两个闭包持有的借用区间完全不重叠,或者避免闭包长期持有借用:

  • 方案1:手动缩小闭包作用域,让inspect在edit创建前就销毁,需要再次调用时重新创建闭包
#[derive(Default, Debug)]
pub struct Ball {
    pub color: String,
    pub size: String,
}

pub fn moves() {
    let mut ball = Ball {
        color: "blue".to_string(),
        size: "small".to_string(),
    };

    {
        let inspect = || {
            println!("Unremarkable. {} ball. ", (&ball).color);
        };
        inspect();
    } // 此处inspect离开作用域,持有的不可变借用完全释放

    {
        let mut edit = || {
            ball.color = "red".to_string();
        };
        edit()
    }; // edit离开作用域,可变借用释放

    // 需要再次检查时重新创建inspect闭包
    let inspect = || {
        println!("Unremarkable. {} ball. ", (&ball).color);
    };
    inspect();
}
  • 方案2:不让闭包直接捕获环境中的ball,改为通过参数传入引用,这样借用只会在闭包调用时临时产生,调用结束立即释放,不会长期占用
#[derive(Default, Debug)]
pub struct Ball {
    pub color: String,
    pub size: String,
}

pub fn moves() {
    let mut ball = Ball {
        color: "blue".to_string(),
        size: "small".to_string(),
    };

    // 闭包通过参数接收引用,不长期捕获环境变量
    let inspect = |ball: &Ball| {
        println!("Unremarkable. {} ball. ", ball.color);
    };
    let mut edit = |ball: &mut Ball| {
        ball.color = "red".to_string();
    };

    inspect(&ball); // 临时产生不可变借用,调用结束立即释放
    edit(&mut ball); // 临时产生可变借用,调用结束立即释放
    inspect(&ball); // 此时无活跃借用,可正常调用
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:18:15