Skip to content

Commit 17e9fbc

Browse files
MajorBreakfastboats
authored andcommitted
?-operator and control-flow constructs in async blocks
1 parent 57707fc commit 17e9fbc

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

text/0000-async_await.md

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ let my_future = async {
129129
};
130130
```
131131

132-
This form is equivalent to an immediately-invoked `async` closure.
132+
This form is almost equivalent to an immediately-invoked `async` closure.
133133
That is:
134134

135135
```rust
@@ -142,7 +142,9 @@ async { /* body */ }
142142

143143
except that control-flow constructs like `return`, `break` and `continue` are
144144
not allowed within `body` (unless they appear within a fresh control-flow
145-
context like a closure or a loop).
145+
context like a closure or a loop). How the `?`-operator and early returns
146+
should work inside async blocks has not yet been established (see unresolved
147+
questions).
146148

147149
As with `async` closures, `async` blocks can be annotated with `move` to capture
148150
ownership of the variables they close over.
@@ -464,11 +466,11 @@ As noted in the main text, `async` blocks and `async` closures are closely
464466
related, and are roughly inter-expressible:
465467

466468
```rust
467-
// equivalent
469+
// almost equivalent
468470
async { ... }
469471
(async || { ... })()
470472

471-
// equivalent
473+
// almost equivalent
472474
async |..| { ... }
473475
|..| async { ... }
474476
```
@@ -479,7 +481,7 @@ We could consider having only one of the two constructs. However:
479481
such closures are often useful for higher-order constructs like constructing a
480482
service.
481483

482-
- There's a strong reason to have `async` blocks: the initialization pattern
484+
- There's a strong reason to have `async` blocks: The initialization pattern
483485
mentioned in the RFC text, and the fact that it provides a more
484486
direct/primitive way of constructing futures.
485487

@@ -604,3 +606,33 @@ across yield points.
604606
We could also, with an annotation, typecheck an async function to confirm that it
605607
does not contain any references across yield points, allowing it to implement
606608
`Unpin`. The annotation to enable this is left unspecified for the time being.
609+
610+
## `?`-operator and control-flow constructs in async blocks
611+
612+
This RFC does not propose how the `?`-operator and control-flow constructs like
613+
`return`, `break` and `continue` should work inside async blocks.
614+
615+
It was discussed that async blocks should act as a boundary for the
616+
`?`-operator. This would make them suitable for fallible IO:
617+
618+
```rust
619+
let reader: AsyncRead = ...;
620+
async {
621+
let foo = await!(reader.read_to_end())?;
622+
Ok(foo.parse().unwrap_or(0))
623+
}: impl Future<Output = io::Result<u32>>
624+
```
625+
626+
Also, it was discussed to allow the use of `break` to return early from
627+
an async block:
628+
629+
```rust
630+
async {
631+
if true { break "foo" }
632+
}
633+
```
634+
635+
The use of the `break` keyword instead of `return` could be beneficial to
636+
indicate that it applies to the async block and not its surrounding function. On
637+
the other hand this would introduce a difference to closures and async closures
638+
which make use the `return` keyword.

0 commit comments

Comments
 (0)