How can one await a result of a boxed future?

According to the implementation:

impl<F> Future for Box<F>
where
    F: Unpin + Future + ?Sized, 

Boxed futures only implement the Future trait when the future inside the Box implements Unpin.

Since your function doesn't guarantee that the returned future implements Unpin, your return value will be considered to not implement Future. You'll not able to await it because your type is basically not a Future.

The solution from @Stargateur, adding an explicit type boundary to the signature, works (Playground):

fn test() -> Box<dyn Future<Output = Result<bool, ()>> + Unpin> 

If you are using futures-rs, there is a helper type BoxFuture. You can use BoxedFuture without explicitly stating Unpin:

use futures::future::BoxFuture;

fn test() -> BoxFuture<'static, Result<bool, ()>> {
    Box::pin(async { Ok(true) })
}

Playground


When it comes to Box and future, it almost always make sense to use Box::pin instead of Box::new:

use std::pin::Pin;
use futures::{future, Future};

fn test() -> Pin<Box<dyn Future<Output = Result<bool, ()>>>> {
    Box::pin(future::ok(true))
}

async fn async_fn() -> bool {
    test().await.unwrap()
}

The reason is quite interesting. Pin has a blanket implementation for Unpin:

impl<P> Unpin for Pin<P> where
    P: Unpin,

And the Box<T> inside it is unconditionally Unpin:

impl<T> Unpin for Box<T> where
    T: ?Sized,

So a Pin<Box<dyn Future>> is a unpinned Future. Everything works out, but why Box itself doesn't? This is one place where Deref gets in the way:

impl<T: ?Sized> Deref for Box<T> {
    type Target = T;
}

await expects an unpinned Future, and the Box<dyn Future> you created with Box::new does contain a Future. So it is auto-dereferenced and the Unpin is lost unless you explicitly state it that way with Box<dyn Future + Unpin>.


Edit: @ÖmerErden is right about why Box<dyn Future> wouldn't work.