# Explicit future construction, implicit await

**URL:** <https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344>\
**Category:** language design\
**Created:** [April 20, 2018, 1:50am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344 "2018-04-20T01:50:39Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![yasammez](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yasammez/32/4029_2.png) [@yasammez](https://internals.rust-lang.org/u/yasammez)\
**Post date:** [April 21, 2018, 10:39pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/62 "2018-04-21T22:39:35Z")

</div>

Since the RFC was posted I tried to follow it all, but especially this thread always seems to move faster than I can keep up with; what a great, engaging community this is!

There has been a lot of talking about the Kotlin language in here. However, a comparison with Go could also shed some light on it. Disclaimer: I never used Go and all this is hearsay, but as far as I recall, in Go **every** statement is a possible suspension point, because everything can always yield to the Go green threading executor thingy. In practice this is indistinguishable from a preempted world in which an interrupt can move control over the thread from you after every CPU instruction, i.e. OS scheduling. This may be fine for Go (and Kotlin which comes with a default CPU pool?) which was designed to do one thing and do it well and solved the function colouring problem with a sledgehammer. Rust on the other hand has different design goals and ditched green threading a long time ago (which made me very happy). People are building kernels and other very low-level stuff in Rust. In a world where there may be no executor, no tokio reactor, no runtime support at all; maybe the futures will be polled, maybe they will be spawned on some hand-rolled state machine, who knows? Thus I am all for the “make interesting things explicit” way. My only wish was that async fns could anounce their impl Future in their visible signature; I understand from the RFC discussion that this is problematic together with lifetime elision, but I think it would have made the case clearer here, because then an async fn can just be read as a function which you can call to get exactly what it says on the tin, an impl Future, which you can then await at your leisure.

When the proposal for an @-sigil was first made, my guts hated it, but as I absorb more of the discussion, it looks nicer to me each day. So a +1 to that as well from me.

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [April 21, 2018, 10:43pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/63 "2018-04-21T22:43:02Z")

</div>

> [@MajorBreakfast](#):
>
> You mean when you forget to call await? Then, either the types don’t match or it is caught by the “unused variables” lint 🙂

How, then, did anyone ever get confused using Dart 1?

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [April 21, 2018, 10:43pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/64 "2018-04-21T22:43:02Z")

</div>

> [@parasyte](#):
>
> The illustration here is that just because it looks like it works, in reality that doesn’t always mean that it works as expected. I am under the impression that explicit await would have prevented this kind of condition (or at least been a good indicator of something gone awry) because it is nonsensical to await a synchronous function (like the blocking client API in pika). And if you know you are blocking a single threaded application, then the locality of the bug becomes more apparent.

I didn't quite understand this point. IIUC, you are saying that if `await` was explicit, you would have tried to `await!(pika_client())` and gotten an error that `pika_client` is not async. Is that correct?

* * *

> [@rpjohnst](#):
>
> The simplest way to get a value from an impl Future is the await function, the async equivalent of block\_on.

Sorry, I didn't quite understand the distinction between `block_on` and `await`.

> [@rpjohnst](#):
>
> ```rust
> async fn do_work() { .. }
> 
> async fn do_work_with_timeout() {
> let work = async { do_work() };
> 
> let when = Instant::now() + Duration::from_millis(100);
> let timeout = Delay::new(when);
> 
> futures::select(work, timeout);
> }
> 
> ```

To be clear, the actual work of `do_work` does not start until the `select`, right? So if I wanted to start the work earlier and concurrently do some other computation I would do something like this:

```rust
async fn do_work() { .. } // assume the work happens on thread B

async fn do_work_with_timeout() {
    let work = async { do_work() };
    let work = async { futures::await(work) }; // concurrently start `work` on B

    my_sync_function(); // do some computation synchronously on this thread

    let when = Instant::now() + Duration::from_millis(100);
    let timeout = Delay::new(when);

    futures::select(work, timeout);
}

```

Is that correct?

> [@rpjohnst](#):
>
> In an async context, the call some\_async\_fn(a, b, c) is expanded to this:

Is this supposed to say in a _sync_ context (i.e. not in an `async` block/fn/closure)? Or does it intentionally mean that in an `async` context we will block until the Future is resolved?

> [@rpjohnst](#):
>
> A common objection to this proposal is that it hides async code’s suspension points, making them look like normal function calls. This is important, they argue, because suspension points might allow another task to violate some invariant unexpectedly.
> 
> However, we already have an un-annotated operation that can do the same thing: a normal synchronous function call!

I still don't completely buy this argument. I realize that it's possible for a function to do arbitrary crazy stuff in theory, but in practice I don't usually expect a function to do arbitrary stuff in the middle without that being documented. On the other hand, in concurrent code I very much expect random stuff to happen in the middle of a function call (say, on another thread).

---

<div class="post-metadata">

**Author:** ![MajorBreakfast](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/majorbreakfast/32/4015_2.png) [@MajorBreakfast](https://internals.rust-lang.org/u/MajorBreakfast)\
**Post date:** [April 21, 2018, 10:45pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/65 "2018-04-21T22:45:44Z")

</div>

> [@rpjohnst](#):
>
> How, then, did anyone ever get confused using Dart 1?

Because Dart futures were lazy°, i.e. there was no way to synchronously run code when called. Now they're eager like in JavaScript, were everything until the first `await` is executed when you call the `async function`. Implicit/explicit await is orthogonal to this.

° Edit: (1 day later): What the Dart people call "lazy" is significantly different to Rust's definition of "lazy". More on that in subsequent comments

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [April 21, 2018, 11:07pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/66 "2018-04-21T23:07:55Z")

</div>

> [@mark-i-m](#):
>
> IIUC, you are saying that if `await` was explicit, you would have tried to `await!(pika_client())` and gotten an error that `pika_client` is not `async`. Is that correct?

Yes, I believe that is exactly what @parasyte meant.

> [@mark-i-m](#):
>
> Sorry, I didn’t quite understand the distinction between `block_on` and `await`.

`block_on` is synchronous. It actually blocks the calling thread until the future has completed. `await` its "async equivalent" because it does not _block_ the calling thread, but instead _suspends_ the calling task.

> [@mark-i-m](#):
>
> To be clear, the actual work of `do_work` does not start until the `select`, right? So if I wanted to start the work earlier and concurrently do some other computation I would do something like this:

You are correct that `do_work` does not start until the call to `select`. But your example does does not do what you want. You would need to do something like this instead:

```rust
fn start_do_work() -> impl Future {
    signal_thread_b_to_start_working();
    async { .. }
}

async fn do_work_with_timeout() {
    let work = start_do_work();

    my_sync_function();

    let when = Instant::now() + Duration::from_millis(100);
    let timeout = Delay::new(when);

    futures::select(work, timeout);
}

```

> [@mark-i-m](#):
>
> Is this supposed to say in a _sync_ context (i.e. not in an `async` block/fn/closure)? Or does it intentionally mean that in an `async` context we will block until the Future is resolved?

The latter- `some_async_fn(a, b, c)` has no meaning in a sync context, and results in a compiler error. This is what gives this proposal the name "implicit await."

> [@MajorBreakfast](#):
>
> Because Dart futures were lazy, i.e. there was no way to synchronously run code when called. Now they’re eager like in JavaScript, were everything until the first `await` is executed when you call the `async function`.

Why does this not _also_ apply to explicit await in Rust? This also accurately describes the main RFC, and this is precisely why the Dart designers reached out to warn us! (Yes, the main RFC does provide the `-> impl Future { .. async { .. } }` trick, but this is also available to Dart 1.)

The problem is not lazy futures on their own. It is lazy futures _combined_ with the mistaken expectation that the expression `some_async_fn()` will do something more than construct the future. Dart 2 addresses the first aspect by making futures eager; implicit await addresses the second aspect by making that expectation correct.

Again, please think through the point you're trying to make, because you're re-treading ground that has already been covered here, on GitHub, and on Reddit.

---

<div class="post-metadata">

**Author:** ![MajorBreakfast](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/majorbreakfast/32/4015_2.png) [@MajorBreakfast](https://internals.rust-lang.org/u/MajorBreakfast)\
**Post date:** [April 21, 2018, 11:27pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/67 "2018-04-21T23:27:04Z")

</div>

> [@rpjohnst](#):
>
> The problem is not lazy futures on their own. It is lazy futures combined with the mistaken expectation that the expression some\_async\_fn() will do something more than construct the future.

It's only a problem if we forget the `await`. This can be detected by adding an "unused\_must\_use" warning to futures like it exists today for `Result`.

```rust
async fn get_num() () { 42 }

async fn my_fn() {
  get_num(); // Warning: "unused_must_use"
  await get_num(); // Correct

  get_num().is_positive(); // Error: Method does not exist
  (await get_num()).is_positive(); // Correct
}

```

With this, lazy futures and explicit await is just as easy.

---

<div class="post-metadata">

**Author:** ![tmccombs](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tmccombs/32/1845_2.png) [@tmccombs](https://internals.rust-lang.org/u/tmccombs)\
**Post date:** [April 21, 2018, 11:36pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/68 "2018-04-21T23:36:09Z")

</div>

I don’t really understand what implicit await has to do with making it more clear that async functions are lazy futures. I get that you want the call to look more like a constructor, to make it clear that is only constructing the future and not executing it eagerly, but that seems orthogonal to whether await is implicit or explicit. An alternative could be to have syntax like:

```rust
async do_work(...) {
    let x = await!(async_fn::new());
    let y = await!(future_fn());
   ....

```

where async “functions” are really just definitions for structs and are _always_ constructed with the `new` method, and awaits are explicit.

I’d also like to point out that there is now garantee that there is any eager evaluation for non-async functions that return `impl Futurure` either. And even if the future is eagerly evaluated, you don’t know how much it is evaluated, and if you want it to continue executing, you need to make sure it gets polled by awaiting, adding it to some execution context, or manually polling it.

I think that marking Futures as a must\_use type, and having good documentation would be a better solution.

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [April 21, 2018, 11:47pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/69 "2018-04-21T23:47:25Z")

</div>

> [@MajorBreakfast](#):
>
> With this, lazy futures and explicit await is just as easy.

For literally the third time, Dart 1 already has all of that, and was still confusing enough that they changed things.

> [@tmccombs](#):
>
> I don’t really understand what implicit await has to do with making it more clear that async functions are lazy futures. I get that you want the call to look more like a constructor, to make it clear that is only constructing the future and not executing it eagerly, but that seems orthogonal to whether await is implicit or explicit.

That's not an accurate description of what I want. In fact, if you take a look at the revised proposal, you'll see I don't use constructor-like syntax at all. (FWIW, your alternative syntax has a lot in common with the revised proposal's "future-compatible" section.)

The point of implicit await is to make the `foo()` syntax, which _looks_ like a function call, also _act_ like a function call. The follow-on effect of this is that all the remaining ways to expose lazy behavior _don't_ look like function calls. Some may look like constructor calls, but others look like closures, or whatever else we come up with.

---

<div class="post-metadata">

**Author:** ![MajorBreakfast](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/majorbreakfast/32/4015_2.png) [@MajorBreakfast](https://internals.rust-lang.org/u/MajorBreakfast)\
**Post date:** [April 21, 2018, 11:47pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/70 "2018-04-21T23:47:26Z")

</div>

> [@tmccombs](#):
>
> I think that marking Futures as a must\_use type, and having good documentation would be a better solution.

I've posted this now in the futures RFC: [Link to comment](https://github.com/rust-lang/rfcs/pull/2395#issuecomment-383341721)

---

<div class="post-metadata">

**Author:** ![MajorBreakfast](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/majorbreakfast/32/4015_2.png) [@MajorBreakfast](https://internals.rust-lang.org/u/MajorBreakfast)\
**Post date:** [April 22, 2018, 12:02am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/71 "2018-04-22T00:02:45Z")

</div>

> [@rpjohnst](#):
>
> For literally the third time, Dart 1 already has all of that, and was still confusing enough that they changed things.

But they changed a different aspect! They went from "lazy" ° to "eager" and kept explict `await`!

They wern't happy with the "lazy" ° aspect (for reasons explained in the post on reddit), so they changed it to "eager". Implict vs explict `await` had nothing to do with it! A forgotten `await` is BTW just as bad with "eager" as with "lazy" ° futures. It just fails in a different way (future runs concurrently instead of not at all (Rust) or asynchronously (Dart 1), edited: Added distinction, see my next comment why).

° Edit: (1 day later): What the Dart people call “lazy” is significantly different to Rust’s definition of “lazy”. More on that in subsequent comments

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [April 22, 2018, 12:17am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/72 "2018-04-22T00:17:57Z")

</div>

@rpjohnst Thanks for the clarifications and the thought provoking pre-RFC 🙂

So I’m coming at this from the perspective of an async I/O novice. I have never really used async I/O for anything serious, and my first introduction to async I/O was through Alex’s [Back to the Futures](https://www.youtube.com/watch?v=bcrzfivXpc4) talk and Rust Futures as they existed.

That said, starting from my “blank slate” perspective, I find the current RFC proposal more easy to understand than this proposal. Introspecting a bit, I think this might be because

- There seems to be “less stuff” in some sense. For example, in the original RFC, `async fn`s are really just another way to construct a `Future`. There doesn’t need to be any bridging between `async fn` and the rest of the Futures ecosystem. This significantly reduces the cognitive overhead for me as a beginner.
- There are a few counterintuitive things:
  - `async fn` are not async by default, rather they are awaited by default. I realize that this is the whole point, but it still takes a bit of getting used to.
  - `futures::await` is `async`. As you saw, the difference between `await` and `block_on` is a bit non-obvious until explained.

- I actually don’t find it more clear to know when things run under this model. If anything, I’m having a bit more trouble because I’ve already trained myself to the lazy model. Under the lazy model, I know that stuff only happens when I `poll`. Under this model they happen when I make a function call, unless it’s a call to an `async fn` in an `async` block.

I don’t know how common my perspective is, but hopefully it is a useful data point.

---

<div class="post-metadata">

**Author:** ![MajorBreakfast](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/majorbreakfast/32/4015_2.png) [@MajorBreakfast](https://internals.rust-lang.org/u/MajorBreakfast)\
**Post date:** [April 22, 2018, 12:23am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/73 "2018-04-22T00:23:10Z")

</div>

I just noticed that there’s a difference between what’s called “lazy” in Rust and in Dart 1.

- Rust futures do nothing if you don’t await them
- Dart 1 futures run even if you don’t await them, they just start asynchronously: [https://dartpad.dartlang.org/33706e19df021e52d98c](https://dartpad.dartlang.org/33706e19df021e52d98c) (DartPad is “Based on Dart SDK 1.25.0.”, click on “DartPad” in the top left corner to see this)

@rpjohnst You should remove the Dart thing under “benefits”. Dart 1’s futures weren’t lazy by Rust’s definition and Dart 2’s futures still have explicit `await`. There really isn’t any basis for comparison. (If anything, the fact that they chose explicit `await` and are sticking with it serves more like a counter example)

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [April 22, 2018, 12:40am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/74 "2018-04-22T00:40:53Z")

</div>

> [@mark-i-m](#):
>
> Under the lazy model, I know that stuff only happens when I `poll`. Under this model they happen when I make a function call, unless it’s a call to an async fn in an async block.

Maybe this phrasing will make things clearer: under this model, stuff _always_ happens when you make a function call. An `async` block is like a closure, in that its body does not run (i.e., you in fact do not make said function call) until it is `poll`ed.

I'm actually somewhat confused by your description. You make it sound like you expect `async { some_sync_fn() }` to run `some_sync_fn` immediately, when it is actually deferred along with the rest of the `async` block's body!

---

<div class="post-metadata">

**Author:** ![parasyte](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/parasyte/32/8925_2.png) [@parasyte](https://internals.rust-lang.org/u/parasyte)\
**Post date:** [April 22, 2018, 12:46am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/75 "2018-04-22T00:46:03Z")

</div>

> [@mark-i-m](#):
>
> I didn’t quite understand this point. IIUC, you are saying that if await was explicit, you would have tried to await!(pika\_client()) and gotten an error that pika\_client is not async. Is that correct?

I think you have the gist of it, yes.

---

<div class="post-metadata">

**Author:** ![tmccombs](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tmccombs/32/1845_2.png) [@tmccombs](https://internals.rust-lang.org/u/tmccombs)\
**Post date:** [April 22, 2018, 1:58am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/76 "2018-04-22T01:58:30Z")

</div>

> all the remaining ways to expose lazy behavior don’t look like function calls

that isn't the case though. Regardless of what happens with async/await syntax a call to a normal function that returns a Future is lazy, and looks like a normal function call. As a concrete example:

```rust
// in a non-async context
async_stream.read(buffer); // looks like a normal function call, doesn't do anything until the return value is scheduled.

```

> you’ll see I don’t use constructor-like syntax at all

ok, what I should have said is you want a different syntax to somehow indicate that the future is lazy. But my point that it is orthogonal to implicit await still stands.

> For literally the third time, Dart 1 already has all of that, and was still confusing enough that they changed things.

Dart has a very different execution model though. Dart (and javascript) has an implicit event loop, and futures are automatically scheduled onto the event loop, in rust however, the future must be added to something to poll it.

Python's async/await is actually pretty similar to the RFC. An async function returns a coroutine object, which must be added to an event loop or awaited in another async function. In python the coroutine is also lazy, not eager, and await is explicit. Has there been a lot of confusion about coroutines being lazy in python?

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [April 22, 2018, 2:26am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/77 "2018-04-22T02:26:58Z")

</div>

> [@rpjohnst](#):
>
> I’m actually somewhat confused by your description. You make it sound like you expect async { some\_sync\_fn() } to run some\_sync\_fn immediately, when it is actually deferred along with the rest of the async block’s body!

I think for some reason my mental model was that if I put something in an `async` block, it immediately starts running concurrently somehow and I get a future to the final result. Looking back, that doesn't really make sense, though...

---

<div class="post-metadata">

**Author:** ![vorner](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vorner/32/3310_2.png) [@vorner](https://internals.rust-lang.org/u/vorner)\
**Post date:** [April 22, 2018, 7:12am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/78 "2018-04-22T07:12:38Z")

</div>

As for the suggestion to wrap things that must not do async into a sync function (or maybe a local closure) ‒ I’ve already thought of that. And I would probably structure my code that way, but it’s an ugly hack at best, because:

- I think it’ll be less rare in Rust than you think. You still seem to consider Rust to be one more Kotlin or Go, designed to just run your server code, but fast… while Rust can do that, what makes it unique is it’s _very_ low-level nature, allowing you to do all kinds of crazy things while preserving at least some sanity. Degrading this support for the sake of a code that _pretends_ not to be async on the surface doesn’t sound correct in that context.
- If the author decides to write it that way, sure it becomes more readable in the code review or when hunting for bugs. But if the author forgets or doesn’t know about the trick, the review is still tedious ‒ in other words, I’d either have to mandate that every place with a mutex held is wrapped into a sync function, or give up on that and still suspect every single thing.
- This doesn’t go well with the „pit of success“ principle. It should be _easier_ to do the right thing (writing a code that is clear about the intentions, here), while here it looks like the right thing is much more convoluted.

You state that now you want you `async fn` to return future too, but that it runs it right away… how does it fit into _any_ mental model? How does the `async fn`'s call expand into something that does the `NotReady` loop and pinning? How can the function (if it’s a function) influence what happens on the caller side?

How much is that `async fn` just `fn → Future`? If I have another function, like this:

```rust
async fn measure_time<R, F: FnOnce() -> R>(f: F) -> R {
    let before = ntp_get_time(); // This one is async
    let result = f(); // ????
    let after = ntp_get_time(); // Async
    print("It took: {}", after - before);
}

```

Now, if I pass a sync function, it does something I expect. How should it act when I pass an async fn? Should it not compile, because `async fn` isn’t just `fn → Future`, at least sometimes (inconsistent), should it create and await that future (probably consistent but very surprising to the author of the `measure_time` or should it just return the `Future`, because some kind of other exception (inconsistent)?

I think implicit await fits well with languages where the async is really a core feature of the language, like Go, where everything is just async and implicit await in a sense. But I feel Rust is built around different models and async is just an extension, one of many and in much of the code isn’t `async`. It feels like the `IO` monad in Haskell to me a bit ‒ you could write all your program in the `IO` monad, but the usual style is to do it only on the top level ‒ to read/write the input, but the the computation in pure code. In Rust I would imagine the usual pattern would be to do the async somewhere on the top level (maybe just one async fn, with few suspension points) and all the computations to be done in sync code. Sure, not everything fits there.

---

<div class="post-metadata">

**Author:** ![bbatha](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bbatha/32/2662_2.png) [@bbatha](https://internals.rust-lang.org/u/bbatha)\
**Post date:** [April 22, 2018, 6:19pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/79 "2018-04-22T18:19:35Z")

</div>

> [@rpjohnst](#):
>
> This solves the problem, though it is somewhat strange. It enables you to construct an instance of foo::Type by calling foo::new(args..), in addition to the async { .. } syntax for constructing a future with a fresh anonymous type.

Instead of this implementation, why not have `async fn`s implement a compiler magic `AsyncFn*` trait that's similar to the closure traits. Then later the `AsyncFn*` traits can be changed to be aliases for an `Async + Fn*` where `Async` is some trait that exposes the machinery of `async fn`s enough to implement functions like `Future::await`, and possibly even opt into implicit `await` for handwritten types. This also would nicely interact with the `abstract Types` feature.

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [April 23, 2018, 1:20am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/80 "2018-04-23T01:20:22Z")

</div>

> [@vorner](#):
>
> You state that now you want you async fn to return future too, but that it runs it right away… how does it fit into any mental model?

I believe the mental model is that if it looks like a normal function call, it is (i.e. it actually does stuff). If it is in an `async` block, it does not do anything immediately and the whole block evaluates to a Future (you can only call `async fn`s in an `async` block). So

> [@vorner](#):
>
> ```rust
> async fn measure_time<R, F: FnOnce() -> R>(f: F) -> R {
> let before = ntp_get_time(); // Actually get the time
> let result = f(); // Does something
> let after = ntp_get_time(); // Actually get the time again
> print("It took: {}", after - before); // Prints the time elapsed during `f`
> }
> 
> fn main() {
> // This doesn't do anything. It just creates a future
> let future = async { measure_time() };
> 
> // This actually does stuff and prints a time
> measure_time();
> 
> // This actually does stuff and prints a time (again)
> future.await();
> }
> 
> ```

---

<div class="post-metadata">

**Author:** ![mark-i-m](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mark-i-m/32/3167_2.png) [@mark-i-m](https://internals.rust-lang.org/u/mark-i-m)\
**Post date:** [April 23, 2018, 1:23am UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/81 "2018-04-23T01:23:51Z")

</div>

That said, there might need to be some compiler magic to track the async-ness of `f`, and I’m not really sure if that’s possible in general…

[Previous page](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344.md?page=3)

[Next page](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344.md?page=5)
