无法访问含生命周期的具体结构体时如何指定HRTB?
问题:带生命周期的回调参数泛化时类型不匹配
以下是尝试泛化带生命周期回调参数机制的简化代码:
struct ThingWithLifetime<'a> { borrowed_thing: &'a i32, } fn process<Arg, Func>(f: Func) where Func: FnMut(Arg) + 'static, // 预期需要类似`for<'a> FnMut(Arg<'a>)`的写法 Arg: Argument<Func = Box<dyn FnMut(Arg)>>, { <Arg as Argument>::process_boxed(Box::new(f)) } trait Argument { type Func; fn process_boxed(func: Self::Func); } impl Argument for ThingWithLifetime<'_> { type Func = Box<dyn for<'b> FnMut(ThingWithLifetime<'b>)>; fn process_boxed(func: Self::Func) {} } fn main() { let cb = |_msg: ThingWithLifetime<'_>| {}; process(cb); }
运行后触发类型不匹配错误:
25 | process(|_msg: ThingWithLifetime<'_>| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other = note: expected struct `Box<(dyn for<'b> FnMut(ThingWithLifetime<'b>) + 'static)>` found struct `Box<(dyn FnMut(ThingWithLifetime<'_>) + 'static)>`
核心需求是调整process()函数,使其兼容给定的Argument trait及其实现,让Func不绑定到参数的特定生命周期。
解决方案
问题根源在于原process的泛型约束无法将绑定到具体生命周期的闭包,转换为多态生命周期(for<'b>)的trait对象。需要重新设计trait关联类型和函数约束,匹配多态生命周期的要求。
方案一:通过Into trait实现类型转换
struct ThingWithLifetime<'a> { borrowed_thing: &'a i32, } fn process<Arg, Func>(f: Func) where Arg: Argument, Func: 'static + Into<Arg::Func>, { <Arg as Argument>::process_boxed(f.into()) } trait Argument { type Func; fn process_boxed(func: Self::Func); } impl Argument for ThingWithLifetime<'_> { type Func = Box<dyn for<'b> FnMut(ThingWithLifetime<'b>)>; fn process_boxed(func: Self::Func) {} } // 实现从多态闭包到目标trait对象的转换 impl<F> Into<Box<dyn for<'b> FnMut(ThingWithLifetime<'b>)>> for F where F: 'static + for<'b> FnMut(ThingWithLifetime<'b>), { fn into(self) -> Box<dyn for<'b> FnMut(ThingWithLifetime<'b>)> { Box::new(self) } } fn main() { let cb = |_msg: ThingWithLifetime<'_>| {}; process::<ThingWithLifetime<'_>, _>(cb); }
关键调整:
- 重构
process约束:用Into<Arg::Func>替代原有的FnMut(Arg),让Argumenttrait定义所需的函数类型,避免硬编码约束。 - 添加
Into实现:针对满足多态生命周期的闭包,实现到目标trait对象的转换逻辑。 - 显式指定
Arg类型:调用process时明确传入ThingWithLifetime<'_>,帮助编译器完成类型推断。
方案二:扩展Argument trait关联类型
struct ThingWithLifetime<'a> { borrowed_thing: &'a i32, } fn process<Arg, Func>(f: Func) where Arg: Argument<Func = Box<dyn for<'b> FnMut(Arg<'b>)>>, Func: 'static + for<'b> FnMut(Arg<'b>), { <Arg as Argument>::process_boxed(Box::new(f)) } trait Argument { type Func; // 添加关联类型表示带生命周期的参数本身 type Arg<'b>; fn process_boxed(func: Self::Func); } impl<'a> Argument for ThingWithLifetime<'a> { type Func = Box<dyn for<'b> FnMut(ThingWithLifetime<'b>)>; type Arg<'b> = ThingWithLifetime<'b>; fn process_boxed(func: Self::Func) {} } fn main() { let cb = |_msg: ThingWithLifetime<'_>| {}; process(cb); }
关键调整:
- 给
Argument添加Arg<'b>关联类型,明确表示参数的生命周期多态性。 - 让
process的约束直接匹配Argument::Func的多态生命周期要求,无需额外转换逻辑。
内容的提问来源于stack exchange,提问作者nnnmmm
相关产品推荐
相关产品推荐

