assert_eq的可变和不可变借用问题

时间:2017-11-21 11:41:30

标签: rust

我正在为LEDDriver重写一些C测试代码到Rust。

struct LEDDriver<'a> {
    address: &'a mut u32,
}

impl<'a> LEDDriver<'a> {
    fn new(address: &'a mut u32) -> Self {
        let leddriver = LEDDriver { address: address };
        *leddriver.address = 0;
        leddriver
    }
}

fn driver_init_leds_off() {
    let ref mut addr = 0xffffffff;
    let leddriver = LEDDriver::new(addr);

    assert_eq!(0, *addr);
}

您可以运行示例here

问题在于assert语句要求ref是不可变的,但我将mut ref传递给LEDDriver以清除addr。

1 个答案:

答案 0 :(得分:2)

由于这是一个最小化的示例,我不确定它是否与您的实际用例匹配,但您可以使用*leddriver.address代替*addr来访问借用后的数据(因为leddriver是借用它的人)

您也可以使用Cell,它不会产生任何内存或运行时开销,但会阻止对内部值的引用。

use std::cell::Cell;

struct LEDDriver<'a> {
    address: &'a Cell<u32>,
}

impl<'a> LEDDriver<'a> {
    fn new(address: &'a Cell<u32>) -> Self {
        let leddriver = LEDDriver { address: address };
        leddriver.address.set(0);
        leddriver
    }
}

fn driver_init_leds_off() {
    let ref mut addr = Cell::new(0xffffffff);
    let leddriver = LEDDriver::new(addr);

    assert_eq!(0, addr.get());
}

如果addr的内存位置将传递给硬件或从中断修改,您应该使用Volatile,因为否则Rust允许假定多个addr.get()没有{中间的{1}}将产生相同的结果,即使硬件或中断可能已经改变它