症状
编译器是在提问而不是报 bug:error[E0106]: missing lifetime specifier 指向返回类型,提示“返回类型包含未知生命周期的借用值”。省略规则解释了为什么只有这个形状失败:单引用参数——输出自动获得该生命周期;&self 加其他引用——self 胜出;两个互不相干的引用配一个返回引用——没有任何规则适用,编译器要求你声明输出借用自哪个输入。它要的是契约,不是在指责你的逻辑。
诊断思路
先读 E0106 完整信息,编译器会点名返回类型与候选引用;再在心里过一遍三条省略规则(每个省略的参数各得一个生命周期;有 &self 时它赢得输出;否则多候选加返回引用必须手动标注);最后按真实数据流标注——参数与返回之间的实际借用关系才是答案。结构体持有引用时还要把生命周期参数穿透到 impl 与方法签名。
根因
Rust 生命周期省略只在无歧义形状下自动填充:单引用参数,或 &self 显然拥有结果的方法。两个以上候选引用喂给返回引用时,编译器无从得知结果借用自谁,于是要求显式标注以声明契约。
修复与验证
写出匹配真实数据流的显式生命周期:共享一个 ’a 表示结果可借用任一输入且活得与两者一样久;流不同就拆成两个不同生命周期;结构体场景把 <’src> 穿透到 impl。设计逃生门:不存在真实借用关系时返回拥有类型(String/Vec),问题整个消失。验证时标注后的签名编译通过,并写两个调用方分别行使预期的关系(短参数与长参数两种生命周期形态)都按设计通过类型检查。切忌“先抄一个能编译的标注”——过约束的 API 会堵死合法调用方,标注实际的数据流而不是第一个让编译器闭嘴的东西。
代码示例
error[E0106]: missing lifetime specifier
--> src/lib.rs:3:33
|
3 | fn longest(a: &str, b: &str) -> &str {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with
an unknown lifetime
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() >= b.len() { a } else { b }
}
fn wrap<'a, 'b>(outer: &'a str, inner: &'b str) -> String {
// owned return: no borrow relationship, no annotation pressure
format!("{}{}", outer, inner)
}
struct Parser<'src> { source: &'src str }
impl<'src> Parser<'src> {
fn token(&self) -> &'src str { /* elided &self: correct by rule 2 */ }
}