Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error[E0698]: type inside async object must be known in this context #2

Closed
kpp opened this issue Jul 23, 2019 · 3 comments · Fixed by #4
Closed

error[E0698]: type inside async object must be known in this context #2

kpp opened this issue Jul 23, 2019 · 3 comments · Fixed by #4
Labels
bug Something isn't working

Comments

@kpp
Copy link

kpp commented Jul 23, 2019

This code works:

impl<T: ?Sized> FutureExt for T where T: Future {}

#[async_trait]
pub trait FutureExt: Future {
    async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
        where <Self as Future>::Output: Future + Send,
              Self: Sized,
    {
        let nested_future = self.await;
        nested_future.await
    }
}

However if I want to reduce the number of angle brackets, this won't work:

    async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
        where Self::Output: Future + Send,
              Self: Sized,
    {...}


error:
   |
34 |         let nested_future = self.await;
   |             ^^^^^^^^^^^^^ cannot infer type
   |

But this will work:

    async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
        where Self: Future, // hence self is Future whereas we already have FutureExt: Future
              Self::Output: Future + Send,
              Self: Sized,
    {...}

Why? Is it a desired behavior? Also I'd like to reduce angle brackets in the result type, but I failed...

@dtolnay
Copy link
Owner

dtolnay commented Jul 24, 2019

Thanks for reporting this! This was hitting a surprising (to me) restriction in rustc's parser. The following code is accepted by rustc:

fn f<T>()
where
    T: std::str::FromStr,
    <T>::Err: Send,
{}

but swapping the where-predicates is not:

fn f<T>()
where
    <T>::Err: Send,
    T: std::str::FromStr,
{}
error: generic parameters on `where` clauses are reserved for future use
  --> src/main.rs:45:5
   |
45 |     <T>::Err: Send,
   |     ^^^ currently unsupported

error[E0412]: cannot find type `Err` in the crate root
  --> src/main.rs:45:10
   |
45 |     <T>::Err: Send,
   |          ^^^ not found in the crate root

I released 0.1.1 with a workaround, so your original code should now work.

#![feature(async_await)]

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

impl<T: ?Sized> FutureExt for T where T: Future {}

#[async_trait]
pub trait FutureExt: Future {
    async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
    where
        Self::Output: Future + Send,
        Self: Sized,
    {
        let nested_future = self.await;
        nested_future.await
    }
}

@dtolnay
Copy link
Owner

dtolnay commented Jul 24, 2019

You should also be able to remove a set of angle brackets from the return type.

-     async fn flatten(self) -> <<Self as Future>::Output as Future>::Output
+     async fn flatten(self) -> <Self::Output as Future>::Output

@kpp
Copy link
Author

kpp commented Jul 24, 2019

Nice!

async fn flatten(self) -> <Self::Output as Future>::Output

Very nice!

@dtolnay dtolnay added the bug Something isn't working label Oct 29, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants