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!");
}
Playground
Error:
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>>`
The poll method The core method of future, poll , is used to attempt to generate the value of a Future . This method does not block but is allowed to inform the caller that the value is not ready yet.
A future represents an asynchronous computation obtained by use of async . A future is a value that might not have finished computing yet. This kind of “asynchronous value” makes it possible for a thread to continue doing useful work while it waits for the value to become available.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With