# A final proposal for await syntax

**URL:** <https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021>\
**Category:** language design\
**Created:** [May 6, 2019, 2:36pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021 "2019-05-06T14:36:19Z")\
**Posts on this page:** 20\
**Page:** 12

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [May 14, 2019, 4:28am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/232 "2019-05-14T04:28:47Z")

</div>

> [@aglx](#):
>
> Most of the arguments pro or against each variant of await in _A_ should directly translate to an argument pro or against the respective variant of try in _B_ and vice-versa.

The main difference is that Rust's `await` is similar to `await` in other languages, so using the same term helps with learnability. In contrast, the old `try!()` had completely different semantics from `try` in other languages\*, so using the name was not only unhelpful but actively harmful to learnability. Indeed, that was part of the motivation for getting rid of it, and [soon the name `try` will be reused](https://github.com/rust-lang/rfcs/blob/master/text/2388-try-expr.md) for something that _is_ similar to `try` in other languages.

Another difference might be that `await` will likely be somewhat less common than `?`, though that's questionable (it depends a lot on the type of codebase).

That said, you do have a point.

\* Aside from Swift, which added a `try` keyword with similar semantics to `try!()`, around the same time Rust was moving away from it. ¯\_(ツ)\_/¯

---

<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:** [May 14, 2019, 6:11am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/233 "2019-05-14T06:11:01Z")

</div>

> [@rpjohnst](#):
>
> The mandatory/optional delimiters option offers a neat solution here. `await(foo)?`

And since I don't remember seeing the point:

I want to avoid a situation where `await (expr)?` is not semantically equivalent to `await expr?`. (For any trailing continuation, not just `?`.) Even with rustfmt pushing towards function formatting, someone's bound to write the equivalent of `await (a + b).c` and be very surprised.

It's similar to why I don't like `await { }`: `await` doesn't take a block like that syntax suggests, but rather a value. If we had to do mandatory delimiters, I'd prefer `await[..]` because it's the least likely to be confused with `await ([..])`, and even is forward compatible with `await[,]` for awaiting multiple futures in parallel 🙃

---

<div class="post-metadata">

**Author:** ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)\
**Post date:** [May 15, 2019, 1:26am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/234 "2019-05-15T01:26:15Z")

</div>

> [@rpjohnst](#):
>
> The mandatory/optional delimiters option offers a neat solution here. `await(foo)?` is simultaneously much closer to `await foo` , and much closer to _other uses of `?`_ . I suspect we could be much happier with it in the medium-to-long term than `(await foo)?` .
> 
> This is similar, I think, to your inclination toward `await!(foo)` , but with more willingness to let it be a “real” syntax.

I don't really agree with this. To put it simply, I think `await $block` is just too verbose, if not _the_ most verbose syntax of all `await` syntaxes hitherto. Compare this with `?` which is an unobtrusive syntax.

I suspect we would commonly get things like:

```rust
let foo = await {
    bar_computation()
}?;

```

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [May 15, 2019, 5:02am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/235 "2019-05-15T05:02:52Z")

</div>

> [@rpjohnst](#):
>
> `await(foo)?` is simultaneously much closer to `await foo` , and much closer to _other uses of `?`_ . I suspect we could be much happier with it in the medium-to-long term than `(await foo)?` .

I disagree that we'd be happier with it, because it's inconsistent with the other prefix keywords:

- `return(foo)` is actively linted against
- `return(foo)?` is `return (foo?)`, so I think it'd be weird for `await(foo)?` to be `(await(foo))?`
- and `break` works the same as `return` here

> [@rpjohnst](#):
>
> If we don’t want a generalized postfix `.keyword` syntax, _why would we want a specific one_ ?

I think that's easy, because it's the first one which both takes only a value (not a block) and returns something interesting (not `()` or `!`).

(To elaborate, even if you `{ ... }.await`, the await is still getting a value, not a block, because it doesn't treat the block as a closure and doesn't have scopeful effects on the block, etc.)

Also, it's an unsubstantiated leap from "in the near term" to "we don't want". C# will have had `switch foo { ... }` for 19 years before it gets `foo switch { ... }` -- could I see rust getting `.match` in the next 19 years even though I agree that it won't be "in the near term"? Absolutely. (I could easily see it happening in _much_ fewer than that, plausibly for the next edition. But not _this_ year.)

---

<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:** [May 15, 2019, 6:11am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/236 "2019-05-15T06:11:12Z")

</div>

> [@scottmcm](#):
>
> I disagree that we’d be happier with it, because it’s inconsistent with the other prefix keywords:

If `await(foo)`'s inconsistency with other prefix keywords is a problem, then so is `foo.await`'s inconsistency with other postfix stuff, IMO.

So the comparison I'm making here is a bit more nuanced- `await(foo)` is much closer _on the whole_ to the constellation of other syntax, even though it still doesn't fit perfectly:

- It's prefix like other keywords.
- It matches the expectations of _two_ mental models- "await is control flow" (all prefix) _and_ "await is a call" (all parentheses).
- It has parentheses like other things that bind tighter than `?`- function calls and macro invocations.
- It also behaves like function calls in terms of borrowing, because it evaluates to a temporary.

On the other hand, `foo.await` is quite a bit different, carving out a whole new space in almost every aspect:

- There is currently no such thing as a postfix keyword at all, with or without a dot.
- It's closest syntactically to field access, but differs significantly in semantics from it.
- It's closer semantically to a method call, but differs in syntax by lacking parentheses and not having an equivalent prefix form.

> [@scottmcm](#):
>
> Also, it’s an unsubstantiated leap from “in the near term” to “we don’t want”.

This feels like it's twisting my words. You can add "in the near term" to _both_ halves of my sentence and get the same meaning- I'd strongly prefer we approach any dot-postfix syntax holistically, and avoid a situation where we can't make them all consistent.

It's a fair point that `await` is the first keyword to take a value _and_ evaluate to a value. But I've seen little-to-no consideration of what else might land in this category and how that might interact with our choice of syntax here.

For example, suppose we get generator arguments. While `await` can arguably be seen as an operation _on_ the value, the same cannot be said of `yield`, which a) does its work completely independent of the value or its type, and b) evaluates to a value completely unrelated to its input.

Maybe in the end we won't care whether `await` and `yield` feel at all similar. But I'd rather we decide that on purpose than stumble into it, and any other unforeseen dilemmas, without giving ourselves the chance.

---

<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:** [May 15, 2019, 7:06pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/238 "2019-05-15T19:06:55Z")

</div>

> [@rpjohnst](#):
>
> So the comparison I’m making here is a bit more nuanced- `await(foo)` is much closer _on the whole_ to the constellation of other syntax, even though it still doesn’t fit perfectly:

I think this is indeed an interesting argument and I think worth adding to some summary (I am trying to create a "master summary", but I've not had time to finish up yet, and I would include it there).

I don't agree with your conclusion, though: let me try to elaborate why. I guess perhaps it's an _uncanny valley_ argument -- to me, having `await(foo)` be _so close_ to other keywords and yet with this critical difference is quite surprising. It differs in two respects:

- It requires a (non-block) delimiters
- It has unusual precedence

That is, `return(foo)?` would be parsed as `return ((foo)?)`. But `await(foo)?` would be parsed as `(await (foo))?`.

That seems bad and quite surprising to me -- more so that `foo.await`. I guess it's like this: `foo.await` feels like something where you might say "oh, that's unusual", but you'd have no real doubt as to when it takes effect. I can't say the same for `await (foo)?`, which I consider quite visibly ambiguous.

If we're going to use mandatory delimiters, then, this leads us to either `await[foo]` -- which to me is quite "foreign", this is not indexing, and indeed shares many of the same concerns as `foo.await` -- or to `await { foo }`. Here, I agree with @Centril that this feels clumsy and verbose, and ... kind of surprising. We don't expect you to "await" a long block of stuff.

I think you can see a similar tension in `unsafe { }` today. The original intention, I believe, was that one would use `unsafe { ... }` on a long block of instructions. But it has become a more prevalent style to push `unsafe { }` down to the actual operation that requires unsafe, and in that case, the `{ }` feel unnatural -- we've kept them because it feels important to be clear about the scope of unsafe (though I'm not sure that's a good argument, I might be inclined to reconsider that point).

---

<div class="post-metadata">

**Author:** ![insanitybit](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/insanitybit/32/4389_2.png) [@insanitybit](https://internals.rust-lang.org/u/insanitybit)\
**Post date:** [May 15, 2019, 9:00pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/239 "2019-05-15T21:00:17Z")

</div>

It is well worn territory that the rust team is already aware of (I have discussed it at the SF Meetup, this is an acknowledged issue) that users do not participate in RFCs because they are extremely noisy and hard to follow, among many other reasons (self esteem, lack of familiarity with the process, etc).

I have no interest in an argument to the contrary since it’s proven every single time a syntax feature comes out.

How should they fix it? No idea, but it’s their responsibility to do so.

As for how someone may not have seen the conversation, I absolutely do not think that `.await` was a widely published option before the last month. I read rust news every day, I’m pretty active in the community, and it was new to me.

---

<div class="post-metadata">

**Author:** ![theduke](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/theduke/32/2782_2.png) [@theduke](https://internals.rust-lang.org/u/theduke)\
**Post date:** [May 15, 2019, 9:21pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/240 "2019-05-15T21:21:47Z")

</div>

Over the last few days I have written some code with about a 300 occurrences of `.await` (with the somewhat decent `compat` features of futures 0.3) , and I’d like to share some personal observations.

I’ll cover ease of use, observability, oddity factor and language switching cost.

## Utility and ease of use

My opinion that a postfix syntax is very desirable has been reaffirmed. `.await` is very easy to type and makes writing code really fluid and convenient. It prevents the need for introducing unneeded locals, and also avoids falling back to combinators.

With `.await` chaining, applying await becomes really effortless and is very nice to write. Something that’s usually not exactly a strength of Rust, with it’s tendency for boilerplate.

For example, in Javascript I would sometimes use `Promise` combinators to prevent locals.

```javascript
// Use of combinators.
async function load() {
  return fetch(...)
    .then(r => r.json())
    .then(response => response.data);
}

// With locals
async function load() {
  const res = await fetch(..);
  const json = await res.json();
  return json.data;
}

```

The equivalent comparison in Rust would be:

```rust
// With combinators
async fn load() -> Result<Value, Error> {
  reqwest::get(..)
    .and_then(|res| res.json())
    .map(|value| value.data)
    .await
}

// With locals.
async fn load() -> Result<Value, Error> {
  let res = reqwest::get(..).await?;
  let json = res.json().await?;
  Ok(json.data)
}

// With chaining.
async fn load() -> Result<Value, Error> {
  reqwest::get(...)
    .await?
    .json()
    .await?
    .data
}

```

One might argue that it’s almost too easy to use. (See below).

## Observability

Combined with how easy it is to apply, I noticed that I really stop thinking about if I really want to suspend here or not. I just slap a `.await` at the end and move on.

This is often fine, but it also can cause problems. I stumbled over two such examples:

- I introduced a bug because I was incrementing a `AtomicU64` after a suspension point, which really needed to be incremented before hand because I appended a `.await` on to a function call without thinking about it
- I made a particular function too slow because three things that were supposed to happen in parallel happened one after the other, again because I just took the convenient route of `.await` without thinking about it.

You could of course argue that this is just my mindlessness at fault.

But I do think a noisier syntax that looks less like just a field access causes a bit more of a mental stopgap that makes you consider if suspending right there is really what you want.

The noiselessness of the syntax can therefore both be seen as a feature and as a detriment , IMO.

Also, without syntax highlighting, `.await` becomes very easy to miss. This is real annoyance in eg `git diff`. `.await` looks just like a field access and doesn’t stand out at all. This is alleviated a bit by the fact that `.await?` will be very common, which stands out more, but it’s still an issue for me personally.

Even with highlighting, it still is weird for me to associate it with control flow rather than just a cheap field access. This is something that could become better with time, if you are writing a lot of Rust code.

## Oddity factor

I did notice that `.await` becomes natural to use very quickly. I stopped thinking about it quickly when **writing** code.

Yet, when reading the code rather then writing, it still looks very odd to me that `value.await` is not just a field access but actually suspends the function.

I just have trouble separating field access from the control flow that await introduces, and I don’t think that is something that would go away with time.

As I mentioned in a previous post, I’m really worried about this syntax creating a permanent weirdness factor in the language, since `DOT` can not be a general pipeline operator (unless we also get universal function call syntax). I still hold the view that `DOT` is a very questionable choice for this regardless, and it’s doubtful to me that this syntax could be accepted for other language constructs like `.match`, `.if`, …

Future consistency of the language should be an important concern.

Also, the syntax will be very odd for users not familiar with Rust or who write little Rust code. (The same would be somewhat true for any kind of postfix syntax though, I reckon) This leads to my last point.

## Language Switching

One very real detriment I discovered is switching between languages and familiarity concerns.

While writing code over the last few days, I was often switching between Javascript and Rust, and this was a real headache for me. I kept trying to apply prefix await in Rust, and after a while, then started to use `.await` in Javascript, which the obvious results.

I believe this will be a real issue for developers using multiple languages, because you constantly need to readjust and move code around.

Almost every language that supports `async/await` has the same prefix syntax for it, and Rust will be the odd one out. This could become a real annoyance for devs that don’t write Rust often, or write multiple languages with async await on a regular basis.

The mental and familiarity cost is very real and should not be dismissed lightly.

## Conclusion

I assume that, with the lang team having consensus and the syntax already being in master, the decision is pretty much made.

Personally, after writing a pretty decent amount of code and extensive consideration, I have to say that it is a decision I can live with, but not one I would personally make.

I still believe introducing the standard prefix syntax, and then working on a postfix pipelining would be the wiser long term choice, due to three primary reasons, mostly outlined above.

- long term language consistency
- clear distiction of concepts (field access vs control flow)
- cross language familiarity (With prefix await available, devs could always use the familiar and common syntax, with a more rusty a postfix variant being available for those that want it)

---

<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:** [May 15, 2019, 9:44pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/241 "2019-05-15T21:44:02Z")

</div>

> [@theduke](#):
>
> Over the last few days I have written some code with about a 300 occurrences of `.await` (with the somewhat decent `compat` features of futures 0.3) , and I’d like to share some personal observations.

Thanks for the feedback. Quite interesting.

---

<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:** [May 15, 2019, 11:43pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/243 "2019-05-15T23:43:22Z")

</div>

> [@theduke](#):
>
> unless we also get universal function call syntax

We have universal function call syntax (UFCS). That's what allows you to do `Type::method(this)`. What we don't have is universal method call syntax, which would allow you to do `this.module::free_fn()`.

> [@theduke](#):
>
> Language Switching

I can vouch for language switching being a big deal. I wrote primarily Kotlin for a good two years or more, and it always takes be a long time to switch back to writing Java. And now that I've written primarily Rust for about two years, I'm actually in a similar position for Kotlin.

Language switching has a cost. It's a decent goal to minimize the cost when you're advertising a new language, but it'll always be there, so optimizing for it seems like a goal of little importance.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [May 15, 2019, 11:45pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/244 "2019-05-15T23:45:15Z")

</div>

Thanks for trying it out!

> [@theduke](#):
>
> The noiselessness of the syntax can therefore both be seen as a feature and as a detriment , IMO.

This is a great point, and also a similarity to `?`. We've seen a variety of [PRs for try\_fold](https://github.com/rust-lang/rust/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aclosed+try_fold) which often end up having subtle before/after-the-return bugs.

Any thoughts on how hard it is to tell based on the surrounding code whether you're in a place where "just slap `await` or `?` on everything" is probably fine, or where it's a more complex situation that needs careful inspection? I've found `?` way easier than exception-safety because there _is_ that marker, even though it's subtle.

The example in there reminded me that I was wondering whether formatting `.await` like other postfix operations will help emphasize that it's _not_ a field access. Something like

```cs
async fn load() -> Result<Value, Error> {
  reqwest::get(...).await?
    .json().await?
    .data
}

```

Where the `.data` is distinguished by the layout too.

---

<div class="post-metadata">

**Author:** ![theduke](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/theduke/32/2782_2.png) [@theduke](https://internals.rust-lang.org/u/theduke)\
**Post date:** [May 16, 2019, 12:16am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/245 "2019-05-16T00:16:50Z")

</div>

> [@CAD97](#):
>
> We have universal function call syntax (UFCS). That’s what allows you to do `Type::method(this)` . What we don’t have is universal method call syntax, which would allow you to do `this.module::free_fn()` .

I always found this naming convention wrong/up side down, since "UFCS" gives me a way to call a _method_ (or "associated function") with a different syntax, while "UMCS" let's me call _functions_ with a different syntax.

For example **D** also calls "UMCS" [UFCS](https://tour.dlang.org/tour/en/gems/uniform-function-call-syntax-ufcs) aka uniform function call syntax.

The [Wikipedia](https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax) article defines it this way, and even criticizes Rust for it's naming. (which is a bit weird actually)

> [@CAD97](#):
>
> Language switching has a cost. It’s a decent goal to minimize the cost when you’re advertising a new language, but it’ll always be there, so optimizing for it seems like a goal of little importance.

I disagree that it is of "little importance" because `await` is a popular feature in other languages and not being compatible has a considerable cost for learnability and can play a role in a language choice for adopters. I'm not saying that it should be the deciding factor, and I did mention that postfix is very desirable. But it is a decision with consequences. The problem is somewhat exacerbated by being the same keyword, but used differently.

> [@scottmcm](#):
>
> this is a great point, and also a similarity to `?` .

The situation with `?` is different to me because `?` was new, dedicated syntax with no previous equivalent in the language (post 1.0). It's also a noticeable sigil so it stands out even w/o highlighting.

The equivalent comparison would be introducing postfix try.

Eg:

```rust
async fn load() -> Result<Value, Error> {
  reqwest::get()
    .await
    .try
    .json()
    .await
    .try
    .data
}

```

I find this really cryptic.

Let's go one step further:

```rust
async fn load(key: String) -> Result<String, Error> {
  is_cached(&key)
  .try
  .if { from_cache(&key) } else { from_db(&key).await }
  .try
  .data
  .field
  .match {
     Enum::A(x) => x + 1,
     Enum::B(x) => x * 1,
  }
  .to_string()
}

```

My main objection is really about mixing together two distinct concepts in the same syntax.

---

<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:** [May 16, 2019, 1:00am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/246 "2019-05-16T01:00:42Z")

</div>

> [@theduke](#):
>
> I always found this naming convention wrong/up side down, since “UFCS” gives me a way to call a _method_ (or “associated function”) with a different syntax, while “UMCS” let’s me call _functions_ with a different syntax.

(This isn't exactly on topic, but:

UFCS (unified function calling syntax) allows you to call anything like a function, as if it were a function, with function calling syntax. Thus it being UFCS.

The same for UMCS: calling things that aren't methods as if they were methods.)

---

<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:** [May 16, 2019, 4:21am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/247 "2019-05-16T04:21:27Z")

</div>

> [@nikomatsakis](#):
>
> I don’t agree with your conclusion, though: let me try to elaborate why. I guess perhaps it’s an _uncanny valley_ argument – to me, having `await(foo)` be _so close_ to other keywords and yet with this critical difference is quite surprising. It differs in two respects:
> 
> - It requires a (non-block) delimiters
> - It has unusual precedence
> 
> That is, `return(foo)?` would be parsed as `return ((foo)?)` . But `await(foo)?` would be parsed as `(await (foo))?` .
> 
> That seems bad and quite surprising to me – more so that `foo.await` . I guess it’s like this: `foo.await` feels like something where you might say “oh, that’s unusual”, but you’d have no real doubt as to when it takes effect. I can’t say the same for `await (foo)?` , which I consider quite visibly ambiguous.

I might agree with the uncanny valley argument, if we intended there to be a space between the keyword and the delimiters. But `some_function (foo)?`, with a space, is just as visibly ambiguous and something we avoid. It's unidiomatic in `f(x)` languages, and rustfmt doesn't even have an option for it.

For that matter, `return(foo)?` looks nearly as ambiguous in the other direction. While some styles in other languages (e.g. C) do use `return(`, they never have any reason to put anything after the `)`, and so this relatively rare style doesn't seem to cause problem there like it would for us.

So to me this is really a question of whether people will expect there to be a space, simply because `await` is a keyword. I suspect that if they are introduced to it without, as `await(foo)?`, that problem simply won't come up.

I also suspect this will help when scanning code, a situation when you mostly see spacing and punctuation rather than text. For example, `&mumble(foo)?` behaves consistently across `await`, `yield`, and `some_function`. In contrast, `&foo.mumble?` does not.

---

<div class="post-metadata">

**Author:** ![steven099](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steven099/32/3871_2.png) [@steven099](https://internals.rust-lang.org/u/steven099)\
**Post date:** [May 16, 2019, 4:42am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/248 "2019-05-16T04:42:16Z")

</div>

> [@theduke](#):
>
> Combined with how easy it is to apply, I noticed that I really stop thinking about if I really want to suspend here or not. I just slap a `.await` at the end and move on.
> 
> This is often fine, but it also can cause problems. [...]

Just a thought experiment on designing with preventing these problems as the main consideration, something like an await rebinding statement would force a very explicit consideration of when you want / need to await futures.

```rust
async fn async_foo() -> Result<i64, Error> {
    let a = async_bar();
    let b = async_baz();
    await (a, try b);
    // use a and b
    ...
}

```

This forces you to await futures in a separate statement from where they are created because they have to be assigned to a variable first. Await takes a list of bindings, where the new binding is assigned the result of awaiting the previous binding with the same name. I'm using an invented `try` binding modifier as a way to apply `?` to the result of awaiting the future before binding it to the variable. By using two bindings, I'm essentially joining the futures so they can execute concurrently, This construction also means that `await` is always the first token on a line under normal code formatting.

I think this definitely goes too far the other way, I just wanted to think about what the feature might look like if the intent was to help you avoid the problems you encountered as much as possible. Obviously, as you've shown in your examples, there are good use cases for being able to chain awaits.

---

<div class="post-metadata">

**Author:** ![spease](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/spease/32/3042_2.png) [@spease](https://internals.rust-lang.org/u/spease)\
**Post date:** [May 16, 2019, 7:40am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/249 "2019-05-16T07:40:02Z")

</div>

Maybe this is a dumb idea, probably already considered, but what about `someVar:await` ?

That is, just use a single colon instead of the double colon usually used to denote associated types etc. This does mean it’s replicating the manual type specification operator, but imho the behavior of await would end up being closer to that than a field or a method (as suggested by a .)

EDIT: Another couple ideas I could think of that seem within hailing distance of reasonable while trying to preserve the meaning of . for fields/methods would be `someVar#await` or `someVar!!await`.

`someVar await` would at least have the upside of being consistent with other keyword denotation but I can see how this would get confusing.

To me the most confusing thing is that the proposal seems to require memorization of which connecting character is used for which associated struct entities. Methods and members use ., associated types use ::, etc.

If everything used ., that’d be easier to remember than mapping the type of the entity to the operator you need to use. It’s also easier to type.

But Rust has seemed to opt for distinguishing what syntax type that entities are, and I’m used to there being a very strict expectation that things that look like fields are only fields (no properties like other languages).

Sorry for the imprecise jargon and minimal formatting, typing this on my phone atm.

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [May 16, 2019, 8:41am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/250 "2019-05-16T08:41:45Z")

</div>

See:

> [@Idea: universal pipelining (a.k.a. making @await generic)](https://internals.rust-lang.org/t/idea-universal-pipelining-a-k-a-making-await-generic/9973):
>
> In “[Await Syntax Discussion Summary](https://internals.rust-lang.org/t/await-syntax-discussion-summary/9914)” it was [proposed](https://internals.rust-lang.org/t/await-syntax-discussion-summary/9914/116) to allow keywords to be used after ., for example: await future match foo { ... } // will be equivalent to future.await foo.match {...} Personally I am not fond of using . in such way, partially because it’s too similar to magic attributes and I think will be quite confusing for newcommers. But the idea on another hand is quite appealing. So how about introducing sigil for pipelining which (eventually) will work with keywords (accepting one …

It was discussed many times and was mentioned in the final proposal (though very briefly) and in the @nikomatsakis's [summary](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/172).

---

<div class="post-metadata">

**Author:** ![OZ\_](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oz_/32/4298_2.png) [@OZ\_](https://internals.rust-lang.org/u/OZ_)\
**Post date:** [May 16, 2019, 11:47am UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/251 "2019-05-16T11:47:46Z")

</div>

New revolutionary idea for await syntax:

`foo...await...?bar()`

You even read this with pause!

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [May 16, 2019, 12:01pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/252 "2019-05-16T12:01:22Z")

</div>

[That](https://github.com/rust-lang/rust/issues/57640#issuecomment-455818177) is [very](https://github.com/rust-lang/rust/issues/57640#issuecomment-457415027) much [not](https://github.com/rust-lang/rust/issues/57640#issuecomment-463651241) a revolutionary idea.

---

<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:** [May 16, 2019, 12:22pm UTC](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021/253 "2019-05-16T12:22:29Z")

</div>

> [@theduke](#):
>
> My opinion that a postfix syntax is very desirable has been reaffirmed. `.await` is very easy to type and makes writing code really fluid and convenient.

I can second this from my own (limited) experience. Writing `.await?` felt very natural to me, perhaps because I've become accustomed to writing `?` -- it feels like "discharging" the extra details from calling the function so I can get at the thing I want. I think that going back to insert an `await` at the start of the line would have felt rather different.

> [@theduke](#):
>
> I introduced a bug because I was incrementing a `AtomicU64` after a suspension point, which really needed to be incremented before hand because I appended a `.await` on to a function call without thinking about it

I find this interesting and i'd like to drill into it a bit:

- First, I'd be curious if you are able to point to the code in question (is it public?).
  - What is this atomic increment for? What data is being communicated here?

- Second, I'd like to know the order of events.
  - Did you add the increment before or after the suspension point?
  - When did you find the bug and how long did it take you to diagnose the problem?

In asking about the point of the code, it's because I'm trying to compare this to my own experiences in writing blocking threaded code. It seems like the `.await` was some kind of synchronization point that might read this counter, and I'm trying to understand how that came to be.

With regard to the order of events, I'm trying to separate out two scenarios:

- If you had to interrupt your editing to insert an `await` in prefix position, you might have noticed the order vis a vis the increment _at the time_;
- or, you would have seen it earlier when debugging?

I have not used async fns a lot in practice, but my assumption is that -- over time -- one gets quite accustomed to inserting an `await` and it becomes second nature, in which case these same sorts of errors might occur. It seems like you do have a lot of such experience -- can you think of times, say when writing JavaScript code, that you detected subtle ordering bugs early as a result of having to interrupt your flow and insert an `await`?

Might it be possible that stylistic guidelines, such as writing `.await` into a distinct let binding, would be helpful here too?

> [@theduke](#):
>
> This is real annoyance in eg `git diff` . `.await` looks just like a field access and doesn’t stand out at all. This is alleviated a bit by the fact that `.await?` will be very common, which stands out more, but it’s still an issue for me personally.

I'd like to drill a bit into why it is important for it to stand out in git diffs. One thing I can imagine is that, during code review, it might help reviewers to spot ordering conflicts like the one above? This seems like it might be true, although it's very hard to judge the "magnitude" of such an effect -- if the reviewer knows that ordering is sensitive in that function, and in particular that the ordering is important with respect to an await, it seems likely that they can look for it either way. If they don't know, they don't know. So I guess the difference might be in some case where they are not actively thinking about it but the visibility of an added await makes them aware.

> [@theduke](#):
>
> One very real detriment I discovered is switching between languages and familiarity concerns.

This is an interesting point I personally had not considered before. I'm not sure how to "weigh" it overall but I'm glad you brought it up.

[Previous page](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021.md?page=11)

[Next page](https://internals.rust-lang.org/t/a-final-proposal-for-await-syntax/10021.md?page=13)
