函数参数中的可变借位

用户名

为什么下面的代码不编译(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功能都还没有完成?

Shepmaster

您的问题也适用于一个可能更令人惊讶的相关情况-&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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章