咱们先来观察以下 Rust 片段:
fn foo<'a>(_: Option<&'a mut Vec<&'a u8>>) {}
fn main() {
let mut v = Vec::new();
foo(Some(&mut v));
for _ in &v {}
}
这段代码编译时会让 borrow checker 触发一个错误:
Compiling ctr v0.1.0 (file:///Users/realityone/Desktop/ctr)
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> main.rs:6:15
|
5 | foo(Some(&mut v));
| - mutable borrow occurs here
6 | for _ in &v {}
| ^ immutable borrow occurs here
7 | }
| - mutable borrow ends here
error: aborting due to previous error
error: Could not compile `ctr`.
To learn more, run the command again with --verbose.
刚看到这个错咱还以为是在同一个 scope 里对同一个变量有两个不同类型的 borrow 导致的错误,因此咱下意识地将第 5 行用一对大括号引了起来:
fn foo<'a>(_: Option<&'a mut Vec<&'a u8>>) {}
fn main() {
let mut v = Vec::new();
{
foo(Some(&mut v));
}
for _ in &v {}
}
但是实际上还是会报一模一样的错。
怎么回事呢喵!
回过头看函数 foo 的定义
fn foo<'a>(_: Option<&'a mut Vec<&'a u8>>) {}
其中这里显式地制定了 input lifetime,所有 borrow 对象的 lifetime 都是 'a
。
此时如果咱们把这个 lifetime 去掉后就可以正常编译了。
重新翻阅了下 Rust Lifetime 的说明。发现在不显式指定 lifetime 的情况下,对于 input lifetime,每个 borrow 都会被分配一个独立的 lifetime,但是咱在这里显式地指定了两个 borrow 的 lifetime 全部为 'a
,因此 Rust 的 borrow checker 会把对 v
的两个 borrow 检查出现混乱。所以会爆出之前一个错。
事实上当你不显式写 lifetime 时,这个函数真正的定义是:
fn foo<'a, 'b>(_: Option<&'a mut Vec<&'b u8>>) {}