Rust中为何部分返回类型生命周期可省略,部分需显式标注?
Rust 生命周期省略规则差异的根本原因
所有差异本质上都是Rust生命周期省略规则的确定性要求:编译器只会按固定的语法规则自动补全生命周期,不会做任何“猜测”,只要存在歧义就直接抛出E0106错误,不存在灵活判断的空间。
先明确3条硬性省略规则
编译器做生命周期自动补全时,只看函数签名,完全不分析函数内部实现、也不检查返回结构体的字段绑定逻辑,仅做模式匹配:
- 规则1:每个引用类型的入参,自动分配一个独立的匿名生命周期
- 规则2:如果入参里只有1个输入生命周期,这个生命周期会自动赋值给所有需要生命周期的返回值位置
- 规则3:如果是带
&self/&mut self的方法,self的生命周期会自动赋值给所有需要生命周期的返回值位置
只有完全符合以上规则的场景,才能用'_占位符让编译器自动补全生命周期,否则必须显式标注。
为什么StatefulList::with_items可以合法省略
看它的函数签名:
fn with_items(items: &Vec<T>) -> StatefulList<'_, T>
这个签名完全符合规则2的要求:入参里只有1个引用类型(就是外层的&Vec<T>),只有1个输入生命周期。这里的T是结构体的泛型参数,和StatefulList自身的生命周期参数'a没有绑定关系——StatefulList只要求存的&Vec<T>的生命周期匹配'a,T内部的引用生命周期和'a无关。
编译器可以无歧义地把入参的唯一生命周期填到返回值StatefulList<'_, T>的占位符位置,所以省略完全合法。
为什么App::new省略生命周期会报错
报错的问题签名如下:
fn new(items: &Vec<(&str, &str, usize)>) -> App<'_>
这个签名不满足任何自动补全的条件:
- 它是关联函数不是方法,没有
self参数,规则3不生效 - 入参里的引用类型不止1个:外层
&Vec是1个引用,元组里的两个&str各是1个独立引用,总共3个输入生命周期
按照规则1,编译器会给这3个引用各分配一个独立的匿名生命周期,这时候返回值App<'_>需要一个确定的生命周期,编译器没有规则能判断该选3个里的哪一个——毕竟App的生命周期'a同时绑定了内部的StatefulList和两个&str,编译器不会猜你的意图,直接报错。
两个可正常编译的版本,本质都是帮编译器消除了歧义:
- 版本1:给所有引用都标同一个
'a,明确所有引用生命周期统一,返回值用'a - 版本2:只给外层
&Vec标'a,返回值用'a,编译器会自动校验内部两个&str的生命周期长于'a,满足App的约束,同样没有歧义
容易踩的误区
'_不是“随便什么生命周期”,它只是*“请编译器按省略规则补全”*的占位符,只要不满足省略规则,写'_一样报错- 生命周期省略是纯语法层面的规则匹配,编译器不会深入看你函数里到底返回了哪个引用,只要签名模式不匹配规则,一律要求显式标注
内容的提问来源于stack exchange,提问作者cowboybebop
相关产品推荐
相关产品推荐

