rust - 为什么可变的 self 借贷不会变成不可变的?

标签 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());
}

由于实现了非词汇生存期,因此需要触发以下错误:
fn main() {
    let mut dat = Data { a: 1, b: 2, c: 3 };
    let aref = dat.reference_to_a();
    let b = dat.get_b();
    println!("{:?}, {}", aref, 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()会转换为不可变的借项,因为该函数仅返回不可变的引用。借钱检查员还不够聪明吗?这是有计划的吗?有办法解决吗?

最佳答案

生存期与引用是否可变无关。通过代码工作:

fn reference_to_a(&mut self) -> &i32

尽管生命周期已被消除,但这等效于:
fn reference_to_a<'a>(&'a mut self) -> &'a i32

即输入和输出生命周期是相同的。这是为这样的函数分配生存期的唯一方法(除非它返回了对全局数据的&'static引用),因为您无法一无所获地弥补输出生存期。

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

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

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

关于rust - 为什么可变的 self 借贷不会变成不可变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61918872/

相关文章:

rust - 检查 Rust 中值的连续性

rust - 文档示例中 Unresolved 导入

rust - 从 HashMap 或 Vec 返回引用会导致借用持续超出其所在的范围吗?

loops - 如何改变我正在循环的结构?

rust - 如何在不丢弃物体的情况下解构物体?

rust - 在其函数中捕获变量的结构体

rust - 如果 `write` 不可变, `RwLock` 模式如何工作?

rust - 为什么临时借用是合法的?

for-loop - 何时在 for 循环中使用引用?

rust - 什么时候无法推断 Rust 借用检查器中的生命周期?