首页 文章

可循环借用

提问于
浏览
5

我有以下代码:

struct Baz {
    x: usize,
    y: usize,
}

struct Bar {
    baz: Baz,
}

impl Bar {
    fn get_baz_mut(&mut self) -> &mut Baz {
        &mut self.baz
    }
}

struct Foo {
    bar: Bar,
}

impl Foo {
    fn foo(&mut self) -> Option<&mut Baz> {
        for i in 0..4 {
            let baz = self.bar.get_baz_mut();
            if baz.x == 0 {
                return Some(baz);
            }
        }
        None
    }
}

Rust Playground

它无法编译:

error[E0499]: cannot borrow `self.bar` as mutable more than once at a time
  --> src/main.rs:23:23
   |
23 |             let baz = self.bar.get_baz_mut();
   |                       ^^^^^^^^ mutable borrow starts here in previous iteration of loop
...
29 |     }
   |     - mutable borrow ends here

但是,如果我从 Foo::foo 返回 Some(baz.x) (并将返回类型更改为 Option<usize> ),则代码将编译 . 这让我相信问题不在于循环,即使编译器似乎表明了这一点 . 更具体地说,我相信本地可变引用 baz 将在循环的下一次迭代中超出范围,导致这是一个非问题 . 上述代码的生命周期问题是什么?

以下问题类似:

但是,它们处理明确声明的生命周期(特别是这些显式生命周期是答案的一部分) . 我的代码省略了这些生命周期,因此删除它们是一种非解决方案 .

1 回答

  • 3

    它不起作用,因为返回借来的值会将借用扩展到函数的末尾 .

    有关一些有用的详细信息,请参阅here .

    这适用于带有 1.27 夜间版本的non-lexical lifetimes

    #![feature(nll)]
    
    struct Baz {
        x: usize,
        y: usize,
    }
    
    // ...
    

    非词汇生命周期RFC解释了生命的实际工作:

    但是当您有一个跨越多个语句的引用时会出现问题 . 在这种情况下,编译器要求生命周期是包含两个语句的最内层表达式(通常是一个块),并且通常比实际需要或期望的要大得多 .

    rustc nightly 1.28

    作为pointed out by @pnkfelix,从夜间1.28开始的非词汇生命期实现不再编译上述代码 .

    但是有a long-term plan to (re)-enable a more powerful NLL analysis .

相关问题