# Would implicit \`await\` really be a bad idea?

**URL:** <https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256>\
**Category:** Uncategorized\
**Created:** [January 21, 2019, 6:25pm UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256 "2019-01-21T18:25:16Z")\
**Posts on this page:** 9\
**Page:** 3

<div class="post-metadata">

**Author:** ![Pauan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pauan/32/3006_2.png) [@Pauan](https://internals.rust-lang.org/u/Pauan)\
**Post date:** [January 23, 2019, 6:33pm UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/41 "2019-01-23T18:33:22Z")

</div>

> [@vorner](#):
>
> To make them otherwise, a step back to a design table would have to be made, a lot of existing stuff thrown away.

To be clear, that already needs to be done: most things are based on Futures 0.1, but they will need to move to Futures 0.3 (which is a breaking change).

In addition, we're not talking about changing anything about Future, just the behavior of `async` (which is not stabilized, and isn't as widely used as Future is). So existing stuff does _not_ need to be thrown away.

---

<div class="post-metadata">

**Author:** ![Pauan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pauan/32/3006_2.png) [@Pauan](https://internals.rust-lang.org/u/Pauan)\
**Post date:** [January 23, 2019, 9:31pm UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/42 "2019-01-23T21:31:28Z")

</div>

Something like this should work (I did some light testing):

```rust
use std::pin::Pin;
use std::task::{Poll, LocalWaker};
use futures_util::future::FutureExt;

pub struct Force<A> {
    future: Option<Pin<Box<A>>>,
}

impl<A> Force<A> {
    #[inline]
    pub fn new(future: A) -> Self {
        Self {
            future: Some(Box::pin(future)),
        }
    }
}

impl<A> Unpin for Force<A> {}

impl<A> Future for Force<A> where A: Future {
    type Output = Deferred<A>;

    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        let mut future = self.future.take().unwrap();

        match future.poll_unpin(lw) {
            Poll::Ready(value) => Poll::Ready(Deferred {
                state: DeferredState::Ready(Some(value)),
            }),

            Poll::Pending => Poll::Ready(Deferred {
                state: DeferredState::Pending(future),
            }),
        }
    }
}

enum DeferredState<A> where A: Future {
    Ready(Option<A::Output>),
    Pending(Pin<Box<A>>),
}

pub struct Deferred<A> where A: Future {
    state: DeferredState<A>,
}

impl<A> Unpin for Deferred<A> where A: Future {}

impl<A> Future for Deferred<A> where A: Future {
    type Output = A::Output;

    fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
        match &mut self.state {
            DeferredState::Ready(value) => Poll::Ready(value.take().unwrap()),
            DeferredState::Pending(future) => future.poll_unpin(lw),
        }
    }
}

```

You use it like this:

```rust
async fn foo() {
    let x = await!(Force::new(bar()));

    ...

    let y = await!(x);
}

```

Basically, `Force::new` returns a `Future` which immediately polls `bar()`, and then you can later retrieve the value by awaiting on `x`.

This does have some overhead (a `Box` heap allocation), but perhaps that can be fixed with some trickery.

I’m not actually sure how to express this with implicit `await`. Maybe something like this?

```rust
async fn foo() {
    let x = async { Force::new(bar()) };

    ...

    let y = await!(x);
}

```

I haven’t looked too deeply at the various implicit async proposals, so I’m not sure how they handle deferred Futures.

I know they usually use `async { ... }` to do the actual deferral, but then how do they await the deferred Future?

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [January 23, 2019, 11:57pm UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/43 "2019-01-23T23:57:17Z")

</div>

That’s the reason I used `async || { .. }`. The idea in “implicit await” is that the explicit async creates a deferred execution, which is equivalent to a closure in sync code.

Personally, in a implicit await I think I’d write that as

```rust
async fn foo() {
    let x = Async::start(bar);
    ..
    let y = x.await();
}

```

I do think the system _requires_ a type (trait) for “synchronous asynchronous execution” which is `async fn` and a separate type (trait) for “deferred asynchronous execution” which is `async || { .. }`.

---

<div class="post-metadata">

**Author:** ![Pauan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pauan/32/3006_2.png) [@Pauan](https://internals.rust-lang.org/u/Pauan)\
**Post date:** [January 24, 2019, 12:59am UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/44 "2019-01-24T00:59:00Z")

</div>

I like this. It feels very clean, and it’s shorter than the explicit `await`.

I also like the strict separation between auto/non-auto Futures, with `Async::start` and `.await()` to convert between them.

As I understand it, `Async::start` and `.await()` are not magic at all, they are ordinary structs/methods.

Defining the `.await()` method seems fairly trivial, but how would the `Async::start` function be defined? It would have to take in the return value of an `async fn`, but without the auto-`await`.

I guess it could be used like this instead:

```rust
let x = Force::new(async || bar());

```

That seems quite reasonable as well.

---

<div class="post-metadata">

**Author:** ![Pauan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pauan/32/3006_2.png) [@Pauan](https://internals.rust-lang.org/u/Pauan)\
**Post date:** [January 24, 2019, 1:09am UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/45 "2019-01-24T01:09:16Z")

</div>

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:

```rust
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`:

```rust
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:

```rust
async fn foo() {
    let x = Force::new(|| bar());
    ...
    let y = x.await();
}

```

This is really great! Quite a bit nicer than explicit `await`.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [January 24, 2019, 9:25pm UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/46 "2019-01-24T21:25:41Z")

</div>

> [@vorner](#):
>
> I understand readability is a subjective thing. You may not need that information, but in the code I write, I often prefer to have it at hand.

I haven't read this whole thread, but I wanted to point out some interesting research on this topic. Jaeheon Yi and Tim Disney, working with Freund and Flanagan, [studied an extension to Java with "cooperative concurrency"](https://users.soe.ucsc.edu/~cormac/papers/issta12a.pdf) -- where you explicitly identify synchronization points with yield. The idea of their system was that the compiler put in enough locks that this was the only point you could observe "nonatomic execution".

If memory serves, one of the things they looked at was how quickly people fixed threading bugs. They found that, indeed, people fix bugs faster if they have explicit `yield`.

Just a datapoint.

(I don't think it's the only consideration, mind you, but it is an argument in favor of explicit `await`.)

---

<div class="post-metadata">

**Author:** ![cenwangumass](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cenwangumass/32/5112_2.png) [@cenwangumass](https://internals.rust-lang.org/u/cenwangumass)\
**Post date:** [January 25, 2019, 5:47am UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/47 "2019-01-25T05:47:14Z")

</div>

Hi, I just find this discussion about implicit await. I’m reposting my comment on Github. Just want to know if it’s a good idea to be explicit about implicit await since there is no feedback so far there.

We can first have prefix await landing:

```rust
await { future }?

```

And later we add something similar to

```rust
let result = implicit await { client.get("https://my_api").send()?.json()?; }

```

When choosing implicit mode, everything between `{}` are automatically awaited.

This has unified `await` syntax and would balance the need for prefix await, chaining, and being as explicit as possible.

---

<div class="post-metadata">

**Author:** ![yazaddaruvala](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yazaddaruvala/32/4927_2.png) [@yazaddaruvala](https://internals.rust-lang.org/u/yazaddaruvala)\
**Post date:** [January 28, 2019, 3:23am UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/48 "2019-01-28T03:23:20Z")

</div>

> They found that, indeed, people fix bugs faster if they have explicit `yield`.

@nikomatsakis There are definitely benefits to explicit await. The only question is if the benefits are worth the costs. The supporters of implicit await are also talking about "partial implicit await" which tries to balance the signal to noise of each additional `await` in the codebase.

A [proposal I've made](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/21), or another [similar idea from the github thread](https://github.com/rust-lang/rust/issues/57640#issuecomment-456209577).

Would love to hear your thoughts on such a compromise.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [April 28, 2019, 3:23am UTC](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256/49 "2019-04-28T03:23:26Z")

</div>

Closed on April 28, 2019, 3:23am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.

[Previous page](https://internals.rust-lang.org/t/would-implicit-await-really-be-a-bad-idea/9256.md?page=2)
