我有一个带有
Option
的结构,用于通过 getter 方法延迟初始化字段。
这是我的简化代码(playground):
struct Worker {
worktree: Option<PathBuf>, // Access via get_worktree
}
impl Worker {
fn get_worktree(&mut self) -> Result<&PathBuf, ()> {
if let Some(ref path) = &self.worktree {
// Already initialized, just return
return Ok(path);
}
// First call, initialize lazily and return.
let path = PathBuf::from("<result of a fallible process>");
self.worktree.insert(path);
Ok(self.worktree.as_ref().unwrap())
}
}
此操作失败并出现以下错误:
error[E0502]: cannot borrow `self.worktree` as mutable because it is also borrowed as immutable
--> src/lib.rs:17:9
|
9 | fn get_worktree(&mut self) -> Result<&PathBuf, ()> {
| - let's call the lifetime of this reference `'1`
10 | if let Some(ref path) = &self.worktree {
| -------------- immutable borrow occurs here
11 | // Already initialized, just return
12 | return Ok(path);
| -------- returning this value requires that `self.worktree` is borrowed for `'1`
...
17 | self.worktree.insert(path);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
我将其理解为:我在初始条件中返回的借用被视为与将新值插入到
Option
中所必需的可变借用重叠。
我想这是因为一旦它从函数返回,就必须假设该引用与
Worker
一样长,因此借用检查器禁止从 Worker::worktree
可能存在的上下文中对 get_worktree
进行任何可变引用之前打过电话。
(到目前为止我有这个权利吗?)
I知道在我获取可变引用的这一点上,
get_worktree
之前不能被调用(因为我们只到达这个分支一次)。有没有办法帮助借阅检查员解决这个问题?
我相信我可以用
RefCell
“逃脱”这个问题,我还没有完全弄清楚如何做到这一点,但更重要的是我怀疑我不会学习借用检查器的方式,除非我尝试抵抗RefCell
玩 Rust 时!
嗯,这是一个相当简单的技巧 - 只需反转 getter 中的条件即可!
fn get_worktree(&mut self) -> Result<&PathBuf, ()> {
if self.worktree.is_none() {
self.worktree.replace(PathBuf::from("<result of a fallible process>"));
}
Ok(self.worktree.as_ref().unwrap())
}
我无法决定我是否对此答案感到满意,我真的不觉得我在这里学到了任何关于 Rust 的知识,更像是我刚刚找到了解决这个特定问题的技巧......