为什么 Rust borrow checker 会忽略函数参数中的可变指针?
Why does Rust borrow checker ignores the mutable pointer among the function parameters?
我刚刚被关于生命周期的 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
returns 一个 Option<&mut String>
类型,其中 &mut String
是一个指向部分地图的借用指针,指针贯穿整个 match
块。然后在 None
分支内,map.insert(key, String::new())
自动创建另一个 &mut HashMap<String, String>
指针,它也指向地图。两个指针两次借用同一个map作为mutable,所以导致:
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.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 执行隐式 reborrow.
A reborrow 相当于从可变引用中借用,然后将引用展平。也就是说,给定类型 &'a T
的可变引用,从中借用会产生 &'b &'a T
(注意有两个不同的生命周期;'b
比 'a
短),并且展平参考产量 &'b T
.
Rust 知道生命周期 'b
的借用是从生命周期 'a
的借用派生出来的。因此,只要 borrow 'b
还活着,borrow 'a
就会被冻结。
在 NLL 之前,为调用 get_mut
获得的借用将在整个 match
块中存在,因为 get_mut
returns 一个使借用保持活动的值。 map.insert(...)
也尝试从 map
重新借用,但是由于从 map
的第一次重新借用仍然有效,所以这是一个错误。
我刚刚被关于生命周期的 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
returns 一个 Option<&mut String>
类型,其中 &mut String
是一个指向部分地图的借用指针,指针贯穿整个 match
块。然后在 None
分支内,map.insert(key, String::new())
自动创建另一个 &mut HashMap<String, String>
指针,它也指向地图。两个指针两次借用同一个map作为mutable,所以导致:
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.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 执行隐式 reborrow.
A reborrow 相当于从可变引用中借用,然后将引用展平。也就是说,给定类型 &'a T
的可变引用,从中借用会产生 &'b &'a T
(注意有两个不同的生命周期;'b
比 'a
短),并且展平参考产量 &'b T
.
Rust 知道生命周期 'b
的借用是从生命周期 'a
的借用派生出来的。因此,只要 borrow 'b
还活着,borrow 'a
就会被冻结。
在 NLL 之前,为调用 get_mut
获得的借用将在整个 match
块中存在,因为 get_mut
returns 一个使借用保持活动的值。 map.insert(...)
也尝试从 map
重新借用,但是由于从 map
的第一次重新借用仍然有效,所以这是一个错误。