diff --git a/blog/content/second-edition/posts/12-async-await/index.md b/blog/content/second-edition/posts/12-async-await/index.md index b97e0c5e..fd0e1474 100644 --- a/blog/content/second-edition/posts/12-async-await/index.md +++ b/blog/content/second-edition/posts/12-async-await/index.md @@ -488,97 +488,9 @@ Note that this function does not start the execution of the state machine. This ### Pinning - - - - - - - -### The Async Keyword - -The purpose of the async/await pattern is to make working with futures easier. Rust has language-level support for this pattern built on the two keywords `async` and `await`. We will explain them individually, starting with `async`. - -The purpose of the `async` keyword is to turn a synchronous function into an asynchronous function that returns a `Future`: - -```rust -fn synchronous() -> u32 { - 42 -} - -async fn asynchronous() -> u32 { - 42 -} -``` - -While both functions specify a return type of `u32`, the `async` keyword turns the return type of the second function into `impl Future`. So instead of returning an `u32` directly, the `asynchronous` function returns a type that implements the `Future` trait with output type `u32`. We can see this when we try to assign the result to a variable of type `u32`: - -```rust -let val: u32 = asynchronous(); -``` - -The compiler responds with the following error ([try it on the playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=590273d2f4ef75eb890c5354f788e29c)): - -``` -error[E0308]: mismatched types - --> src/main.rs:3:23 - | -3 | let val: u32 = asynchronous(); - | --- ^^^^^^^^^^^^^^ expected `u32`, found opaque type - | | - | expected due to this -... -10 | async fn asynchronous() -> u32 { - | --- the `Output` of this `async fn`'s found opaque type - | - = note: expected type `u32` - found opaque type `impl std::future::Future` -``` - -The relevant part of that error message are the last two lines: It expects an `u32` because of the type annotation, but the function returned an implementation of the `Future` trait instead. - -Of course, changing the return type alone would not work. Instead, the compiler also needs to convert the function body, which is `42` in our case, into a future. Since `42` is not asynchronous, the compiler just generates a future that returns the result on the first `poll`. The generated code _could_ look something like this: - -```rust -struct GeneratedFuture; - -impl Future for GeneratedFuture { - type Output = u32; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll { - Poll::Ready(42) - } -} - -fn asynchronous() -> impl Future { - GeneratedFuture -} -``` - -Instead of returning `u32`, the `asynchronous` function now returns an instance of a new `GeneratedFuture` struct. This struct implements the `Future` trait by returning `Poll::Ready(42)` on `poll`. The `42` is the body of `asynchronous` in this case. - -Note that this is just an example implementation. The actual code generated by the compiler uses a much more powerful approach, which we will explain in a moment. - -In addition to `async` futures, Rust also supports `async` blocks: - -```rust -let future = async { - 42 -}; -``` - -The `future` variable also has the type `impl Future` in this case. The generated code is very similar to the `async fn`, only without a function call: `let future = GeneratedFuture;`. - -We now know roughly what the `async` keyword does, but we still don't know why it's useful yet. After all, there is no advantage of returning a `impl Future` instead of returning the `u32` directly. To answer this question, we have to explore different ways to work with futures. - - - - -#### Await - -### Generators - - +### Executors + +## Implementation