对实现Future的泛型类型的生命周期约束

时间:2020-06-28 03:12:24

标签: rust async-await future traits wasm-bindgen

我正在尝试编写一个特征,该特征将一个异步函数(fetch_dep_proxy())的句柄包装起来。有问题的异步函数在内部调用JavaScript(使用适当的wasm_bindgen属性)。

use async_trait::async_trait;
use std::future::Future;

async fn fetch_dep_proxy(name: &str) -> Option<String> {
    Some("test".to_owned()) // in practice, this would call into JavaScript and convert the returned JsFuture into a Option<String>
}

#[async_trait(?Send)]
pub trait Fetcher<T> {
    async fn fetch(&self, name: &str) -> Result<T, String>;
}

struct FetchedValue {
    pub val: String,
}

struct SourceFetcher<F> {
    pub raw_fetch: F,
}
#[async_trait(?Send)]
impl<
        Fut: Future<Output = Option<String>>,
        F: Fn(&str) -> Fut,
    > Fetcher<FetchedValue> for SourceFetcher<F>
{
    async fn fetch(
        &self,
        name: &str,
    ) -> Result<FetchedValue, String> {
        let resp = (self.raw_fetch)(name).await;
        unimplemented!(); // todo: convert it to FetchedValue...
    }
}

fn main() {
    let sf = SourceFetcher{raw_fetch: fetch_dep_proxy};
}

请注意,返回的未来不是Send,因为从JavaScript返回的JsFuture不是Send

但是,编译器抱怨以下错误:

error[E0309]: the parameter type `Fut` may not live long enough
  --> src/main.rs:29:39
   |
22 |           Fut: Future<Output = Option<String>>,
   |           ---- help: consider adding an explicit lifetime bound...: `Fut: 'async_trait +`
...
29 |       ) -> Result<FetchedValue, String> {
   |  _______________________________________^
30 | |         unimplemented!();
31 | |     }
   | |_____^
   |
note: ...so that the type `impl std::future::Future` will meet its required lifetime bounds
  --> src/main.rs:29:39
   |
29 |       ) -> Result<FetchedValue, String> {
   |  _______________________________________^
30 | |         unimplemented!();
31 | |     }
   | |_____^

Playground link

特别是,这表明我需要在Fut上有明确的生命周期约束。大概生存期'async_trait可能是async_trait宏的一部分,但是我认为我对生存期界限的理解更加根本。我似乎无法理解类型参数的生命周期界限。

Fut通用参数的显式生存期意味着什么?毕竟,fetch_dep_proxy()是一个非常普通的异步函数(不是闭包),因此应转换为(name: &str) -> impl Future<Option<String>>。特别是,Future是按值返回的,因此(self.raw_fetch)(name)是按值返回的,因此此impl Future<Option<String>>的生存期将仅取决于它在fetch()中的使用方式。但是很明显,这不是正在发生的事情,对于Future来说,需要终身限制。生命周期限制在这里实际上意味着什么?如何解决此问题?

0 个答案:

没有答案
相关问题