Actually, I don’t think it’s necessary to use the async || { ... }
syntax.
The reason is because await
does not work inside of closures (unless the closure is async
, of course). In other words, async/await is shallow, just like JavaScript async/await.
So in order to prevent the auto-await
, an ordinary function works just fine:
async fn foo() {
// bar() is not awaited
let x = || bar();
...
// x() is awaited
let y = x();
}
So that means we don’t need two traits! We can use impl Future
for both the auto and non-auto Futures! And async
fns can return impl Future
!
Any delaying of Futures is simply done with closures, which is already the standard way to delay synchronous code!
I was pretty ambivalent about implicit await
before, but this is really making me like it.
And of course the Deferred
struct can be changed to have a completely non-magical await
method which simply returns impl Future
:
enum DeferredState<A> where A: Future {
Ready(Option<A::Output>),
Pending(Pin<Box<A>>),
}
impl<A> Unpin for DeferredState<A> where A: Future {}
impl<A> Future for DeferredState<A> where A: Future {
type Output = A::Output;
fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
match *self {
DeferredState::Ready(value) => Poll::Ready(value.take().unwrap()),
DeferredState::Pending(future) => future.poll_unpin(lw),
}
}
}
pub struct Deferred<A> where A: Future {
state: DeferredState<A>,
}
impl<A> Deferred<A> where A: Future {
#[inline]
pub fn await(self) -> impl Future<Output = A::Output> {
self.state
}
}
And now it can be used like this:
async fn foo() {
let x = Force::new(|| bar());
...
let y = x.await();
}
This is really great! Quite a bit nicer than explicit await
.