我一直磕磕绊绊地看着我的Rust程序中的模式,这种模式总是让我与借用检查器发生冲突。请考虑以下玩具示例:
use std::sync::{Arc,RwLock};
pub struct Test {
thing: i32,
}
pub struct Test2 {
pub test: Arc<RwLock<Test>>,
pub those: i32,
}
impl Test {
pub fn foo(&self) -> Option<i32> {
Some(3)
}
}
impl Test2 {
pub fn bar(&mut self) {
let mut test_writer = self.test.write().unwrap();
match test_writer.foo() {
Some(thing) => {
self.add(thing);
},
None => {}
}
}
pub fn add(&mut self, addme: i32) {
self.those += addme;
}
}
这不会编译,因为add
中的Some
函数试图可变地借用自己,这已经在match语句之上不可靠地借用以打开读写锁。
我在Rust中遇到过这种模式几次,主要是在使用RwLock
时。我还找到了一种解决方法,即在match
语句之前引入一个布尔值,然后在Some
臂中更改布尔值,然后最后在此布尔值后引入一个测试匹配语句,以便在Some
手臂上做我想做的任何事情。
在我看来,这不是解决问题的方法,我认为在Rust中这样做更为惯用的方式 - 或以完全不同的方式解决问题 - 但我找不到它。如果我没有弄错,问题与词汇借用有关,所以self
不能在匹配声明的范围内可变地借用。
是否有一种惯用的Rust方式来解决这类问题?
答案 0 :(得分:2)
Use directly the field those
, for example with custom type:
use std::sync::{Arc,RwLock};
pub struct Those(i32);
impl Those {
fn get(&self) -> i32 {
self.0
}
fn add(&mut self, n: i32) {
self.0 += n;
}
}
pub struct Test {
thing: Those,
}
pub struct Test2 {
pub test: Arc<RwLock<Test>>,
pub those: Those,
}
impl Test {
pub fn foo(&self) -> Option<Those> {
Some(Those(3))
}
}
impl Test2 {
pub fn bar(&mut self) {
let mut test_writer = self.test.write().unwrap();
match test_writer.foo() {
Some(thing) => {
// call a method add directly on your type to get around the borrow checker
self.those.add(thing.get());
},
None => {}
}
}
}
答案 1 :(得分:1)
You either need to end borrow of a part of self
, before mutating self
pub fn bar1(&mut self) {
let foo = self.test.write().unwrap().foo();
match foo {
Some(thing) => {
self.add(thing);
},
None => {}
}
}
or directly mutate non borrowed part of self
pub fn bar2(&mut self) {
let test_writer = self.test.write().unwrap();
match test_writer.foo() {
Some(thing) => {
self.those += thing;
},
None => {}
}
}