为什么下面的代码不编译(Playground):
use std::collections::HashMap;
fn main() {
let mut h: HashMap<u32, u32> = HashMap::new();
h.insert(0, 0);
h.insert(1, h.remove(&0).unwrap());
}
借阅检查器抱怨:
error[E0499]: cannot borrow `h` as mutable more than once at a time
--> src/main.rs:6:17
|
6 | h.insert(1, h.remove(&0).unwrap());
| - ------ ^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
该代码是安全的,但是最后一行的几乎机械转换使其可以编译(操场):
//h.insert(1, h.remove(&0).unwrap());
let x = h.remove(&0).unwrap();
h.insert(1, x);
我的理解是,这种问题在非词汇生命周期中得到了解决。这个问题是一个例子,还有很多其他问题。
是否有一些细微之处使第一个变体毕竟不正确,所以Rust正确地拒绝了它?还是在所有情况下NLL功能都还没有完成?
您的问题也适用于一个可能更令人惊讶的相关情况-&self
当方法参数需要时,有方法调用require &mut self
:
use std::collections::HashMap;
fn main() {
let mut h: HashMap<u32, u32> = HashMap::new();
h.insert(0, 0);
h.contains_key(&h.remove(&0).unwrap());
}
Rust借用检查器使用所谓的两阶段借用。我与Niko Matsakis聊天的经编辑转录:
两阶段借用的想法是,直到实际使用外层,或多或少地将其
&mut
视为&
借用。这使它与内部兼容,因为两个混合,但与内部不兼容。&
&
&mut
如果我们要支持这一点,就必须添加一种新的借用方式-即,“未激活”的
&mut
行为就不会像&
,它会像其他行为(&const
,也许……“其他人可以变异”)尚不清楚这是否可以,而且似乎添加了更多概念,因此我们选择不支持它。
如您所述,这是安全的,因为内部借用在外部借用开始之前就已经完成了,但是实际上认识到此时编译器过于复杂。
也可以看看:
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句