为什么以下代码中的调用 self.f2()
会触发借用检查器? else block 不是在不同的范围内吗?这是一个难题!
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,因此借用检查器应该不会对第二次借用有任何问题。请注意以下代码也失败了...
// ...
if let Some(x) = self.f1() {
self.f2()
}
// ...
我认为第二次借用在这里应该没问题,因为 f1
和 f3
没有与 f2 同时使用
。self
最佳答案
我在这里举了一个例子来展示范围规则:
struct Foo {
a: i32,
}
impl Drop for Foo {
fn drop(&mut self) {
println!("Foo: {}", self.a);
}
}
fn generate_temporary(a: i32) -> Option<Foo> {
if a != 0 { Some(Foo { a: a }) } else { None }
}
fn main() {
{
println!("-- 0");
if let Some(foo) = generate_temporary(0) {
println!("Some Foo {}", foo.a);
} else {
println!("None");
}
println!("-- 1");
}
{
println!("-- 0");
if let Some(foo) = generate_temporary(1) {
println!("Some Foo {}", foo.a);
} else {
println!("None");
}
println!("-- 1");
}
{
println!("-- 0");
if let Some(Foo { a: 1 }) = generate_temporary(1) {
println!("Some Foo {}", 1);
} else {
println!("None");
}
println!("-- 1");
}
{
println!("-- 0");
if let Some(Foo { a: 2 }) = generate_temporary(1) {
println!("Some Foo {}", 1);
} else {
println!("None");
}
println!("-- 1");
}
}
这打印:
-- 0
None
-- 1
-- 0
Some Foo 1
Foo: 1
-- 1
-- 0
Some Foo 1
Foo: 1
-- 1
-- 0
None
Foo: 1
-- 1
简而言之,if
子句中的表达式似乎同时存在于 if
block 和 else
block 中。
一方面,这并不奇怪,因为它确实需要比 if
block 更长寿,但另一方面,它确实阻止了有用的模式。
如果您更喜欢直观的解释:
if let pattern = foo() {
if-block
} else {
else-block
}
脱糖成:
{
let x = foo();
match x {
pattern => { if-block }
_ => { else-block }
}
}
虽然您希望它脱糖成:
bool bypass = true;
{
let x = foo();
match x {
pattern => { if-block }
_ => { bypass = false; }
}
}
if not bypass {
else-block
}
你不是第一个被这个绊倒的人,所以尽管改变了一些代码的含义(特别是守卫),这可能会在某个时候得到解决。
关于rust - 为什么借用仍然保留在 if let 的 else block 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30698061/