为什么 Rust 在已经持有可变借用的情况下再次尝试借用 *self 作为可变借用?
Why does Rust try to borrow *self as mutable again, when it already holds a mutable borrow?
为什么下面的程序会产生如下错误?有什么办法可以在不改变程序流程的情况下修复错误吗?
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:10:39
|
9 | for bar in &mut self.bars {
| --------------
| |
| first mutable borrow occurs here
| first borrow later used here
10 | bar.add_foo_value_and_inc(self);
| ^^^^ second mutable borrow occurs here
程序:
#[derive(Debug)]
struct Foo {
add_value: u32,
bars: Vec<Bar>,
}
impl Foo {
fn add_value_to_bars(&mut self) {
for bar in &mut self.bars {
bar.add_foo_value_and_inc(self);
}
}
}
#[derive(Debug)]
struct Bar {
value: u32,
}
impl Bar {
fn add_foo_value_and_inc(&mut self, foo: &mut Foo) {
self.value += foo.add_value;
foo.add_value += 1;
}
}
fn main() {
let mut foo = Foo{add_value: 1, bars: vec![Bar{value:2}, Bar{value:3}]};
foo.add_value_to_bars();
}
在我看来,函数 add_value_to_bars
已经持有对 self
的可变引用(这是函数的参数)。那么,为什么它在调用 bar.add_foo_value_and_inc
时再次尝试借用 self
作为可变 ?
注意:这是一个用于重现问题的最小程序,因此它不是明智的。
编辑:@Herohtar 评论说“add_foo_value_and_inc 试图可变地借用 self
而 add_value_to_bars 已经拥有一个可变引用,因此它被第二次借用。"
如果是这个原因,那么为什么下面的代码编译 运行 没有任何问题?
函数 add_three
已经持有对 x
的可变引用。函数 add_two
接受一个可变的
再次参考 x
但在这种情况下不会造成任何问题
fn main() {
let mut x: u32 = 1234;
add_three(&mut x);
}
fn add_three(x: &mut u32) {
add_two(x);
add_one(x);
}
fn add_two(x: &mut u32) {
*x += 2;
}
fn add_one(x: &mut u32) {
*x += 1;
}
这是 Rust 在做 Rust 的设计目的:防止您以不安全的方式使用内存。
对 self.bars
的可变引用被借用并赋予 implicitly-created std::slice::IterMut
值(循环正在使用的迭代器)。因此,self
不能在循环内可变地借用——它包含已经借用的 self.bars
。
如果 Rust 允许这种情况发生,将会有两个 concurrently-existing 可变引用,通过它们 self.bars
可以被改变,这就是 正是 借用的东西检查器旨在防止。
但是有一个解决方案:您可以可以在循环中借用self
的不同部分。如果您将 Bar::add_foo_value_and_inc
更改为接受 &mut u32
而不是 &mut Foo
,那么您可以借用 self.add_value
,这是此方法修改的唯一字段。
#[derive(Debug)]
struct Foo {
add_value: u32,
bars: Vec<Bar>,
}
impl Foo {
fn add_value_to_bars(&mut self) {
for bar in &mut self.bars {
bar.add_foo_value_and_inc(&mut self.add_value);
}
}
}
#[derive(Debug)]
struct Bar {
value: u32,
}
impl Bar {
fn add_foo_value_and_inc(&mut self, foo_value: &mut u32) {
self.value += *foo_value;
*foo_value += 1;
}
}
fn main() {
let mut foo = Foo{add_value: 1, bars: vec![Bar{value:2}, Bar{value:3}]};
foo.add_value_to_bars();
}
为什么下面的程序会产生如下错误?有什么办法可以在不改变程序流程的情况下修复错误吗?
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:10:39
|
9 | for bar in &mut self.bars {
| --------------
| |
| first mutable borrow occurs here
| first borrow later used here
10 | bar.add_foo_value_and_inc(self);
| ^^^^ second mutable borrow occurs here
程序:
#[derive(Debug)]
struct Foo {
add_value: u32,
bars: Vec<Bar>,
}
impl Foo {
fn add_value_to_bars(&mut self) {
for bar in &mut self.bars {
bar.add_foo_value_and_inc(self);
}
}
}
#[derive(Debug)]
struct Bar {
value: u32,
}
impl Bar {
fn add_foo_value_and_inc(&mut self, foo: &mut Foo) {
self.value += foo.add_value;
foo.add_value += 1;
}
}
fn main() {
let mut foo = Foo{add_value: 1, bars: vec![Bar{value:2}, Bar{value:3}]};
foo.add_value_to_bars();
}
在我看来,函数 add_value_to_bars
已经持有对 self
的可变引用(这是函数的参数)。那么,为什么它在调用 bar.add_foo_value_and_inc
时再次尝试借用 self
作为可变 ?
注意:这是一个用于重现问题的最小程序,因此它不是明智的。
编辑:@Herohtar 评论说“add_foo_value_and_inc 试图可变地借用 self 而 add_value_to_bars 已经拥有一个可变引用,因此它被第二次借用。"
如果是这个原因,那么为什么下面的代码编译 运行 没有任何问题?
函数 add_three
已经持有对 x
的可变引用。函数 add_two
接受一个可变的
再次参考 x
但在这种情况下不会造成任何问题
fn main() {
let mut x: u32 = 1234;
add_three(&mut x);
}
fn add_three(x: &mut u32) {
add_two(x);
add_one(x);
}
fn add_two(x: &mut u32) {
*x += 2;
}
fn add_one(x: &mut u32) {
*x += 1;
}
这是 Rust 在做 Rust 的设计目的:防止您以不安全的方式使用内存。
对 self.bars
的可变引用被借用并赋予 implicitly-created std::slice::IterMut
值(循环正在使用的迭代器)。因此,self
不能在循环内可变地借用——它包含已经借用的 self.bars
。
如果 Rust 允许这种情况发生,将会有两个 concurrently-existing 可变引用,通过它们 self.bars
可以被改变,这就是 正是 借用的东西检查器旨在防止。
但是有一个解决方案:您可以可以在循环中借用self
的不同部分。如果您将 Bar::add_foo_value_and_inc
更改为接受 &mut u32
而不是 &mut Foo
,那么您可以借用 self.add_value
,这是此方法修改的唯一字段。
#[derive(Debug)]
struct Foo {
add_value: u32,
bars: Vec<Bar>,
}
impl Foo {
fn add_value_to_bars(&mut self) {
for bar in &mut self.bars {
bar.add_foo_value_and_inc(&mut self.add_value);
}
}
}
#[derive(Debug)]
struct Bar {
value: u32,
}
impl Bar {
fn add_foo_value_and_inc(&mut self, foo_value: &mut u32) {
self.value += *foo_value;
*foo_value += 1;
}
}
fn main() {
let mut foo = Foo{add_value: 1, bars: vec![Bar{value:2}, Bar{value:3}]};
foo.add_value_to_bars();
}