DEV Community

x1957
x1957

Posted on

Rust existential type

最近在封装一点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

Top comments (0)