以下代码无法编译:

struct Foo {
    values: Vec<i32>,
}

impl Foo {
    fn len(&self) -> usize {
        todo!()
    }
    
    fn set(&mut self) {
        self.values[self.len()] = 0;
    }
}
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src/lib.rs:12:21
   |
12 |         self.values[self.len()] = 0;
   |         ------------^^^^^^^^^^-
   |         |           |
   |         |           immutable borrow occurs here
   |         mutable borrow occurs here
   |         mutable borrow later used here

Playground

有许多方法可以修复这个错误,对我来说最令人困惑的是:

    fn set(&mut self) {
        self.set_len(self.len()); // <----- double borrow again?
    }
    
    fn set_len(&mut self, index: usize) {
        self.values[index] = 0;
    }

Playground

为什么第一种情况无法编译,而第二种情况可以编译?在我看来,在这两种情况下,self在一个表达式中都被借了两次--一次是沉默的,一次是不变的.这是不是有我看不到的微妙原因,或者是借阅判断器的怪癖?

推荐答案

这是借入支票的怪癖.有一个实现的特殊规则来解决"调用可变方法,其中一个参数是另一个方法的结果"的问题.

对于"访问一个成员并在需要方法结果的地方做一些事情",没有特殊的规则.首先borrow 成员,然后不能再为方法调用borrow 整个对象.

Rust相关问答推荐

为什么幻影数据不能自动推断?

收集RangeInclusive T到Vec T<><>

抽象RUST中的可变/不可变引用

如何为 struct 字段设置新值并在Ruust中的可变方法中返回旧值

可以为rust构建脚本编写单元测试吗?

为什么实现特征的对象期望比具体对象有更长的生命周期?

这个不安全的 Rust 代码有什么问题,所以它可以在 Windows 上运行,但不能在 Ubuntu 上运行?

如何在 Rust 中打印 let-else 语句中的错误?

如何保存指向持有引用数据的指针?

Rust中是否可以在不复制的情况下从另一个不可变向量创建不可变向量?

decltype、dyn、impl traits,重构时如何声明函数的返回类型

如何限制通用 const 参数中允许的值?

在运行时在 Rust 中加载字体

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

Rust 异步和 AsRef 未被发送

如何使用 rust bindgen 生成的 std_vector

隐式类型闭包的错误生命周期推断

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?

有没有办法在 Rust 中对 BigInt 进行正确的位移?

A 有一个函数,它在 Option<> 类型中时无法编译,但在 Option<> 类型之外会自行编译.为什么?