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

使用defer-lite crate结合可变结构体时为何出现可变借用编译错误?

问题原因分析

这个编译错误是Rust严格的借用检查规则和defer-lite宏的工作机制共同导致的:

当你在defer!块中调用timer.timer_stop()时,该宏会生成一个持有timer可变引用的闭包,并且这个闭包会被存储到当前作用域末尾才执行。也就是说,从defer!定义完成开始,到main函数结束前,timer的可变引用一直被这个闭包占用着。

而Rust的核心规则之一是:同一时间只能存在一个活跃的可变引用。当你取消注释timer.timer_interval()时,这行代码又尝试获取timer的另一个可变引用,直接触发了借用检查器的报错。

解决方案

方案1:使用内部可变性(RefCell)

通过RefCell实现内部可变性,允许在持有不可变引用的同时修改内部数据,避免外部的可变借用冲突:

use defer_lite::defer;
use std::cell::RefCell;

struct Timer {
    start: RefCell<i32>,
    interval: RefCell<i32>,
    stop: RefCell<i32>,
}

fn timer_initialize() -> Timer {
    Timer {
        start: RefCell::new(0),
        interval: RefCell::new(0),
        stop: RefCell::new(0),
    }
}

impl Timer {
    fn timer_start(&self) { *self.start.borrow_mut() = 1; }
    fn timer_interval(&self) { *self.interval.borrow_mut() = 2; }
    fn timer_stop(&self) { *self.stop.borrow_mut() = 3; }
}

fn main() {
    let timer = timer_initialize();

    println!("Start");
    timer.timer_start();

    defer! {
        println!("Stop");
        timer.timer_stop();
    }

    println!("Interval");
    timer.timer_interval(); // 现在可以正常编译执行
}

方案2:拆分Timer的可变操作逻辑

如果不想引入RefCell,可以通过调整作用域来释放可变引用,避免后续操作的借用冲突:

use defer_lite::defer;

struct Timer {
    start:i32, interval:i32, stop:i32
}

fn timer_initialize() -> Timer {
    Timer{start:0, interval:0, stop:0 }
}

impl Timer {
    fn timer_start(&mut self) { self.start = 1; }
    fn timer_interval(&mut self) { self.interval = 2; }
    fn timer_stop(&mut self) { self.stop = 3; }
}

fn main() {
    let mut timer = timer_initialize();

    println!("Start");
    timer.timer_start();

    // 将defer的作用域限制在不需要后续修改的代码段
    {
        let mut timer_ref = &mut timer;
        defer! {
            println!("Stop");
            timer_ref.timer_stop();
        }
    } // 此处作用域结束,可变引用被释放

    println!("Interval");
    timer.timer_interval(); // 现在可以正常借用
}

补充说明

defer-lite的设计完全遵循Rust的借用规则,问题本质是对Rust生命周期和借用规则的理解偏差——闭包捕获的引用会存活到闭包执行时,而非闭包定义完成就释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 06:06:30