外观
雷区 4:E0106 函数忘了说借条的保质期
报错码:E0106
症状
rust
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let a = String::from("aaa");
let b = String::from("bb");
println!("{}", longest(&a, &b));
}编译输出
text
error[E0106]: missing lifetime specifier
--> src/main.rs:1:33
|
1 | fn longest(x: &str, y: &str) -> &str {
| ---- ---- ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
help: consider introducing a named lifetime parameter
|
1 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
| ++++ ++ ++ ++诊断
第 9 章的老朋友,但真实项目里,它的出现姿势往往更隐蔽:
- 函数返回一个引用,但编译器不知道它借自哪个参数
- 两个参数都是
&str,返回值也是&str——借自x还是y?编译器猜不出来,拒绝编译
注意:不是所有返回引用的函数都要写 'a!Rust 有生命周期省略(第 9 章提过):如果只有一个输入引用,编译器自己能推断:
rust
fn first_word(s: &str) -> &str { ... } // 一个输入引用 → 不用写 'a,编译器自动补
fn longest(x: &str, y: &str) -> &str { ... } // 两个输入引用 → 编译器懵了,要你写"输出引用借自哪个输入"有歧义时,必须手动标注。 这正是 E0106 想告诉你的。
解药
解药一:标注生命周期——告诉编译器"返回的借条,和两个输入共享保质期":
rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let a = String::from("aaa");
let b = String::from("bb");
println!("{}", longest(&a, &b));
}<'a> 声明"有一个保质期 a",三个 &'a str 是"三个引用共享这个保质期"——返回的借条,活不过两个输入里先过期的那个(第 9 章原话)。
解药二:让编译器自己猜——只有一个输入引用,或干脆不返回引用:
rust
fn first_word(s: &str) -> &str { // 一个输入,省略生效,不用写
s.split_whitespace().next().unwrap_or("")
}
fn longest_owned(x: &str, y: &str) -> String { // 返回拥有值,没有借条,不用写
if x.len() > y.len() {
x.to_string()
} else {
y.to_string()
}
}预防
- 看到 E0106,先数输入引用:一个 → 编译器自己会;两个以上 + 返回引用 → 要写
'a 'a的名字无所谓('a/'b/'life都行),关键是连接:哪些引用共享保质期,用同一个字母- 能省略就省略:真实项目 90% 的引用函数不用手动写生命周期(省略规则够用);写
'a的场景,通常是"返回借自哪个参数说不清"或"多个引用要建立关系" - 最省心的路还是那条:返回拥有所有权的值(
String/Vec),借条问题直接消失