返回包含引用的结果时,不能一次多次借用 `*self` 作为可变变量 [英] Cannot borrow `*self` as mutable more than once at a time when returning a Result containing a reference

查看:31
本文介绍了返回包含引用的结果时,不能一次多次借用 `*self` 作为可变变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么以下无效,我应该怎么做才能使它起作用?

struct Foo;impl Foo {fn mutable1(&mut self) ->结果<(), &str>{好的(())}fn mutable2(&mut self) ->结果<(), &str>{self.mutable1()?;self.mutable1()?;好的(())}}

此代码产生:

error[E0499]: 不能一次多次借用 `*self` 作为可变变量-->src/lib.rs:10:9|8 |fn mutable2(&mut self) ->结果<(), &str>{|- 让我们将此引用的生命周期称为1"9 |self.mutable1()?;|---- - 返回这个值需要为 `'1` 借用 `*self`|||第一个可变借用发生在这里10 |self.mutable1()?;|^^^^ 第二个可变借用发生在这里

已经有很多问题出现了相同的错误,但我无法使用它们来解决这个问题,因为 ? 提供的隐式返回的存在导致了问题,而没有 ? 代码编译成功,但有警告.

游乐场

解决方案

这与 从 HashMap 返回引用中讨论的问题相同或 Vec 导致借用持续超出其范围?.通过生命周期省略&str 的生命周期与&self 的生命周期相关联.编译器不知道在返回 Ok 的情况下不会使用借用.它过于保守并且不允许使用此代码.这是当前借用检查器实现的局限性.

如果您确实需要将 Err 变体的生命周期绑定到 Foo 实例的生命周期,那么在安全 Rust(不安全 Rust是另一个故事).但是,在您的情况下,您的 &str 似乎不太可能与 self 的生命周期相关联,因此您可以使用显式生命周期来避免该问题.例如,&'static str 是一种常见的基本错误类型:

impl Foo {fn mutable1(&mut self) ->结果<(), &'static str>{好的(())}fn mutable2(&mut self) ->结果<(), &'static str>{self.mutable1()?;self.mutable1()?;好的(())}}

<块引用>

因为它存在 提供的隐式返回?

并非如此,因为带有 explicit 返回的相同代码具有相同的问题:

fn mutable2(&mut self) ->结果<(), &str>{如果让 Err(e) = self.mutable1() {返回错误(e);}如果让 Err(e) = self.mutable1() {返回错误(e);}好的(())}

error[E0499]: 不能一次多次借用 `*self` 作为可变变量-->src/lib.rs:12:25|8 |fn mutable2(&mut self) ->结果<(), &str>{|- 让我们将此引用的生命周期称为1"9 |如果让 Err(e) = self.mutable1() {|---- 第一个可变借用发生在这里10 |返回错误(e);|------ 返回这个值需要`*self` 被借用于`'1`11 |}12 |如果让 Err(e) = self.mutable1() {|^^^^ 第二个可变借用发生在这里

Why is the following invalid and what should I do instead to make it work?

struct Foo;

impl Foo {
    fn mutable1(&mut self) -> Result<(), &str> {
        Ok(())
    }

    fn mutable2(&mut self) -> Result<(), &str> {
        self.mutable1()?;
        self.mutable1()?;
        Ok(())
    }
}

This code yields:

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/lib.rs:10:9
   |
8  |     fn mutable2(&mut self) -> Result<(), &str> {
   |                 - let's call the lifetime of this reference `'1`
9  |         self.mutable1()?;
   |         ----           - returning this value requires that `*self` is borrowed for `'1`
   |         |
   |         first mutable borrow occurs here
10 |         self.mutable1()?;
   |         ^^^^ second mutable borrow occurs here

There are many questions already with the same error but I cannot use them to address this one as it's the presence of the implicit return provided by ? that causes the problem, without ? the code compiles successfully, yet with warnings.

Playground

解决方案

This is the same problem discussed in Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?. Through lifetime elision, the lifetime of the &str is tied to the lifetime of &self. The compiler isn't aware that the borrow won't be used in the condition that an Ok is returned. It's overly conservative and disallows this code. This is a limitation of the current borrow checker implementation.

If you did need the lifetime of the Err variant to be tied to the lifetime of the Foo instance, there's not much to be done in safe Rust (unsafe Rust is another story). In your case, however, it seems unlikely that your &str is intended to be tied to the lifetime of self, so you can use explicit lifetimes to avoid the problem. For example, a &'static str is a common basic error type:

impl Foo {
    fn mutable1(&mut self) -> Result<(), &'static str> {
        Ok(())
    }

    fn mutable2(&mut self) -> Result<(), &'static str> {
        self.mutable1()?;
        self.mutable1()?;
        Ok(())
    }
}

as it's the presence of the implicit return provided by ?

Not really, as the same code with explicit returns has the same problem:

fn mutable2(&mut self) -> Result<(), &str> {
    if let Err(e) = self.mutable1() {
        return Err(e);
    }
    if let Err(e) = self.mutable1() {
        return Err(e);
    }
    Ok(())
}

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/lib.rs:12:25
   |
8  |     fn mutable2(&mut self) -> Result<(), &str> {
   |                 - let's call the lifetime of this reference `'1`
9  |         if let Err(e) = self.mutable1() {
   |                         ---- first mutable borrow occurs here
10 |             return Err(e);
   |                    ------ returning this value requires that `*self` is borrowed for `'1`
11 |         }
12 |         if let Err(e) = self.mutable1() {
   |                         ^^^^ second mutable borrow occurs here

这篇关于返回包含引用的结果时,不能一次多次借用 `*self` 作为可变变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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