【发布时间】:2020-10-12 03:14:36
【问题描述】:
此代码编译(playground link):
use std::collections::HashMap;
fn main() {
let mut h = HashMap::<char, Vec<i32>>::new();
h.insert('a', vec![0]);
let first_borrow = h.get_mut(&'a').unwrap();
first_borrow.push(1);
let second_borrow = h.get_mut(&'a').unwrap();
second_borrow.push(2);
}
使用借用改变代码的顺序(push() 调用)...
let first_borrow = h.get_mut(&'a').unwrap();
let second_borrow = h.get_mut(&'a').unwrap();
first_borrow.push(1);
second_borrow.push(2);
...使其无法编译:
error[E0499]: cannot borrow `h` as mutable more than once at a time
--> src/main.rs:8:25
|
7 | let first_borrow = h.get_mut(&'a').unwrap();
| - first mutable borrow occurs here
8 | let second_borrow = h.get_mut(&'a').unwrap();
| ^ second mutable borrow occurs here
9 | first_borrow.push(1);
| ------------ first borrow later used here
此外,在 second_borrow 的实例化之后使用 first_borrow 也不会编译:
let first_borrow = h.get_mut(&'a').unwrap();
first_borrow.push(1);
let second_borrow = h.get_mut(&'a').unwrap();
second_borrow.push(2);
// ...
first_borrow.push(1);
考虑到文档似乎对范围所说的内容,这令人惊讶。在编译的代码中,为什么我们没有两个可变借用呢?
在编译的示例中,Rust 是否看到,在 let second_borrow = ... 之后,任何地方都不再提及 first_borrow,因此它取消借用 first_borrow 的可变借用,因此保留了一个在main()?! 的整个范围内单次借用?!
【问题讨论】:
-
“文档似乎说的范围”到底是什么?在旧版本的 Rust(pre-1.26,IIRC)中,一些这样的代码不会被编译。它现在可以编译。您可能正在阅读一些过时的文档吗?
-
@CoronA 几乎!谢谢。我的情况只是不同,我的可变借用似乎绑定到范围内仍然存在的对象(例如
first_borrow),而在那个问题中,它们仅在范围内的函数调用中。这些案例在技术上可能是等效的,但我的案例对我来说更违反直觉。 -
我推荐阅读current documentation,它解释了借用的行为。
-
当前的文档确实解释了这一点:“请注意,引用的范围从引入它的位置开始,一直持续到最后一次使用该引用。”不幸的是,这是在许多使用
{}大括号表示范围的范围示例的末尾,这让我有点困惑。
标签: rust mutable borrow-checker borrowing