如何等待一个盒装未来的结果?

Tec*_*dar 12 future rust async-await

use futures::{future, Future};

fn test() -> Box<dyn Future<Output = bool>> {
    Box::new(future::ok::<bool>(true))
}

async fn async_fn() -> bool {
    let result: bool = test().await;
    return result;
}

fn main(){
    async_fn();
    println!("Hello!");
}
Run Code Online (Sandbox Code Playgroud)

操场

错误:

use futures::{future, Future};

fn test() -> Box<dyn Future<Output = bool>> {
    Box::new(future::ok::<bool>(true))
}

async fn async_fn() -> bool {
    let result: bool = test().await;
    return result;
}

fn main(){
    async_fn();
    println!("Hello!");
}
Run Code Online (Sandbox Code Playgroud)

Öme*_*den 12

根据实施

impl<F> Future for Box<F>
where
    F: Unpin + Future + ?Sized, 
Run Code Online (Sandbox Code Playgroud)

盒装期货只是实现了Future特质里面将来时Box工具Unpin

由于您的函数不保证返回的未来实现Unpin,因此您的返回值将被视为未实现Future。您将无法使用await它,因为您的类型基本上不是Future.

来自@Stargateur 的解决方案,为签名添加一个显式类型边界,有效(Playground):

fn test() -> Box<dyn Future<Output = Result<bool, ()>> + Unpin> 
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 futures-rs,则有一个辅助类型BoxFuture。您可以在BoxedFuture不明确说明的情况下使用Unpin

use futures::future::BoxFuture;

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

操场


edw*_*rdw 9

当谈到Boxand 时future,使用Box::pin代替几乎总是有意义的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()
}
Run Code Online (Sandbox Code Playgroud)

原因很有趣。Pin有一个全面的实现Unpin

impl<P> Unpin for Pin<P> where
    P: Unpin,
Run Code Online (Sandbox Code Playgroud)

Box<T>它的内部是无条件的Unpin

impl<T> Unpin for Box<T> where
    T: ?Sized,
Run Code Online (Sandbox Code Playgroud)

所以 aPin<Box<dyn Future>>是一个未固定的Future. 一切正常,但为什么Box它本身没有?这是一个Deref阻碍的地方:

impl<T: ?Sized> Deref for Box<T> {
    type Target = T;
}
Run Code Online (Sandbox Code Playgroud)

await期望一个 unpinned Future,并且Box<dyn Future>您创建的Box::new确实包含一个Future. 因此,它会自动取消引用,并且Unpin会丢失,除非您使用Box<dyn Future + Unpin>.


编辑:@ÖmerErden 关于为什么不起作用是正确的Box<dyn Future>