如何等待盒装未来的结果?
How can one await a result of a boxed future?
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!");
}
错误:
error[E0277]: the trait bound `dyn core::future::future::Future<Output = bool>: std::marker::Unpin` is not satisfied
--> src/main.rs:8:24
|
8 | let result: bool = test().await;
| ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn core::future::future::Future<Output = bool>`
|
= note: required because of the requirements on the impl of `core::future::future::Future` for `std::boxed::Box<dyn core::future::future::Future<Output = bool>>`
当谈到 Box
和 future
时,使用 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()
}
这个原因很有意思。 Pin
有一个 blanket implementation for Unpin
:
impl<P> Unpin for Pin<P> where
P: Unpin,
里面的Box<T>
是unconditionally Unpin
:
impl<T> Unpin for Box<T> where
T: ?Sized,
所以 Pin<Box<dyn Future>>
是未固定的 Future
。一切正常,但为什么 Box
本身没有?这是 Deref
阻碍的地方:
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
}
await
需要未固定的 Future
,而您使用 Box::new
创建的 Box<dyn Future>
确实包含 Future
。所以它被自动取消引用并且 Unpin
丢失,除非你用 Box<dyn Future + Unpin>
.
明确声明它
编辑:@ÖmerErden 关于 Box<dyn Future>
不起作用的原因是正确的。
impl<F> Future for Box<F>
where
F: Unpin + Future + ?Sized,
盒装期货仅在 Box
内的期货实施 Unpin
.
时实施 Future
特征
由于您的函数不保证 returned 未来实现 Unpin
,因此您的 return 值将被视为未实现 Future
。你不能 await
因为你的类型基本上不是 Future
.
来自@Stargateur 的解决方案,向签名添加显式类型边界,有效 (Playground):
fn test() -> Box<dyn Future<Output = Result<bool, ()>> + Unpin>
如果您使用的是 futures-rs,则有一个辅助类型 BoxFuture
。您可以使用 BoxedFuture
而无需明确说明 Unpin
:
use futures::future::BoxFuture;
fn test() -> BoxFuture<'static, Result<bool, ()>> {
Box::pin(async { Ok(true) })
}
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!");
}
错误:
error[E0277]: the trait bound `dyn core::future::future::Future<Output = bool>: std::marker::Unpin` is not satisfied
--> src/main.rs:8:24
|
8 | let result: bool = test().await;
| ^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn core::future::future::Future<Output = bool>`
|
= note: required because of the requirements on the impl of `core::future::future::Future` for `std::boxed::Box<dyn core::future::future::Future<Output = bool>>`
当谈到 Box
和 future
时,使用 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()
}
这个原因很有意思。 Pin
有一个 blanket implementation for Unpin
:
impl<P> Unpin for Pin<P> where
P: Unpin,
里面的Box<T>
是unconditionally Unpin
:
impl<T> Unpin for Box<T> where
T: ?Sized,
所以 Pin<Box<dyn Future>>
是未固定的 Future
。一切正常,但为什么 Box
本身没有?这是 Deref
阻碍的地方:
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
}
await
需要未固定的 Future
,而您使用 Box::new
创建的 Box<dyn Future>
确实包含 Future
。所以它被自动取消引用并且 Unpin
丢失,除非你用 Box<dyn Future + Unpin>
.
编辑:@ÖmerErden 关于 Box<dyn Future>
不起作用的原因是正确的。
impl<F> Future for Box<F>
where
F: Unpin + Future + ?Sized,
盒装期货仅在 Box
内的期货实施 Unpin
.
Future
特征
由于您的函数不保证 returned 未来实现 Unpin
,因此您的 return 值将被视为未实现 Future
。你不能 await
因为你的类型基本上不是 Future
.
来自@Stargateur 的解决方案,向签名添加显式类型边界,有效 (Playground):
fn test() -> Box<dyn Future<Output = Result<bool, ()>> + Unpin>
如果您使用的是 futures-rs,则有一个辅助类型 BoxFuture
。您可以使用 BoxedFuture
而无需明确说明 Unpin
:
use futures::future::BoxFuture;
fn test() -> BoxFuture<'static, Result<bool, ()>> {
Box::pin(async { Ok(true) })
}