Roy*_*son 3 rust borrow-checker
先前的问题是,这不是以下内容的重复:
我有以下结构:
struct Foo {
data: Vec<Bar>,
a: usize,
}
struct Bar {
b: usize
}
Run Code Online (Sandbox Code Playgroud)
在里面impl Foo,我有以下方法:
fn example(&mut self, c: usize) {
let baz = &mut self.data[c];
let z = self.calc(c);
baz.b = 42 + z;
}
fn calc(&self, x: usize) -> usize {
self.a * x
}
Run Code Online (Sandbox Code Playgroud)
当然,Rust 编译器会抛出一个错误,大致是“在创建 时发生可变借用baz,然后在调用时执行不可变借用self.calc,最后在分配给 时使用可变借用baz.a。
但是,我正在访问结构上的不相交字段,因为calc从不读取通过 写入的数据baz。
有没有办法通知 Rust 编译器这一点?
问题是作为接收者的 的Foo::calc签名&self。这保证了calc不存在对所有 的可变引用self,包括其任何字段;也就是说,从主体的角度来看,所有 of 都Foo保证是不可变的。calc这对于代码来说是不可能的,因为在可变借用仍然处于活动状态时self.calc(c)需要一成不变地借用self(全部) 。self
事实上,calc从不读取正在写入的数据baz是无关紧要的。在 Rust 中,关于函数或方法的所有信息都在签名中公开;编译器从不“查看”函数来确定它是否是特殊情况。
calc您可以通过不要求作为&self接收者来避免该问题。例如,通过在调用 ( Self::calc(&self.a, c)) 之前借用各个字段,或者如下例所示,根本不借用self:
impl Foo {
fn example(&mut self, c: usize) {
let baz = &mut self.data[c];
// This avoids borrowing `self` in its entirety...
let z = Self::calc(self.a, c);
baz.b = 42 + z;
}
fn calc(a: usize, x: usize) -> usize {
a * x
}
}
Run Code Online (Sandbox Code Playgroud)