生命周期标记实现失败:报错‘lifetime does not live long enough’
Rust生命周期错误排查:
arena生命周期不足问题 我参考Rust Playground示例实现生命周期标记时遇到了问题——只有当代码中存在v.pup(...)语句时,才会触发以下编译器错误:
error[E0597]: `arena` does not live long enough --> src/lib.rs:65:5 | 64 | let arena = goop::Parent; | ----- binding `arena` declared here 65 | arena.scope(|child, context| { | -^^^^ | | | _____borrowed value does not live long enough | | 66 | | let mut v = Foo::new(child); 67 | | v.pup(context); 68 | | }); | |______- argument requires that `arena` is borrowed for `'static` 69 | } | - `arena` dropped here while still borrowed
以下是精简后的代码:
#![no_std] mod goop { use core::marker::PhantomData; // Cell<T> 在 T 上是不变的;因此 Cell<&'id _> 让 `'id` 成为不变生命周期。 // 这意味着类型推断引擎不能通过缩小或扩大 `'id` 来解决借用检查问题。 type Id<'id> = PhantomData<::core::cell::Cell<&'id mut ()>>; #[derive(Clone, Copy)] pub struct Child<'id> { _id: Id<'id>, } pub struct Parent; #[derive(Clone, Copy)] pub struct Context<'id, 'p> { _id: Id<'id>, parent: &'p Parent, } impl Parent { pub fn scope<'p, F>(&'p self, _f: F) where F: for<'id> FnOnce(Child<'id>, Context<'id, 'p>) {} fn internal_something(&self) {} } pub trait Gator<C> { fn gate(&self, c: C); } impl<'p, 'id> Gator<Context<'p, 'id>> for Child<'id> { fn gate(&self, c: Context<'p, 'id>) { c.parent.internal_something(); } } } use core::marker::PhantomData; struct Foo<C, G> { _c: PhantomData<C>, g: G, } impl<C, G: goop::Gator<C>> Foo<C, G> { fn new(g: G) -> Self { Self { _c: PhantomData, g, } } fn pup(&mut self, c: C) { self.g.gate(c) } } fn _check() { let arena = goop::Parent; arena.scope(|child, context| { let mut v = Foo::new(child); v.pup(context); }); }
问题根源
这个错误的核心是生命周期参数顺序不匹配导致的约束冲突:
Parent::scope的闭包要求接收Context<'id, 'p>('id是闭包内的临时生命周期,'p是arena的生命周期)。- 但
Child<'id>实现的Gatortrait关联的是Context<'p, 'id>——生命周期参数顺序完全反过来了。 - 当调用
v.pup(context)时,编译器试图匹配Foo的C类型与传入的Context,但参数顺序的错误让推断引擎无法正确绑定生命周期,最终错误地要求arena必须拥有'static生命周期才能满足冲突的约束。
修复方案
只需要修正Gator trait的实现,让Context的生命周期参数顺序与闭包传入的一致:
修改goop模块中的impl块:
// 调整泛型参数顺序,让Context的参数对应闭包中的<'id, 'p> impl<'id, 'p> Gator<Context<'id, 'p>> for Child<'id> { fn gate(&self, c: Context<'id, 'p>) { c.parent.internal_something(); } }
这样调整后,编译器就能正确推断生命周期关系,错误会被消除。
内容的提问来源于stack exchange,提问作者PitaJ
相关产品推荐
相关产品推荐

