Rust existential type
x1957
Posted on July 19, 2019
最近在封装一点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
💖 💪 🙅 🚩
x1957
Posted on July 19, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.