【问题标题】:Cannot borrow `*self` as mutable more than once at a time when returning a Result containing a reference返回包含引用的结果时,不能一次多次借用“* self”作为可变变量
【发布时间】:2020-04-25 08:41:16
【问题描述】:

为什么以下内容无效,我应该怎么做才能使其正常工作?

struct Foo;

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

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

这段代码产生:

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

已经有很多问题存在相同的错误,但我不能用它们来解决这个问题,因为它是由? 提供的隐式返回导致问题,没有? 代码编译成功,但是警告。

Playground

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    这与Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in? 中讨论的问题相同。通过生命周期省略&amp;str 的生命周期与 &amp;self 的生命周期相关联。编译器不知道在返回 Ok 的情况下不会使用借用。它过于保守,不允许使用此代码。这是当前借用检查器实现的一个限制。

    如果您确实需要将Err 变体的生命周期与Foo 实例的生命周期相关联,那么在安全Rust 中没有什么可做的(不安全Rust 是another story)。但是,在您的情况下,您的 &amp;str 似乎不太可能与 self 的生命周期相关联,因此您可以使用显式生命周期来避免该问题。例如,&amp;'static str 是常见的基本错误类型:

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

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

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

    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
    
    

    【讨论】:

    • 您提到:> 如果您确实需要 Err 变体的生命周期与 Foo 实例的生命周期相关联,那么在安全 Rust 中没有太多工作要做我今天遇到了类似的问题: play.rust-lang.org/… 我确实需要 err 的生命周期才能连接到我的“机器”实例。我很好奇如何在 Rust 中实现这一点。
    • @skgbanga 您需要不安全,如链接问题中所述。我现在还链接了另一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    相关资源
    最近更新 更多