gpt4 book ai didi

rust - 指定 Rust 闭包生命周期

转载 作者:行者123 更新时间:2023-12-03 11:23:26 27 4
gpt4 key购买 nike

我正在制作执行器/ react 器,同时发现这是一个终生的问题。它与 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()运行 future 并提供异步运行时引用作为参数。
它不编译:
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 语法表达,它是否适用于闭包类型推断。
让我们从第一个开始。你是对的,这不能仅用 where 来表达。条款。为了表达这个需要添加一个辅助特征

trait BorrowingFn<'a> {
type Fut: std::future::Future<Output = Something> + 'a;
fn call(self, arg: &'a Runtime) -> Self::Fut;
}
这允许我们需要写成的界限
    C: for<'a> BorrowingFn<'a>,
并为所有适用功能提供此特征的全面实现
impl<'a, Fu: 'a, F> BorrowingFn<'a> for F
where
F: FnOnce(&'a Runtime) -> Fu,
Fu: std::future::Future<Output = ()> + 'a,
{
type Fut = Fu;
fn call(self, rt: &'a Runtime) -> Fu {
self(rt)
}
}
( playground )
好的,所以它适用于异步函数,但它是否适用于需要类型推断的闭包?不幸的是,答案是否定的
error: implementation of `BorrowingFn` is not general enough
--> src/main.rs:33:5
|
5 | / trait BorrowingFn<'a> {
6 | | type Fut: std::future::Future<Output = ()> + 'a;
7 | | fn call(self, arg: &'a Runtime) -> Self::Fut;
8 | | }
| |_- trait `BorrowingFn` defined here
...
33 | start_with_runtime(|rt| async_main(rt)); // however, it does not work with closure type inference :-(
| ^^^^^^^^^^^^^^^^^^ implementation of `BorrowingFn` is not general enough
|
= note: `[closure@src/main.rs:33:24: 33:43]` must implement `BorrowingFn<'0>`, for any lifetime `'0`...
= note: ...but `[closure@src/main.rs:33:24: 33:43]` actually implements `BorrowingFn<'1>`, for some specific lifetime `'1`
这是在 rust-lang/rust#70263 中跟踪的.编译器还不够聪明,还没有注意到这个闭包需要一个更高等级的类型。
为了好玩,我尝试使用 -Z chalk 进行编译在 Nightly 上,但它还没有为此做好准备(内部编译器错误)。

关于rust - 指定 Rust 闭包生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63517250/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com