【发布时间】:2020-12-10 12:13:03
【问题描述】:
当我发现这是一个终身问题时,我正在制作执行器/反应器。它与 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 中有一个技巧可以使这项工作发挥作用?
【问题讨论】:
-
我认为你不能只提取
start_with_runtime到 main 吗?因为这应该可以工作,没有任何明确的生命周期。 -
start_with_runtime应该在 crate 中并由应用程序使用(例如,对应用程序隐藏运行时构造)。这是应用程序可以let rt = Runtime::new(); rt.run(|rt| my_async_fn(rt));的一种备份计划 -
异步函数的返回类型确实是captures all argument lifetimes。它必须这样做,因为每当异步函数等待其他未来时,参数都需要存储在 Future 中。
-
接收像
Rc<Runtime>这样的共享指针而不是对运行时的引用对你有用吗? -
我想
Rc<>会起作用,但这是开销,对我来说不喜欢权利所有权模型。