Rust 不合适的 lifetime 导致的行为异常

咱们先来观察以下 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>>) {}

Tags :