Rust中非持有泛型参数的结构体为何要求生命周期绑定
为什么编译器要求A: 'a的生命周期绑定
这是Rust对结构体泛型参数的默认检查规则导致的:
只要某结构体的实例需要在生命周期'lt范围内有效(即实例存活时间≥'lt),编译器就会自动要求该结构体的所有泛型参数都满足T: 'lt的约束。这个规则和你是否使用PhantomData、PhantomData的具体类型无关,目的是避免泛型参数提前失效引发未定义行为。
你的两处代码都主动触发了这个检查:
- 第一个示例中你声明了
&'a S<'a, A>,这个引用的生命周期为'a,意味着被指向的S实例必须至少存活到'a结束,自然触发了A: 'a的约束检查。另外这个写法本身还有悬空引用问题:你引用的是语句内的临时S实例,临时实例生命周期只到当前语句结束,不可能达到输入参数的生命周期'a。 - 你补充的第二个示例中,直接在结构体定义上加了
where Self: 'a约束,相当于主动要求S<'a, A>类型本身的生命周期≥'a,直接触发了A: 'a的检查要求,所以编译器会报错。
你用到的PhantomData<*const A>本身不会额外添加生命周期约束,原始指针类型没有自带的生命周期检查规则,这里的报错完全来自于结构体泛型参数的默认约束。
能不能让A的生命周期和S的生命周期相互独立?
完全可以,根据你的使用场景选对应方案即可:
方案1:删除不必要的Self: 'a约束
如果你不需要强制要求S的实例生命周期和value的生命周期'a绑定,直接删掉结构体上的where Self: 'a声明即可,修改后的代码可以正常编译,且A和'a没有任何生命周期关联:
use std::marker::PhantomData; struct S<'a, A> { _phantom: PhantomData<*const A>, value: &'a i32, } fn foo<'a, A>(value: &'a i32) { let s: S<'a, A> = S { _phantom: PhantomData, value, }; } fn main() {}
方案2:更换PhantomData的标记类型
如果你确实需要保留Self: 'a的约束,只是不想让A和'a产生绑定,可以把PhantomData的类型换成函数指针类型。这类标记会告诉编译器,结构体只是用A做类型标记,并没有持有A类型的实例,不需要A满足任何生命周期约束:
use std::marker::PhantomData; struct S<'a, A> where Self: 'a { // 用fn() -> A类型的PhantomData,不会给A附加生命周期约束 _phantom: PhantomData<fn() -> A>, value: &'a i32, } fn foo<'a, A>(value: &'a i32) { let s: S<'a, A> = S { _phantom: PhantomData, value, }; } fn main() {}
如果你需要泛型参数A是不变的,可以改用PhantomData<fn(A) -> A>,同样不会附加生命周期约束。
内容的提问来源于stack exchange,提问作者winjii
相关产品推荐
相关产品推荐

