loading...

Rust existential type

x1957 profile image x1957 ・1 min read

最近在封装一点lib,本来想在trait里面定义async fn的,但是目前来说是不允许的.Async Methods I: generic associated types,只能想其他办法咯,那我们就再调用async fn返回个future吧,也一样的。

然后问题又来了,本来想是return 一个 impl Future,但是。。。trait里面又不允许,sad!

Async Methods I: generic associated types这里也解释了为什么直接associated types不行。

原因就是async返回的Future是个闭包,把所有东西的lifetime都丢进去了,如果我们要写associated types需要这样:

trait Foo {
    type _Future<'a>: Future<Output = i32> + 'a;
    fn foo_method<'a>(&'a self) -> Self::_Future<'a>;
}

但是呢。。。问题又来了,目前associated types不支持lifetime参数,这个东西叫generic associated types

不过还好,我们还有existential type,参考RFC

#![feature(async_await, existential_type)]

use futures::compat::Future01CompatExt;
use futures::compat::Stream01CompatExt;
use futures::future::{FutureExt, TryFutureExt};
use futures::stream::{StreamExt, TryStreamExt};
use futures::Future;
use reqwest::r#async::{Client, ClientBuilder, Decoder};
use std::io::{self, Write};

trait Fuck {
    type AsyncResult: Future<Output=()>;
    fn download(&self) -> Self::AsyncResult;
}

struct Down;

impl Down {
    pub fn new() -> Self{
        Down{}
    }
}

impl Fuck for Down {
    existential type AsyncResult: Future<Output=()>;
    fn download(&self) -> Self::AsyncResult {
        download()
    }
}

async fn download() {
    let client = ClientBuilder::new().build().unwrap();
    let res = client
        .get("https://dev.to/x1957/rust-async-await-2l4c")
        .send()
        .compat()
        .await;
    let mut body = res.unwrap().into_body().compat();
      while let Some(next) = body.next().await {
        let chunk = next.unwrap();
        io::stdout().write_all(&chunk).unwrap();
    }
    println!("\nDone");
}

fn call<T: Fuck>(x: T)->T::AsyncResult {
    x.download()
}

fn main() {
    // let fut = download().unit_error().boxed().compat();
    let fut = call(Down::new()).unit_error().boxed().compat();
    tokio::run(fut);
}

我们定义了Fuck这个trait里面有个associated type AsyncResult,在我们impl这个trait的使用通过existential type来指出AsyncResult是impl Future的即可。

现在使用的时候需要打开feature existential_type

Posted on by:

Discussion

markdown guide