Rust中用Self替代Foo实例化结构体为何触发生命周期错误?
Rust中Self与结构体名的等价性差异
先看这段可正常编译运行的代码:
#[derive(Debug)] struct Foo<'a> { data: Vec<&'a str>, } impl Foo<'_> { fn bar_func(arg1: &str) { let f = Foo { data: arg1.split_whitespace().collect() }; println!("{:?}", f.data); } } fn main() { Foo::bar_func(&"hey split me!"); }
但如果把实例化语句里的Foo替换成Self:
fn bar_func(arg1: &str) { let f = Self { data: arg1.split_whitespace().collect() }; println!("{:?}", f.data); }
就会触发如下生命周期错误:
error: lifetime may not live long enough --> src/main.rs:9:31 | 6 | impl Foo<'_> { | -- lifetime `'2` appears in the `impl`'s self type 7 | 8 | fn bar_func(arg1: &str) { | - let's call the lifetime of this reference `'1` 9 | let f = Self { data : arg1.split_whitespace().collect() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | = note: requirement occurs because of the type `SplitWhitespace<'_>`, which makes the generic argument `'_` invariant = note: the struct `SplitWhitespace<'a>` is invariant over the parameter `'a`
核心结论:Self与结构体名并非完全等价
两者的差异体现在带生命周期/泛型参数的impl块中的绑定逻辑:
- 直接使用结构体名
Foo时,编译器会为当前实例化操作独立推导最合适的生命周期参数,这里会自动把arg1的生命周期绑定给Foo的泛型生命周期,完全匹配data字段的需求,因此编译通过。 - 而在
impl Foo<'_>块中,Self代表的是绑定了该impl块声明的匿名生命周期(即错误信息中的'2)的Foo<'2>。此时用Self实例化时,要求data字段的生命周期必须与'2一致,但函数参数arg1的生命周期'1和'2之间没有任何约束关系,编译器无法保证'1的存活时间长于'2,因此抛出生命周期不匹配的错误。
简单来说,impl Foo<'_>里的Self是“绑定了固定生命周期的Foo”,而直接写Foo是“让编译器临时推导生命周期的Foo”,两者的生命周期绑定逻辑完全不同。
内容的提问来源于stack exchange,提问作者palako
相关产品推荐
相关产品推荐

