# 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:** 2

<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 20, 2018, 3:35pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/22 "2018-04-20T15:35:23Z")

</div>

@rpjohnst Are you proposing that async functions (like `print()` in the example above) should act differently than hand-written functions that return a future (like `Timeout::form_secs()`) when they’re used?

How would I sequentially execute and implicitly await the following code?

```rust
async fn function() {
    let future_a = print::new("hello world");
    let future_b = Timeout::from_secs(5);
    select(future_a, future_b)
}

```

* * *

I fixed various things in the code from your comment. Also, I’ve included a question. Was I correct in applying these fixes?

```rust
async fn my_fn1() { // with forward-compatible explicit await
    async_get_num(); // error for forward compatibility

    await!(async_get_num::new()); // explicit await, Fix1: Added missing ::new()

    println!("{}", await!(async_get_num::new())); // explicit await, Fix:2 Added missing ::new()

    let future = async { await!(async_get_num::new()); }; // Fix3: Added missing await and added missing ::new()

    await!(join_all(vec![future, async_get_num::new()]); // explicit await
}

async fn my_fn2() { // implicit await (future Rust)
    async_get_num(); // implicit await

    // explicit await still works (though now it's just the identity macro)
    await!(async_get_num());

    println!("{}", async_get_num()); // implicit await (prints i32)

    // construct a future, no inference because it was never ambiguous to begin with
    let future = async { async_get_num() }; // Q1: Why is this not awaited implicitly? Async blocks return a future
    join_all(vec![future, async_get_num::new()]); // implicit await
}

```

---

<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 20, 2018, 3:55pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/23 "2018-04-20T15:55:29Z")

</div>

> [@MajorBreakfast](#):
>
> Are you proposing that async functions (like `print()` in the example above) should act differently than hand-written functions that return a future (like `Timeout::form_secs()`) when they’re used?

Yes, and I also covered this in the rationale section under "eager futures."

> [@MajorBreakfast](#):
>
> How would I sequentially execute and implicitly await the following code?

Sequentially executing that code makes no sense, because it uses a `Timeout` with `select`. If you actually wanted to execute the two futures sequentially (that is, print "hello world" and then wait for five seconds), you would write this:

```rust
async fn function() {
    print("hello world"); // `print` is `async`, so calling it implicitly awaits
    Timeout::from_secs(5).await(); // `Timeout` is a `Future`, so you can `.await()` it if you need to make it happen "now."
}

```

> [@MajorBreakfast](#):
>
> Was I correct in applying these fixes?

No:

- `Fix1` and `Fix2` are have the same behavior as what I wrote, but they are unnecessary. Leaving off the `::new()` is what allows `await!` to become the identity macro later. (Note that this is not part of my actual proposal, only the "forwards compatibility" concept.)
- `Fix3` is partially correct- I did need an `await!` (again, for future compatibility only), which I have now added, but the `::new()` is unnecessary as it is for `Fix1` and `Fix2`.

> [@MajorBreakfast](#):
>
> ```rust
> let future = async { async_get_num() }; // Q1: Why is this not awaited implicitly? Async blocks return a future
> 
> ```

The `async_get_num()` call _is_ awaited implicitly- but only inside the `async` block. The `async` block itself is not awaited implicitly, because it is one of the two ways to explicitly construct a future value.

Think about what it would mean if `async` blocks _were_ awaited implicitly- they would no longer be usable outside of `async fn`s, and they would no longer behave any differently from simply writing their contents outside the block.

I suspect you are still confused about what exactly I mean by "implicit await."

- I emphatically **do not** mean that any future evaluated in an `async` context should be immediately awaited.
- I **do** mean that the `some_async_fn()` syntax _changes meaning_ from "construct a future" to "construct and await a future, without ever exposing that future." To go along with this, I note that it is still possible to obtain an actual future value in several ways:
  - Constructing a hand-written future, as always.
  - Using an `async` block, which evaluates to a value whose type implements `Future` just like a closure evaluates to a value whose type implements `Fn`.
  - Optionally, use a new `some_async_fn::new()` function, which provides the old behavior of `some_async_fn()` without the need for `async { .. }`'s additional anonymous type.

---

<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 20, 2018, 4:04pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/24 "2018-04-20T16:04:43Z")

</div>

> [@Nemo157](#):
>
> the main reason I have for wanting separate construction and execution phases is for dealing with data conversion and temporary borrows

That's a very good point. However, I'm not sure it changes anything about my reasoning. Differentiating the two forms (one that borrows its arguments until completion and the other that releases them after construction) via explicit syntax has the same benefits as differentiating whether an initial request is fired off.

---

<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 20, 2018, 4:08pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/25 "2018-04-20T16:08:11Z")

</div>

Having two Futures-like traits (`async` and `Future`) is IMO very confusing. Does Kotlin have such a distinction? Anyway such a distinction destroys a major purpose of async functions: They’re supposed to be a convenient way to write a function that returns a future. Calling them is supposed to work exactly like ordinary functions that return a future.

---

<div class="post-metadata">

**Author:** ![jethrogb](https://avatars.discourse-cdn.com/v4/letter/j/43a26b/32.png) [@jethrogb](https://internals.rust-lang.org/u/jethrogb)\
**Post date:** [April 20, 2018, 4:11pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/26 "2018-04-20T16:11:28Z")

</div>

I’m having a hard time understanding this proposal since there is no direct comparison between code in the current RFC proposal and this proposal. I’d like to see comparisons for these points:

- How is an `async fn` declared and what is the actual return type?
- How is an `async fn` called from another `async fn`?
- How is an async fn called from a regular `fn`?
- In either function, how can you use the returned value of an `async fn` as `impl Future`?

I’m strongly against any proposal that can’t be correctly expressed in the type system, considering both the `Future` and `Fn/FnMut/FnOnce` traits.

---

<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 20, 2018, 4:22pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/27 "2018-04-20T16:22:59Z")

</div>

> [@MajorBreakfast](#):
>
> Having two Futures-like traits (`async` and `Future`) is IMO very confusing. Does Kotlin have such a distinction?

I do not propose this at all. As in the main proposal, `async` is a keyword that transforms a function or block body so that it can suspend, and `Future` is a trait that lets you interact with both `async`-transformed functions and hand-written implementations.

Kotlin does _sort of_ have this distinction, but it's because they use `suspend fun`s for both generators and async/await. I discussed a design like this [here](https://internals.rust-lang.org/t/pre-rfc-await-generators-directly/7202) but it makes the interaction between futures and iterators much harder to deal with. @withoutboats addresses this decision both in that thread and [in the main RFC](https://github.com/withoutboats/rfcs/blob/async-await/text/0000-async_await.md#async-based-on-generators-alone).

> [@MajorBreakfast](#):
>
> They’re supposed to be a convenient way to write a function that returns a future.

I disagree. They are supposed to be a convenient way to _construct_ futures, but that doesn't mean they have to literally return a future when using the function call syntax.

---

<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 20, 2018, 4:26pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/28 "2018-04-20T16:26:06Z")

</div>

> [@rpjohnst](#):
>
> but that doesn’t mean they [async functions] have to literally return a future when using the function call syntax.

Any such distinction would make async Rust just unnecessarily complicated.

---

<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 20, 2018, 4:37pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/29 "2018-04-20T16:37:25Z")

</div>

@jethrogb Fair enough. This proposal has no problems being expressed in the type system:

> [@jethrogb](#):
>
> - How is an `async fn` declared and what is the actual return type?

Declaration remains identical to the main RFC:

```rust
async fn foo(a: A, b: B) -> C { .. }

```

In the main RFC, this desugars to this:

```rust
fn foo(a: A, b: B) -> impl Future<Output = C> { .. }

```

In this proposal, it desugars to this:

```rust
mod foo {
    struct Type { .. }
    fn new(a: A, b: B) -> Type { .. }
    impl Future for Type {
        type Output = C;
        fn poll(self: Pin<Self>, cx: &task::Context) -> Async<Self::Output> { .. }
    }
}

```

(This is not, however, the point of this proposal- this module doesn't have to be exposed, as I mentioned under unresolved questions.)

> [@jethrogb](#):
>
> - How is an `async fn` called from another `async fn`?

The main RFC describes the desugaring for `await!(foo())` as this:

```rust
let mut future = IntoFuture::into_future(foo());
let mut pin = unsafe { Pin::new_unchecked(&mut future) };
loop {
    match Future::poll(Pin::borrow(&mut pin), &mut ctx) {
          Async::Ready(item) => break item,
          Async::Pending => yield,
    }	
}

```

This proposal uses the same expansion, but instead of applying it to `await!(future)` it applies it to `foo()`:

```rust
let mut future = foo::new();
let mut pin = unsafe { Pin::new_unchecked(&mut future) };
loop { /* ... as before ... */ }

```

> [@jethrogb](#):
>
> - How is an `async fn` called from a regular `fn`?
> - In either function, how can you use the returned value of an `async fn` as `impl Future`?

You do not. Instead, both types of functions call `some_async_fn::new()` when they want an `impl Future`. This has the same behavior that the main RFC ascribes to `some_async_fn()`- it constructs the `async fn`'s corresponding future but does not run it:

```rust
// main RFC:
fn main() {
    let future = some_async_fn();
    tokio::run(future);
}

// this proposal:
fn main() {
    let future = some_async_fn::new();
    tokio::run(future);
}

```

---

<div class="post-metadata">

**Author:** ![MajorBreakfast2](https://avatars.discourse-cdn.com/v4/letter/m/c89c15/32.png) [@MajorBreakfast2](https://internals.rust-lang.org/u/MajorBreakfast2)\
**Post date:** [April 20, 2018, 4:46pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/30 "2018-04-20T16:46:57Z")

</div>

@rpjohnst You should add to your comment above that also that you propose `fn_that_returns_a_future().await()` to await a future inside async functions. So that everything you propose is finally together in one post. Your post has cleared a lot of things up that were still unclear to me. (As stated in my previous comments I do not agree with various aspects of it, though)

Note: I’ve created my account today and I’ve now reached my 16 reply limit for today. Thus I’m now “MajorBreakfast2” for the time being

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [April 20, 2018, 5:05pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/31 "2018-04-20T17:05:21Z")

</div>

Rust has intentional syntax noise `?` for returns in error handling, as a compromise between explicit handling and terseness of exceptions.

Having “hidden” returns caused by futures would be unusual for Rust. However, maybe another sigil can be invented as a shortcut for await? e.g. `let x = @fetch_x();`

---

<div class="post-metadata">

**Author:** ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)\
**Post date:** [April 20, 2018, 5:07pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/32 "2018-04-20T17:07:59Z")

</div>

> [@rpjohnst](#):
>
> Another extension might be to apply a CPS transform to async fns, to improve performance of suspending and resuming around nested awaits. By limiting direct invocation of async fns to async contexts where they are immediately awaited, we reserve the ability to tweak their calling convention without touching the Future trait.

This kind of difference sounds surprising, at least when thinking about it under the simplified mental model of "one of them puts the extra syntax here, the other one puts it there". Could you explain? Under the "main" proposal, why couldn't the same thing be accomplished by changing the desugaring of `await!()` (which is what corresponds to "directly calling it" in this proposal)?

...Is it because `await!()` has to work uniformly for both `Future`s as well as `async fn`s, while your proposal distinguishes these?

> [@rpjohnst](#):
>
> However, we already have an un-annotated operation that can do all the same things: a normal sync function call!

I think it would be helpful to illustrate this - that is, a normal sync function call messing things up in the same way as an `await` - using an example or two.

> [@rpjohnst](#):
>
> This is a trade-off with the eager-vs-lazy confusion from the motivation section. What we lose in knowledge of suspension points, we gain in clarity around when async code runs. Notably, the latter point is what the designers and users of other languages have warned us about- not the former.

(I think this could use some unpacking as well - it's not obvious to me what kind of warnings by who this is referencing.)

> This difference is what wins us the clarity around when work is delayed vs when it is fired off immediately. Delayed futures will have a .await() or will be passed to some combinator; normal async fns will appear to directly return their final result.

(I think I understand what you mean here, but only because I already know what you're probably trying to say. Otherwise, I think it'd be helpful to be more explicit about what the significant difference between "delayed futures" and "normal async fns" is, and how distinguishing them gives us greater clarity about what exactly.)

> [@rpjohnst](#):
>
> In Rust, you might use an intrinsic like this to implement leaf futures without ever leaving the async fn world.

(It's not at all obvious to me what this could look like, which may be OK - I've never implemented a leaf future by hand either.)

> [@rpjohnst](#):
>
> I used somewhat of a strawman syntax for future construction- some\_async\_fn::Type and some\_async\_fn::new(..). This could be completely left out in the initial design, in favor of always using async { .. } to construct future values.
> 
> That syntax would, however, enable library authors to store their async fn-based futures in structs, and to implement methods on them.

Would it be hacky to just legislate that an `async { ... }` block containing exactly a single call to an `async fn` shall have the same type as that `async fn`, rather than a fresh anonymous type? Thus replacing a syntactic special case (`::new()` or whatever) with a semantic one.

(Would it still need to have the `::Type` part even then? It's a bit _weird_ to have things which look like `fn`s but are also used as `mod`ules, so it'd be nice to avoid that if it's possible.)

---

<div class="post-metadata">

**Author:** ![MajorBreakfast2](https://avatars.discourse-cdn.com/v4/letter/m/c89c15/32.png) [@MajorBreakfast2](https://internals.rust-lang.org/u/MajorBreakfast2)\
**Post date:** [April 20, 2018, 5:17pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/33 "2018-04-20T17:17:02Z")

</div>

@kornel A lot of `await` syntax alternatives were discussed in the RFC issue before the discussion was tabled to focus on other stuff. [https://github.com/rust-lang/rfcs/pull/2394#issuecomment-383038441](https://github.com/rust-lang/rfcs/pull/2394#issuecomment-383038441) We had:

- `await!(func())` and `await!(func())?`
- `await func()` and `(await func())?` or `await? func()`
- `await:func()` and `await:func()?`
- `func()~` and `func()~?`
- `func().await` and `func().await?`

This thread is about having no keyword, though (implicit await)

---

<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 20, 2018, 5:19pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/34 "2018-04-20T17:19:03Z")

</div>

> [@kornel](#):
>
> Having “hidden” returns caused by futures would be unusual for Rust.

They're not hidden _returns_ per se- the rest of the function will still run, unlike with `?` applied to `Err`. The danger is more that the hidden _suspension_ will lead to invalidated state, but as I said this can already happen just in a normal function call.

---

<div class="post-metadata">

**Author:** ![jethrogb](https://avatars.discourse-cdn.com/v4/letter/j/43a26b/32.png) [@jethrogb](https://internals.rust-lang.org/u/jethrogb)\
**Post date:** [April 20, 2018, 5:24pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/35 "2018-04-20T17:24:40Z")

</div>

Thanks, this makes your proposal significantly clearer to 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 20, 2018, 5:30pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/36 "2018-04-20T17:30:18Z")

</div>

@glaebhoerl Thanks a bunch for the review! I think I'm going to try to revise the proposal based on this and the confusion earlier in the thread. But I'll say a couple things now:

> [@glaebhoerl](#):
>
> …Is it because `await!()` has to work uniformly for both `Future`s as well as `async fn`s, while your proposal distinguishes these?

Yes, exactly. Explicit await bakes the await "calling convention" into the interface, because you can await a `Future` the same way you run an `async fn`. This proposal includes an explicit "bridge" between the two worlds (the `Future::await` method).

I suspect it _might_ be possible to make a CPS transform work under the main RFC, by automatically inserting those bridges whenever an `async fn` is called outside of an `await!` expansion, but I'm not sure it would be worth the complexity in the implementation of `await!` or in understanding what code the compiler generates.

> [@glaebhoerl](#):
>
> Would it be hacky to just legislate that an `async { ... }` block containing exactly a single call to an `async fn` shall have the same type as that `async fn`, rather than a fresh anonymous type?

That would get rid of the need for `::new()`, but `::Type` would still be useful. It enables people to name the `async fn`'s corresponding type, for storing in structs or implementing methods on.

I kind of like it, though- maybe we could drop the braces when we want the inner type, like this:

```rust
let future = async { .. }; // fresh anonymous type
let future = async some_async_fn(); // `some_async_fn`'s corresponding type

```

---

<div class="post-metadata">

**Author:** ![harrychin](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/harrychin/32/2986_2.png) [@harrychin](https://internals.rust-lang.org/u/harrychin)\
**Post date:** [April 20, 2018, 5:34pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/37 "2018-04-20T17:34:11Z")

</div>

> [@rpjohnst](#):
>
> Because it is a suspend fun, it can only be called from a suspend context (analogous to Rust’s async fns).

Part of the confusion in the comparison that I think is somewhat missed under Kotlin and this formulation vs the RFC is that an async or suspending function cannot be called from synchronous code directly.

Kotlin bridges the gap between the synchronous and asynchronous worlds by providing builder functions which can be called from non-suspending code, but they still accept a suspending lambda (closure) from which you can call your suspendable code. This formulation is attempting to achieve that similar builder pattern with some\_async\_fn::new().

One of Kotlin’s builders is called “async {…}” as @rpjohnst has mentioned before, and it’s what exposes the “.await()” function using a “Deferred” interface.

In Kotlin, “async {…}” implies I am going to run this suspending lambda right away, on either a default context or an explicit one, and so you must “.await()”, otherwise it will run to completion and not return a value to anyone. Whereas calling a suspendable function implies that my current function will suspend (or Yield in Rust) and then start running that function (similar to await!()), similar to blocking code in that it still conforms to the linear mental model of code I've been using up to that point.

I think @rpjohnst's other argument is that it's the breaking of linearity which causes confusion, as await!() still implies that my function has stopped until the other future completes.

Kotlin does not quite have an analogous type to Rust’s Future built-in. It’s “Continuation” interface is actually closer in relation to “Generator” in Rust, so in Kotlin, “Jobs” acts as a hybrid of Rust’s “Tasks” and “Future”. Like Generators in Rust currently, you never work directly with Continuations, but instead, you interact with the Job type.

---

<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:** [April 20, 2018, 6:36pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/38 "2018-04-20T18:36:30Z")

</div>

I’d like to challenge the assumption that linear `await` is the most common case in `async fn`.

In JavaScript-y syntax, I think the common case is the following:

```rust
const fileA = fs.read_async("fileA")
const fileB = fs.read_async("fileB")
return await process(await fileA, await fileB)

```

Note that this processes both async reads in parallel. This is, to me, the reason for using `async fn`: that you can get multiple tasks running at the same time that require waiting. Asynchronous IO is by far the most common case of async code.

However, Rust has decided it does not want to start computation until the async context is awaited, so this formulation requires some kind of join so both futures can be awaited concurrently. So, in fully qualified and macro syntax (don’t quote me this is free hand):

```rust
let file_a = async! { fs::read_async("fileA") };
let file_b = async! { fs::read_async("fileB") };
let [file_a, file_b] = await!(Future::all([file_a, file_b]));
await!(process(fileA, fileB))

```

That would be, under **implicit async, explicit await** :

```rust
let file_a = fs::read_async("fileA");
let file_b = fs::read_async("fileB");
let [file_a, file_b] = await!(Future::all([file_a, file_b]));
await!(process(fileA, fileB))

```

And under **explicit async, implicit await** :

```rust
let file_a = Future::of(async || { fs::read_async("fileA") });
let file_b = Future::of(async || { fs::read_async("fileB") });
let [file_a, file_b] = Future::all([file_a, file_b]).await();
process(file_a, file_b)

```

Did I get this right, @rpjohnst?

An interesting consequence of the second style is that, in an async context, you don’t care if you’re calling an `async fn` or a `fn`; both behave the same (modulo if you suspend or block to wait). If you want a deferred value (a `Future`), you construct one explicitly from a new async context. I used a constructor for `Future` here to be explicit, but `Future::of(async || { ... })` would probably be spelled `async! { ... }`.

A `Future` then provides the `async fn` method `Future::await(self)` that then actually drives the `Future` in its caller’s context.

I never really understood the Kotlin style of async until now, but I think I do now. Based on the comparison I have above, I’m now up in the air on which style I’d prefer in a world where futures aren’t registered until they’re awaited.

---

<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 20, 2018, 6:51pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/39 "2018-04-20T18:51:28Z")

</div>

> [@CAD97](#):
>
> Did I get this right, @rpjohnst?

Close but not quite. Here's what we'd actually see (simplifying by assuming a `tokio::fs` or something, and adjusting to match the existing APIs):

Fully qualified, forward-compatible syntax:

```rust
let file_a = async { fs::read("fileA") };
let file_b = async { fs::read("fileB") };
let files = await!(join_all(vec![file_a, file_b]));
await!(process(files))

```

Implicit async, explicit await (the main RFC):

```rust
let file_a = fs::read("fileA");
let file_b = fs::read("fileB");
let files = await!(join_all(vec![file_a, file_b]));
await!(process(files))

```

Explicit async, implicit await (this proposal, and the main difference I'm pointing out with your version):

```rust
let file_a = async { fs::read("fileA") };
let file_b = async { fs::read("fileB") };
let files = join_all(vec![file_a, file_b]);
process(files)

```

Aside from the cosmetic changes to make it a more accurate comparison, the third version has a couple of differences:

- `Future::of(async || { .. })` is overkill and is just an async block (as you mention).
- `join_all` can itself be an `async fn` that merely constructs a `JoinAll` and calls `.await()` on it. You could leave it as `join_all(vec![file_a, file_b]).await()` if you want to keep the API the same as today's.

Both of these changes help enable the first version to be forward-compatible with the third version. The transition then becomes "leave `async` blocks as they are, and remove `async!` invocations." There's no need to add `.await()` calls as long as functions like `join_all` are `async`. (A transition to explicit await would go the other way- "remove (some) `async` blocks, leave `async!` invocations.")

---

<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 20, 2018, 7:14pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/40 "2018-04-20T19:14:49Z")

</div>

Hello

I didn’t want to discuss my objections in the RFC, it seemed out of place. But let’s do it here, then.

I agree that the goal of async-await is ergonomics, therefore too much annotation is probably a problem. That can, however, be solved in other ways than pretending that something acts the same (in the syntax) while it doesn’t. One of the things I like about Rust is, it doesn’t paper over what happens. We have explicit heap allocation, for example, while other languages hide this. This makes me feel that I know what is happening in quite a detail and that I can influence it.

The specific points I don’t like about the proposal, and why:

First, I don’t buy the argument of normal function that can do arbitrary bad things. While it is true that in theory, it can ‒ I probably _could_ write a function that moves the current stack into a different OS thread ‒ it is _uncommon_ and you can guess it from the function name. If I have a function called `load_from_file(filename)`, I can be quite confident it will not move me into another thread, that it’ll eventually return control to me and that it’ll not try to lock a mutex I haven’t provided to it. On the other hand, if I call `scheduler::turn()`, I can guess it just _might_ do something interesting, so I’ll think twice about what state I’m in before the call. If the suspension points disappear, _all functions_ are suspects for doing something bad and just reading the code (when doing code review, for example) is not enough to gain any level of reasonable confidence.

Let’s show an example (I’m not looking the exact interface of the sigprocmask binding into Rust, but it changes the masked signals for the current thread).

```rust
let old_mask = sigsetmask(SIG_BLOCK, SIGTERM | SIGQUIT)?; // Wait with the signal until we finish playing with the DB file
do_something_with_db()?;
sigsetmask(SIG_SETMASK, old_mask)?;

```

If the `do_something_with_db` is sync and I further assume that the author of the function was sane not to hide a very complex code to smuggle my stack into another thread (not a big assumption, I guess and if the author had bad intentions, he could crash my program in million other ways), this is OK. However, if it could mean a suspension point, it could set the signal mask for arbitrary other async task and I could restore the mask in a different thread, introducing a very hard to find bug. A hint at the suspension point (maybe just calling it with `-()-` instead of just `()`) would be enough to both prevent this from slipping through code review and from compiling and introducing this bug by making that function async sometime in the future.

The same can be said for holding a mutex for a while. Let’s say I have single-threaded executor, but have other threads I want to sync with. If I hold it across a suspension point, I might get a deadlock, because other instance of the same code will run and will try to get the mutex too ‒ and can’t and it won’t let me run. Again, while in theory a function call could also try to lock the mutex, if it’s a library function to load metadata of a movie from file (something that could in theory be async), because I haven’t given it access to the mutex nor to my other tasks.

Both of these is something one might reasonably want to do in systems language like Rust.

Furthermore, the proposal doesn’t seem to look very _consistent_. OK, async functions have the `::new` function and otherwise await when called directly. I don’t really see how that works, except adding a corner-case somewhere really deep into the language, while some kind of `await!` or operator is _almost_ implementable as an extern crate. But what about integration with futures? Lot’s of library functions will return futures (`TcpListener::accept`, for example). Is that one awaited automatically? If so, who provides the `::new` for it? Does it appear magically?

Furthermore, if it does auto-await in async function, but returns the future outside of it, then `async` is no longer an extention ‒ `unsafe` allows some more things to do inside of it, but the code that compiles outside _does the same_ inside of it. This would be a code that does something else inside and outside. That looks confusing.

If you don’t auto-await the future, then you can only auto-await other async fns. Considering a lot of futures need to be implemented in other ways than an async fn, it’ll cover only small part of cases ‒ maybe 50%? Considering I’ll receive some futures by a parameter (and I’ll have to await them explicitly), some will be stored in some data structure, or receive by a channel, this’ll even lower the percentage of cases when it can be used.

Therefore, the result will be half implicit waiting and half explicit, getting disadvantages of both worlds.

---

<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:** [April 20, 2018, 7:28pm UTC](https://internals.rust-lang.org/t/explicit-future-construction-implicit-await/7344/41 "2018-04-20T19:28:53Z")

</div>

The idea in “explicit async, implicit await” is that you wouldn’t (normally) be calling `-> impl Future<T>` functions. Instead, you call `async -> T` functions. That function can just construct and `.await()` the structure as in `join_all` above.

I think the `fn::new` part of the RFC here as written complicates things, and should just focus on `async { fn }` formulation of the concept.

The hurdle to both solutions is the namability of types for composition and storage of futures. When and where does stuff get pinned in our example, @rpjohnst?

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

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