一个分支中归还的借用与另一分支中的借用重叠

问题描述 投票:0回答:1

我有一个带有

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 时!

rust borrow-checker
1个回答
0
投票

嗯,这是一个相当简单的技巧 - 只需反转 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 的知识,更像是我刚刚找到了解决这个特定问题的技巧......

© www.soinside.com 2019 - 2024. All rights reserved.