我一直遇到一个编译错误,Rust抱怨我在尝试可变借用时有一个不可变借用,但是不可变借用来自另一个范围,并且我没有从中携带任何内容。
我有一些代码,在映射中检查值,如果存在,则返回它,否则需要以各种方式改变映射。问题在于,即使这两个操作完全分开,我似乎也找不到让Rust让我这样做的方法。
这里有一些无意义的代码,它遵循与我的代码相同的结构并展示了问题:
use std::collections::BTreeMap;
fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> {
// extra scope in vain attempt to contain the borrow
{
// borrow immutably
if let Some(key) = map.get(&key) {
return Some(key);
}
}
// now I'm DONE with the immutable borrow, but rustc still thinks it's borrowed
map.insert(0, 0); // borrow mutably, which errors
None
}
这会出现错误:
error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable
--> src/lib.rs:14:5
|
3 | fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> {
| - let's call the lifetime of this reference `'1`
...
7 | if let Some(key) = map.get(&key) {
| --- immutable borrow occurs here
8 | return Some(key);
| --------- returning this value requires that `*map` is borrowed for `'1`
...
14 | map.insert(0, 0); // borrow mutably, which errors
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
这对我来说毫无意义。不可变的借用如何超出了那个作用域?!那个match
语句的一个分支通过return
退出函数,另一个分支什么也不做并离开了该作用域。
我曾经看到过类似情况,当时我错误地使用了另一个变量将借用移出了作用域,但这里并非如此!
的确,借用通过return
语句逃逸了作用域,但是荒谬的是它阻止了函数下面更远处的借用——程序不可能返回并继续运行!如果我在那里返回其他内容,错误就消失了,因此我认为这是借用检查器卡住的原因。这感觉像是一个bug。
不幸的是,我一直无法找到任何重写方法而不会遇到相同错误,所以如果是这种情况,这就是一个特别棘手的bug。