为什么我会得到终身不匹配?

Why am I getting a lifetime mismatch?

以下函数编译没有问题:

async fn filter_con<T, O, F>(arr: Vec<T>, predicate: F) -> Vec<T>
where
    O: Future<Output = bool>,
    F: for Fn(&T) -> O,
{
    join_all(arr.into_iter().map(|it| async {
        if predicate(&it).await {
            Some(it)
        } else {
            None
        }
    }))
    .await
    .into_iter()
    .filter_map(|p| p)
    .collect::<Vec<_>>()
}

但是我找不到正确调用它的方法:

let items_filtered = filter_con(items, filter).await;

错误:

error[E0308]: mismatched types
   --> src/lifecycle/querier.rs:101:30
    |
101 |         let items_filtered = filter_con(items_response, filter).await;
    |                              ^^^^^^^^^^ lifetime mismatch
    |
    = note: expected associated type `<for<'_> fn(&PairInfo) -> impl futures::Future<Output = bool> {lifecycle::querier::filter} as FnOnce<(&PairInfo,)>>::Output`
               found associated type `<for<'_> fn(&PairInfo) -> impl futures::Future<Output = bool> {lifecycle::querier::filter} as FnOnce<(&PairInfo,)>>::Output`
    = note: the required lifetime does not necessarily outlive the empty lifetime
note: the lifetime requirement is introduced here
   --> src/lifecycle/querier.rs:246:26
    |
246 |     F: for<'a> Fn(&T) -> O,
    |                          ^

为什么会这样?


Full playground here

您遇到的问题与 here

中的问题基本相同

为了更容易理解,我将 rewrite/desugar 您的一些代码。让我们从谓词开始:

async fn filter(x: &Test) -> bool{
    x.0 >= 50
}

在功能上等同于:

fn filter(x: &Test) -> impl Future<Output=bool> + '_{
    async {
        x.0 >= 50
    }
}

现在应该很明显,返回的Future的生命周期不是'static,但实际上它取决于参数的生命周期x: &Test

这应该使错误更容易理解 - 你的谓词正在返回某个生命周期的未来,这是 not 在通用类型定义中的任何地方提到的 - 你可以看到你没有当你既没有定义 O,也没有定义 F:

时,请提及它
where
    O: Future<Output = bool>,
    F: for Fn(&T) -> O,

问题是,目前该语言没有提供任何方式来说明 O 的生命周期取决于 F 的生命周期。我知道的唯一简单的解决方案是使用逃生舱口 - box 未来,这将允许您在 FO 中使用相同的生命周期。缺点是,F 将被分配到堆中:

use futures::future::{join_all, Future};
use futures::future::BoxFuture;
use futures::FutureExt;


#[derive(Debug)]
struct Test(usize);

#[tokio::main]
async fn main() {
    let items = vec![Test(10), Test(100), Test(1000)];
    let items_filtered = filter_con(items, filter).await;

    println!("{:?}", items_filtered); // should print [100, 1000]
}

fn filter(x: &Test) -> BoxFuture<'_, bool>{
    async {
        x.0 >= 50
    }.boxed()
}

async fn filter_con<T, F>(arr: Vec<T>, predicate: F) -> Vec<T>
where
    F: for<'a> Fn(&'a T) -> BoxFuture<'a, bool>,
{
    join_all(arr.into_iter().map(|it| async{
        if predicate(&it).await {
            Some(it)
        } else {
            None
        }
    }))
    .await
    .into_iter()
    .filter_map(|p| p)
    .collect::<Vec<_>>()
}

这里是link到Rust Plauground