rust_interview
rust_interview copied to clipboard
[Practice] 该段代码为什么会通过?
trafficstars
Rust Nightly 1.22.0
use std::collections::BTreeMap;
fn foo(_qux: &BTreeMap<&'static str, &'static str>) -> Option<String> {
Some("baz".to_owned())
}
fn main() {
let mut map = BTreeMap::new();
map.insert("foo", "bar");
foo(&map).and_then( |baz| {
let mut map = map;
map.insert("sign", &baz);
Some(())
});
}
如果注释掉 let mut map = map; ,为什么会报错?
相关issue: https://github.com/rust-lang/rust/issues/45587
当去掉let语句之后产生了如下的语义:
- rustc推断在main中声明的
map的K, V是具有'staticlifetime, 理由是foo函数接受了map作为参数; foo返回的Some是to_owned的关系, 所以变量baz会被move到闭包之中, 于是其析构也会提前到闭包调用结束,baz的生命周期为整个闭包调用
因此baz的声明周期没有'static长, 所以报错:
error[E0597]: `baz` does not live long enough
--> test.rs:12:29
|
12 | map.insert("sign", &baz);
| ^^^ borrowed value does not live long enough
13 | Some(())
14 | });
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
而当我们保留了let语句是, 相当于把mapmove到了闭包中, 并且在let语句的时候重新推断了生命周期条件:
// let dist_map: BTreeMap(&'static str, &'a str) = moved_map;
let map = map;
而这种推断是合理的, 因为'static生命周期要比任何生命周期'a'要长('static: 'a);
接着, rust再推断出满足'a lifetime的最小lifetime 要比&baz的lifetime要长('a: 'baz), 所有生命周期参数得以满足, 于是通过了编译.