我有一个异步函数,我正在向它传递异步回调.回调函数将引用作为参数.

use core::future::Future;

async fn foo(bar: &u32) {}

async fn baz<F, Fut>(f: F)
where
    F: FnOnce(&u32) -> Fut,
    Fut: Future<Output = ()>,
{
    let test: u32 = 42;
    f(&test).await;
}

#[tokio::main]
async fn main() {
    baz(foo).await;
}

如果我try 构建这个(playground),我会遇到以下错误:

error[E0308]: mismatched types
  --> src/main.rs:16:5
   |
16 |     baz(foo).await;
   |     ^^^ lifetime mismatch
   |
   = note: expected associated type `<for<'_> fn(&u32) -> impl Future<Output = ()> {foo} as FnOnce<(&u32,)>>::Output`
              found associated type `<for<'_> fn(&u32) -> impl Future<Output = ()> {foo} as FnOnce<(&u32,)>>::Output`
   = note: the required lifetime does not necessarily outlive the empty lifetime
note: the lifetime requirement is introduced here
  --> src/main.rs:7:24
   |
7  |     F: FnOnce(&u32) -> Fut,
   |                        ^^^

我知道它对推荐人的生命周期不满意.然而,我不明白为什么.

  • 我们borrow "测试"
  • 我们执行回调f(即"foo")
  • 在f完成之前,baz无法退出

所以,看起来借来的东西不可能比宣布测试的地方更长寿.

我错过了什么?

推荐答案

future 以foo()has a hidden lifetime的速度回归.脱go 糖衣的签名如下:

fn foo<'a>(bar: &'a u32) -> impl Future<Output = ()> + 'a {
    async move {}
}

这样做的目的是使该函数可以在.await个点上保持bar.遗憾的是,这意味着函数不满足baz()的界限.由于生命周期是隐藏的,所以错误被模糊化了,但这就是编译器试图告诉您的:界限应该是where F: for<'a> FnOnce(&'a u32) -> impl Future<Output = ()> + 'a,但不能用当前的Rust来表示.

有关更多和潜在的解决方案,请参见示例:

Rust相关问答推荐

通用池类型xsx

如何在rust中有条件地分配变量?

如何在原始字符串中转义";#和#";

为什么std repeat trait绑定在impl块和关联函数之间?

为什么铁 rust S的默认排序功能比我对小数组的 Select 排序稍微慢一些?

`Pin`有没有不涉及不安全代码的目的?

当发送方分配给静态时,Tokio MPSC关闭通道

解析程序无法在Cargo 发布中 Select 依赖版本

在 Rust 中,在第一个空格上分割字符串一次

如何以与平台无关的方式将OsString转换为utf-8编码的字符串?

在 Rust 中忽略 None 值的正确样式

`tokio::pin` 如何改变变量的类型?

str 和 String 的 Rust 生命周期

Rust 中 Mutex<> 的深拷贝?

为什么可以在迭代器引用上调用 into_iter?

仅在运行测试时生成调试输出

为什么具有 Vec 变体的枚举没有内存开销?

当我在 struct 中存储异步函数时,为什么它需要生命周期

为什么这个值在上次使用后没有下降?

为什么这里需要类型注解?