对自我的可变借用不会变为不可变

时间:2016-12-16 18:26:14

标签: rust borrow-checker

此代码未通过可怕的借用检查程序(playground):

struct Data {
    a: i32,
    b: i32,
    c: i32,
}

impl Data {
    fn reference_to_a(&mut self) -> &i32 {
        self.c = 1;
        &self.a
    }
    fn get_b(&self) -> i32 {
        self.b
    }
}

fn main() {
    let mut dat = Data{ a: 1, b: 2, c: 3 };
    let aref = dat.reference_to_a();
    println!("{}", dat.get_b());
}

错误:

error[E0502]: cannot borrow `dat` as immutable because it is also borrowed as mutable
  --> <anon>:19:20
   |
18 |     let aref = dat.reference_to_a();
   |                --- mutable borrow occurs here
19 |     println!("{}", dat.get_b());
   |                    ^^^ immutable borrow occurs here
20 | }
   | - mutable borrow ends here

有人可以解释为什么会这样吗?当dat返回时,我会认为reference_to_a()的可变借位被转换为不可变的,因为该函数只返回一个不可变引用。借用检查员还不够聪明吗?这是计划好的吗?有办法吗?

2 个答案:

答案 0 :(得分:4)

生命期与参考是否可变是分开的。完成代码:

fn reference_to_a(&mut self) -> &i32

虽然生命周期已被省略,但这相当于:

fn reference_to_a<'a>(&'a mut self) -> &'a i32

即。输入和输出的寿命是相同的。这是将生命周期分配给这样一个函数的唯一方法(除非它返回&'static对全局数据的引用),因为你无法从零构成输出生命周期。

这意味着如果您通过将返回值保存在变量中来保持返回值,那么您也可以使&mut self保持活动状态。

另一种思考方式是&i32&mut self的子借位,因此只有在到期之前才有效。

正如@aSpex指出的那样,这是covered in the nomicon

答案 1 :(得分:0)

为什么会出错: 尽管2.5年前@Chris已经给出了更精确的解释,但您可以阅读fn reference_to_a(&mut self) -> &i32作为声明

  

“我想独占借用self,然后返回一个共享的/不可变的引用,该引用的生存期与原始独占借用时间一样长” source < / sub>

显然it can even prevent me from shooting myself in the foot

借阅检查器是否还不够聪明?这是计划好的吗?

仍然无法表达“我想在通话期间专门借用自己,并返回具有单独生命期的共享引用”。正如@aSpex所指出的那样,它是mentioned in the nomicon,并且在2018年末被列在Things Rust doesn’t let you do中。

如先前的other borrow checker improvements were deemed higher priority一样,我找不到解决该问题的具体计划。允许使用单独的读/写“生命周期角色”(Ref2<'r, 'w>)的想法是mentioned in the NLL RFC,但据我所知,没有人将其变成自己的RFC。

有没有解决的办法? 并非如此,但是首先要根据您需要这样做的原因,可能需要采用其他方式来构造代码: