关于生命周期的 rust 编译错误让我感到困惑。

假设代码片段如下所示:

fn process(map: &mut HashMap<String, String>, key: String) {
    match map.get_mut(&key) {
        Some(value) => println!("value: {}", value),
        None => {
            map.insert(key, String::new());
        }
    }
}

我这样称呼它:

fn main() {
    let mut map = HashMap::<String, String>::new();
    let key = String::from("name");
    process(&mut map, key);
}

据我所知(忽略 NLL 功能),map.get_mut返回Option<&mut String>类型,其中&mut String是指向 map 一部分的借入指针,并且该指针贯穿整个match块。然后在None分支内,map.insert(key, String::new())自动创建另一个&mut HashMap<String, String>指针,该指针也指向 map 。这两个指针两次将相同的映射借为可变的,因此它导致:

error[E0499]: cannot borrow `*map` as mutable more than once at a time
 --> test.rs:7:13
  |
4 |     match map.get_mut(&key) {
  |           --- first mutable borrow occurs here
...
7 |             map.insert(key, String::new());
  |             ^^^ second mutable borrow occurs here
8 |         }
9 |     }
  |     - first borrow ends here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0499`.

但是我的问题是:

函数fn process的第一个参数是一个可变的指针本身(&mut HashMap<String, String>),它也指向 map 。根据上述规则,当下一行调用map.get_mut(&key)时,发生第二次可变借用。为什么编译器不会抛出这样的错误(存在内存安全的风险?):

fn process(map: &mut HashMap<String, String>, key: String)
           --- first mutable borrow occurs here
    match map.get_mut(&key)
    ^^^ second mutable borrow occurs here // the return value of type Option<&mut String>

我是新来的 rust ,任何技巧将不胜感激。

最佳答案

为了执行对get_mut的调用,Rust执行隐式的重新借用。

重新借入等同于从可变引用中借用,然后将其展平。也就是说,给定可变类型&'a T的引用,借用它会产生&'b &'a T(请注意,存在两个不同的生存期; 'b'a短),并且将引用展平会产生&'b T

Rust理解,生命周期为'b的借用是从生命周期为'a的借用派生的。因此,只要借用'a仍然存在,就将冻结借用'b

在NLL之前,通过调用get_mut获得的借用将在整个match块中存在,因为get_mut返回的值将使借用保持 Activity 状态。 map.insert(...)也尝试从map重新借入,但是由于第一次从map重新借入仍处于 Activity 状态,所以这是一个错误。

关于rust - 为什么Rust借用检查器会忽略函数参数中的可变指针?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58577762/

10-11 18:22