为什么借用仍然保存在 if let 的 else 块中? [英] Why is a borrow still held in the else block of an if let?
问题描述
为什么下面代码中的调用 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()
}
// ...
我认为这里第二次借用应该没问题,因为 f1
和 f3
没有与 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()
}
正如评论中所指出的,这无需额外的大括号即可工作.这是因为 if
或 if...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>
. Sof1(&mut self) -> Option<Chars>
without elision isf1(&'a mut self) -> Option<Chars<'a>>
which means thatself
remains borrowed as long as the return value fromf1
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屋!