本页目录
生命周期
生命周期(
'a)不是运行时的值——它是编译期对引用有效作用域的约束。从 elision 规则(编译器自动推导)到显式标注(struct/variance/HRTB),生命周期标注本质上是在告诉借用检查器"这几个引用之间谁活得比谁长"。
Lifetime 是编译期概念
Lifetime 参数('a)不是运行时的值——它们只是编译期的约束:这个引用的有效作用域不能比 'a 更长。编译器在 MIR 上用 region inference 推导最小 lifetime。
Lifetime Elision
大多数函数不需要显式标注 lifetime——编译器根据 3 条规则自动推导:
- 每个不标注 lifetime 的引用参数被分配独立的 lifetime(
fn foo<'a, 'b>(x: &'a T, y: &'b U)) - 如果只有一个 input lifetime,它被赋给所有 output lifetime(
fn foo<'a>(x: &'a T) -> &'a U) - 如果多个 input lifetime 中有
&self或&mut self,self的 lifetime 赋给所有 output
规则 2 是最常见的:单个引用参数 → 返回的引用默认借用该参数。规则 3 是 why method chaining works:self 的 borrow 传递到返回值。
Struct 中的 Lifetime
当 struct 包含引用时,必须显式标注 lifetime:
编译器的保证:Excerpt<'a> 实例不能活得比被引用的 &'a str 更久。
'static
'static 是唯一有"特殊"含义的 lifetime——它表示引用的数据存活于整个程序生命周期。来源:
- 字符串字面量:
"hello"的类型是&'static str——编译期嵌入二进制,始终有效 Box::leak(Box::new(T))可以制造&'static mut Tstatic变量和const引用
Variance
Rust 的 lifetime 有 subtyping variance。理解它的关键规则:
'long: 'short(即'long活得比'short长,所以'long满足'short的约束)&'a T: covariant in'a(如果'long: 'short,则&'long T可用于&'short T)&'a mut T: invariant in'a(不能缩短可变引用的 lifetime——否则可能违反 aliasing XOR mutation)
let mut x: &'static str = "hello";
// 如果这能编译, x 指向 y 的数据 → y 被 drop → 悬垂指针
HRTB (Higher-Ranked Trait Bounds)
当 closure 参数有 lifetime 但不需要显式声明时:
// "f 对于**任意** lifetime 'a 都满足 Fn(&'a str) -> &'a str"
// 不需要 caller 处指定 'a — 编译器自动量化
PhantomData
当 struct 有 lifetime 但没有直接存储引用——用 PhantomData 标记所有权/借用关系:
use PhantomData;
参考
- Rust Book: Chapter 10.3 — Validating References with Lifetimes
- Rust Reference: lifetime elision, variance
- RFC: RFC 2094 (NLL), RFC 387 (Higher-Ranked Trait Bounds)
Keywords: lifetime, elision, 'static, variance, covariant, invariant, HRTB, PhantomData, region inference