Skip to content

Add IntoFuture::into_future desugaring #1233

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 22, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/expressions/await-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
> _AwaitExpression_ :\
>    [_Expression_] `.` `await`

*Await expressions* suspend the current computation until the given future is ready to produce a value.
The syntax for an await expression is an expression with a type that implements the [Future] trait, called the *future operand*, then the token `.`, and then the `await` keyword.
An `await` expression is a syntactic construct for suspending a computation
provided by an implementation of `std::future::IntoFuture` until the given
future is ready to produce a value.
The syntax for an await expression is an expression with a type that implements the [`IntoFuture`] trait, called the *future operand*, then the token `.`, and then the `await` keyword.
Await expressions are legal only within an [async context], like an [`async fn`] or an [`async` block].

More specifically, an await expression has the following effect.

1. Evaluate the future operand to a [future] `tmp`;
2. Pin `tmp` using [`Pin::new_unchecked`];
3. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context);
3. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 2;
4. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself.
1. Create a future by calling [`IntoFuture::into_future`] on the future operand.
2. Evaluate the future to a [future] `tmp`;
3. Pin `tmp` using [`Pin::new_unchecked`];
4. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context);
5. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 2;
6. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself.

> **Edition differences**: Await expressions are only available beginning with Rust 2018.

Expand All @@ -29,7 +32,7 @@ Effectively, an await expression is roughly equivalent to the following non-norm

<!-- ignore: example expansion -->
```rust,ignore
match future_operand {
match operand.into_future() {
mut pinned => loop {
let mut pin = unsafe { Pin::new_unchecked(&mut pinned) };
match Pin::future::poll(Pin::borrow(&mut pin), &mut current_context) {
Expand All @@ -53,3 +56,5 @@ The variable `current_context` refers to the context taken from the async enviro
[`poll::Ready`]: ../../std/task/enum.Poll.html#variant.Ready
[async context]: ../expressions/block-expr.md#async-context
[future]: ../../std/future/trait.Future.html
[`IntoFuture`]: ../../std/future/trait.IntoFuture.html
[`IntoFuture::into_future`]: ../../std/future/trait.IntoFuture.html#tymethod.into_future