我在制作执行器/反应堆时发现了这个终身难题。它与异步/Future无关,并且可以在没有异步语法糖的情况下重现。
Translated:我在制作executor/reactor时发现了一个持久性的问题。 它与async/Future无关,可以在没有async语法糖的情况下重现。
use std::future::Future;
struct Runtime;
fn start_with_runtime<C, F>(closure: C)
where
C: for<'a> FnOnce(&'a Runtime) -> F,
F: Future
{
let rt = Runtime;
let _future = closure(&rt);
// block_on(future);
}
async fn async_main(_rt: &Runtime) {
// I can use _rt to do async stuff here
}
fn main() {
start_with_runtime(|rt| { async_main(rt) });
}
我想让 start_with_runtime()
运行未来并将异步运行时引用作为参数提供。
它无法编译:
error: lifetime may not live long enough
--> src/main.rs:17:31
|
17 | start_with_runtime(|rt| { async_main(rt) });
| --- ^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure is impl std::future::Future
| has type `&'1 Runtime`
我认为这个问题似乎是由于Rust如何推断闭包的生命周期而导致的:
https://github.com/rust-lang/rust/issues/58052:
fn main() {
let f = |x: &i32| x;
let i = &3;
let j = f(i);
}
也无法编译:
error: lifetime may not live long enough
--> src/main.rs:2:23
|
2 | let f = |x: &i32| x;
| - - ^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure is &'2 i32
| let's call the lifetime of this reference `'1`
看起来我的闭包签名被推断为|&'a Runtime| -> impl Future + 'b
,因此出现了生命周期错误。我觉得如果给出正确的闭包预期签名将会有帮助,但是我如何在start_with_runtime
中提供正确的签名呢?
fn start_with_runtime<C>(closure: C)
where
C: for<'a> FnOnce(&'a Runtime) -> (impl Future + 'a),
无法工作,因为在此处不允许使用impl Trait
。
fn start_with_runtime<C,F>(closure: C)
where
C: for<'a> FnOnce(&'a Runtime) -> F,
F: Future + 'a
由于'a
在HRTB表达式之外是未知的,因此不起作用。
如果我知道类型,它就能工作:
struct MyType<'a> {
_rt: &'a Runtime
}
fn start_with_runtime<C>(closure: C)
where
C: for<'a> FnOnce(&'a Runtime) -> MyType<'a>,
这有点悲伤,当你思考了所有的生命,但语言无法表达出来。也许在 Rust 中有什么诀窍可以解决这个问题吗?
这有点悲伤,当你思考了所有的生命,但语言无法表达出来。也许在 Rust 中有什么诀窍可以解决这个问题吗?
start_with_runtime
提取到主函数中吧?因为那样应该可以工作,而不需要任何明确的生命周期。 - L. Riemerstart_with_runtime
应该在一个 crate 中,并被应用程序使用(例如,将 Runtime 构造从应用程序中隐藏)。这是一种备份计划,应用程序可以let rt = Runtime::new(); rt.run(|rt| my_async_fn(rt));
。 - orcyRc<Runtime>
这样的共享指针,而不是对运行时的引用? - Sven MarnachRc<>
可以工作,但这会增加开销,并且对我来说不像是正确的所有权模型。 - orcy