将 defer-lite 与可变结构结合使用时出现意外问题

Unexpected Issue when Using defer-lite in combination with a Mutable Struct

提问人:TheLovelySausage 提问时间:7/27/2022 最后编辑:HerohtarTheLovelySausage 更新时间:7/27/2022 访问量:75

问:

我对 Rust 很陌生,但我遇到了一个奇怪的问题,可能是我误解了 defer-lite 板条箱的工作原理。

如果我有以下代码,那么一切都按预期工作

use defer_lite::defer;

fn main() {

    println!("Start");

    defer! {
        println!("Stop");
    }

    println!("Interval");

}

我得到了我想要的输出

Start
Interval
Stop

然后,当我尝试包含可变结构时

use defer_lite::defer;

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

fn timer_initialize() -> Timer {
    let timer = Timer{start:0, interval:0, stop:0 };
    return timer;
}

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! {
        println!("Stop");
        timer.timer_stop();
    }

    println!("Interval");
    // uncommenting this line will cause a compiler error
    //timer.timer_interval();

}

一切仍然正常,直到我尝试使用下面的结构方法,此时我将收到编译器错误defer!

timer.timer_interval();
^^^^^^^^^^^^^^^^^^^^^^ second mutable borrow occurs here

我不确定为什么会这样,如果我使用了 defer-lite 错误

可变

评论

0赞 Jmb 7/27/2022
请添加 中的完整错误消息。话虽如此,您可能需要将结构包装在 RefCell 中。cargo checkTimer

答:

1赞 Chayim Friedman 7/27/2022 #1

这是这个板条箱的局限性。这不能在 Rust 中实现。问题在于,为了完成其工作,需要创建一个 RAII 防护,将清理代码保存为闭包。但是闭包包含对值的可变引用,因此在它被删除之前,您不能再次使用它 - 在作用域的末尾。defer-lite

如果你需要,我会推荐scopeguard板条箱,它也更受欢迎。它为这种情况提供了一个 guard() 函数。它的工作原理如下:

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

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

    let mut timer = scopeguard::guard(timer, |mut timer| {
        println!("Stop");
        timer.timer_stop();
    });

    println!("Interval");

    timer.timer_interval();
}

评论

0赞 TheLovelySausage 7/27/2022
哇,这真是一种巨大的解脱,转移到 scopeguard 正是我所需要的