为什么借用仍然保存在 if let 的 else 块中? [英] Why is a borrow still held in the else block of an if let?

查看:34
本文介绍了为什么借用仍然保存在 if let 的 else 块中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么下面代码中的调用 self.f2() 会触发借用检查器?else 块不是在不同的范围内吗?这真是一个难题!

Why does the call self.f2() in the following code trip the borrow checker? Isn't the else block in a different scope? This is quite a conundrum!

use std::str::Chars;

struct A;

impl A {
    fn f2(&mut self) {}

    fn f1(&mut self) -> Option<Chars> {
        None
    }

    fn f3(&mut self) {
        if let Some(x) = self.f1() {

        } else {
            self.f2()
        }
    }
}

fn main() {
    let mut a = A;
}

游乐场

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/main.rs:16:13
   |
13 |         if let Some(x) = self.f1() {
   |                          ---- first mutable borrow occurs here
...
16 |             self.f2()
   |             ^^^^ second mutable borrow occurs here
17 |         }
   |         - first borrow ends here

self 的借用范围不是以 self.f1() 调用开始和结束吗?一旦来自 f1() 的调用返回 f1() 就不再使用 self ,因此借用检查器在第二次借用时应该不会有任何问题.注意下面的代码也失败了...

Doesn't the scope of the borrow for self begin and end with the self.f1() call? Once the call from f1() has returned f1() is not using self anymore hence the borrow checker should not have any problem with the second borrow. Note the following code fails too...

// ...
if let Some(x) = self.f1() {
    self.f2()
}
// ...

游乐场

我认为这里第二次借用应该没问题,因为 f1f3 没有与 f2 同时使用 self.

I think the second borrow should be fine here since f1 and f3 are not using self at the same time as f2.

推荐答案

这很烦人,但您可以通过引入内部作用域并稍微更改控制流来解决此问题:

It's annoying, but you can work around this by introducing an inner scope and changing the control flow a bit:

fn f3(&mut self) {
    {
        if let Some(x) = self.f1() {
            // ...
            return;
        }
    }
    self.f2()
}

正如评论中所指出的,这无需额外的大括号即可工作.这是因为 ifif...let 表达式具有隐式作用域,并且借用持续到该作用域:

As pointed out in the comments, this works without the extra braces. This is because an if or if...let expression has an implicit scope, and the borrow lasts for this scope:

fn f3(&mut self) {
    if let Some(x) = self.f1() {
        // ...
        return;
    }

    self.f2()
}

这是 Sandeep Datta 和 mbrubeck 之间的 IRC 聊天记录:

Here's a log of an IRC chat between Sandeep Datta and mbrubeck:

mbrubeck: std:tr::Chars 包含对创建它的字符串的借用引用.完整的类型名称是 Chars<'a>.所以 f1(&mut self) ->Option 没有省略是 f1(&'a mut self) ->Option<Chars<'a>> 这意味着只要 self 保持借用f1 的返回值在范围内.

mbrubeck: std:tr::Chars contains a borrowed reference to the string that created it. The full type name is Chars<'a>. So f1(&mut self) -> Option<Chars> without elision is f1(&'a mut self) -> Option<Chars<'a>> which means that self remains borrowed as long as the return value from f1 is in scope.

Sandeep Datta:我可以将 'b 用于 self 并将 'a 用于 Chars 来避免这个问题吗?

Sandeep Datta: Can I use 'b for self and 'a for Chars to avoid this problem?

mbrubeck:如果您实际上是从 self 返回一个迭代器,则不会.虽然如果你可以从 &self -> 制作一个函数可以解决问题的字符(而不是 &mut self -> Chars).

mbrubeck: Not if you are actually returning an iterator over something from self. Though if you can make a function from &self -> Chars (instead of &mut self -> Chars) that would fix the issue.

这篇关于为什么借用仍然保存在 if let 的 else 块中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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