async_executor::LocalExecutor
的成员,该类型本身是针对生命周期'a
泛型的:pub struct LocalExecutor<'a> {
inner: ......<Executor<'a>>,
...
...
}
现在,我的结构体显然也必须是泛型的,涵盖了生命周期'a
,对于它本身来说意义不大——这个生命周期是async_executor::LocalExecutor
的一个细节。
#[cfg(all(test, not(target = "wasm32")))]
struct MockThing<'a> {
executor: async_executor::LocalExecutor<'a>,
}
我的结构体仅在构建单元测试时存在,我需要一个模拟的、单线程执行器来运行异步代码。问题在于:我的结构体的唯一使用者使用了
#[cfg(...)]
条件编译,在内部进行以下操作:
- 编译单元测试时使用我的模拟(而不是WebAssembly)
- 编译WebAssembly时使用一个真实的实现
- 否则使用另一个真实的实现。
实现2和3都不需要通用生命周期,但是由于模拟的那个(1)必须在' a上通用,所以现在我必须使我的整个代码库都通用一些生命周期,' a'!(并且使用PhantomData解决编译器抱怨'a'无意义的问题,大多数情况下确实如此。)
有没有办法以不引起这个问题的方式定义我的模拟结构?如果我可以在成员定义中使用'_',那将非常方便,比如...
#[cfg(test)]
struct MockThing {
executor: async_executor::LocalExecutor<'_>,
}
...表示executor
的生命周期应该从MockThing
的生命周期中推导出来。(当然,这是不起作用的。)
我想我也可以为我的单元测试使用另一个带有环境执行器的async
运行时,并绕过这个问题,但这并不能帮助我理解发生了什么,在这里,以及通常情况下,如何将生命周期封装为实现细节,在具有一些成员泛型的结构中。
然而,有一些我不理解的问题:为什么Executor
(在LocalExecutor
内部)必须是泛型的,覆盖'a
-- 它不包含具有生命周期'a
的引用 -- 以及他们为什么使用PhantomData来确保它是泛型的,并且是一个不变的生命周期,'a
,甚至在这种情况下,什么是生命周期不变性。我已经在 nomicon和其他地方阅读了相关内容,但需要很多天的学习才能说我理解了生命周期变异,而我想做的只是“将其中之一放入我的struct
中”。
肯定有一些方法可以驯服生命周期传染并防止它污染整个代码库,只因为一个类型是泛型的生命周期?请求帮助!
'static
。正如你所指出的那样,它实际上并不是执行器内任何引用的生命周期。它更像是迭代器的“作用域”,允许向其中提交具有非静态生命周期的任务。既然看起来你不想这样做,那么简单地使用'static
应该可以解决你的问题。 - Sven Marnach'static
但只有'a
的未来。这确保了未来的寿命至少与执行器一样长。 - Sven Marnach