循环中的可变借用 [英] Mutable borrow in a loop

查看:37
本文介绍了循环中的可变借用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

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>),代码编译.这让我相信问题不在于循环,即使编译器似乎表明了这一点.更具体地说,我相信本地可变引用 baz 会在循环的下一次迭代中超出范围,导致这不是问题.上面代码的生命周期问题是什么?

However, if I return Some(baz.x) from Foo::foo (and change the return type to Option<usize>), the code compiles. This makes me believe the problem is not with the loop even though the compiler seems to indicate so. More specifically, I believe the local mutable reference baz would go out of scope at the next iteration of the loop, causing this to be a non-problem. What is the lifetime problem with the above code?

以下问题类似:

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

However, they deal with explicitly declared lifetimes (and specifically these explicit lifetimes are part of the answer). My code omits these lifetimes so removing them is a non-solution.

推荐答案

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

It does not work because returning a borrowed value extends the borrow to the end of the function.

请参阅此处了解一些有用的详细信息.

See here for some useful details.

这适用于 非词法生命周期 使用 1.27 夜间版本:

This works with non-lexical lifetimes with the 1.27 nightly version:

#![feature(nll)]

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

// ...

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

The non-lexical lifetimes RFC explains the actual working of lifetimes:

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

Problems arise however when you have a reference that spans multiple statements. In that case, the compiler requires the lifetime to be the innermost expression (which is often a block) that encloses both statements, and that is typically much bigger than is really necessary or desired

rustc 每晚 1.28

正如@pnkfelix 指出的指出的那样,非词法生命周期实现从 nightly 1.28 开始不再编译上述代码.

As pointed out by @pnkfelix, the non-lexical lifetimes implementation starting from nightly 1.28 no longer compiles the above code.

然而,有一个长期计划(重新)-启用更强大的 NLL 分析.

这篇关于循环中的可变借用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆