如何在选项为 None 时结束借入

How to end borrow when an Option is None

以下代码将使借用检查器失败:

fn at(&mut self, i: usize) -> Option<&T> {
    match self.vector.get(i) {
        Some(x) => Some(x),
        None => {
            self.mutate_vector_to_have_more_stuff();
            self.at(i)
        }
    }
}

我明白为什么了:self.vector 仍然是借用到最后的词汇,所以我不能再借用 self

构建范围的正确方法是什么?借用持续存在于匹配中,因为我实际上在 Some(x) 分支中使用它,但在 None 分支中我不再使用借用的值,因为开始时没有借用的值。

我有一个适用于这个特定案例的重写版本:

if i >= self.vector.len() {
    self.mutate_vector_to_have_more_stuff();
    self.at(i)
} else {
    self.vector.get(i)
}

这是有效的,因为使用 len 意味着我在尝试借用任何东西之前就见证了 "nothing to borrow",然后只在嵌套范围内借用。我担心这在我有一个 Option 的所有情况下都不起作用,但是,每个 Option 返回的 API 可能没有一个纯布尔变量。

有没有一种方法可以重构此代码使其正常工作,但仍使用 get 调用作为了解是否存在值的主要方式?

由于当前在(稳定的)Rust 中的生命周期工作方式,这是一个常见问题。在您的情况下,标准解决方案看起来像这样:

fn at(&mut self, i: usize) -> Option<&T> {
    if let Some(x) = self.vector.get(i) {
        return Some(x);
    }
    // mutate self.vector
    self.at(i)
}

正如您可能看到的那样,self.vector 的不可变借用仅持续到 if 块,因此可以尽快对其进行可变借用结束了。

也就是说,如果您想启用不稳定的 non-lexical lifetimes 功能,Rust nightly 可以解决此问题。如果您只在 crate 顶部包含 #![feature(nll)] 行,您现有的代码应该可以正常工作。