Idea of how to bound types that async methods return

I think the larger problem is naming the return type of async functions. With a regular function that returns an existential, we could do something like:

pub type FooIter = impl Iterator<Item = Foo>;
pub fn foo_iter() -> FooIter { ... }

With an async fn, I have no way of doing this. If I want to store tokio::TcpStream::connect futures, in a struct, I have to store a Pin<Box<dyn Future...>>, which feels unnecessary because I'm storing a single type. It is sometimes possible to make the type generic and push the creation of the futures to a standalone function.. but it's very unwieldy and doesn't work for all cases.

With min_type_alias_impl_trait, I am able to write something like:

#![feature(min_type_alias_impl_trait)]
use tokio::net::TcpStream;

type TcpStreamConnectFut = impl Future<Output = io::Result<TcpStream>>;

fn __tcp_stream_connect_defining_use() -> TcpStreamConnectFut  {
    TcpStream::connect("127.0.0.1:8080")
}

struct Foo {
    connection_futs: Vec<TcpStreamConnectFut>,
}

But it would be nice if I could write typeof(TcpStream::connect)::Output, or similar. With this syntax, we could also write:

trait Foo where typeof(connect)::Output: Send + Sync {
    async fn connect() -> io::Result<TcpStream>;
}

@nikomatsakis Also drew up a proposal for "inline futures" that would require this as well:

trait AsyncRead {
    fn read(&mut self, buf: &mut [u8]) -> Future::PollFn<
        typeof(<Self as AsyncRead>::poll_read)
    >;

    // 
    fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<usize, Error>>;
}

These problems were discussed in the past, but async/await was seemingly stabilized with some design holes. I think typeof is applicable to most of these:

1 Like