diff --git a/src/01_getting_started/02_why_async.md b/src/01_getting_started/02_why_async.md index 5e2272b5..d81f7584 100644 --- a/src/01_getting_started/02_why_async.md +++ b/src/01_getting_started/02_why_async.md @@ -8,7 +8,7 @@ thread. In a typical threaded application, if you wanted to download two different webpages at the same time, you would spread the work across two different threads, like this: -```rust +```rust,ignore {{#include ../../examples/01_02_why_async/src/lib.rs:get_two_sites}} ``` @@ -22,7 +22,7 @@ to eliminate. We can rewrite the function above using Rust's `async`/`.await` notation, which will allow us to run multiple tasks at once without creating multiple threads: -```rust +```rust,ignore {{#include ../../examples/01_02_why_async/src/lib.rs:get_two_sites_async}} ``` diff --git a/src/01_getting_started/04_async_await_primer.md b/src/01_getting_started/04_async_await_primer.md index b08eab20..7952cfda 100644 --- a/src/01_getting_started/04_async_await_primer.md +++ b/src/01_getting_started/04_async_await_primer.md @@ -9,14 +9,14 @@ blocked `Future`s will yield control of the thread, allowing other To create an asynchronous function, you can use the `async fn` syntax: -```rust -async fn do_something() { ... } +```rust,edition2018 +async fn do_something() { /* ... */ } ``` The value returned by `async fn` is a `Future`. For anything to happen, the `Future` needs to be run on an executor. -```rust +```rust,edition2018 {{#include ../../examples/01_04_async_await_primer/src/lib.rs:hello_world}} ``` @@ -29,16 +29,16 @@ other tasks to run if the future is currently unable to make progress. For example, imagine that we have three `async fn`: `learn_song`, `sing_song`, and `dance`: -```rust -async fn learn_song() -> Song { ... } -async fn sing_song(song: Song) { ... } -async fn dance() { ... } +```rust,ignore +async fn learn_song() -> Song { /* ... */ } +async fn sing_song(song: Song) { /* ... */ } +async fn dance() { /* ... */ } ``` One way to do learn, sing, and dance would be to block on each of these individually: -```rust +```rust,ignore {{#include ../../examples/01_04_async_await_primer/src/lib.rs:block_on_each}} ``` @@ -48,7 +48,7 @@ we can sing it, but it's possible to dance at the same time as learning and singing the song. To do this, we can create two separate `async fn` which can be run concurrently: -```rust +```rust,ignore {{#include ../../examples/01_04_async_await_primer/src/lib.rs:block_on_main}} ``` diff --git a/src/01_getting_started/05_http_server_example.md b/src/01_getting_started/05_http_server_example.md index cea2bbcc..90581759 100644 --- a/src/01_getting_started/05_http_server_example.md +++ b/src/01_getting_started/05_http_server_example.md @@ -15,14 +15,14 @@ Let's add some dependencies to the `Cargo.toml` file: Now that we've got our dependencies out of the way, let's start writing some code. We have some imports to add: -```rust +```rust,ignore {{#include ../../examples/01_05_http_server/src/lib.rs:imports}} ``` Once the imports are out of the way, we can start putting together the boilerplate to allow us to serve requests: -```rust +```rust,ignore {{#include ../../examples/01_05_http_server/src/lib.rs:boilerplate}} ``` @@ -35,7 +35,7 @@ You can also inspect the request itself, which contains information such as the request URI, HTTP version, headers, and other metadata. For example, we can print out the URI of the request like this: -```rust +```rust,ignore println!("Got request at {:?}", req.uri()); ``` @@ -47,14 +47,14 @@ request to another website using Hyper's HTTP client. We start by parsing out the URL we want to request: -```rust +```rust,ignore {{#include ../../examples/01_05_http_server/src/lib.rs:parse_url}} ``` Then we can create a new `hyper::Client` and use it to make a `GET` request, returning the response to the user: -```rust +```rust,ignore {{#include ../../examples/01_05_http_server/src/lib.rs:get_request}} ``` diff --git a/src/02_execution/02_future.md b/src/02_execution/02_future.md index 6326f3d2..7db17767 100644 --- a/src/02_execution/02_future.md +++ b/src/02_execution/02_future.md @@ -30,7 +30,7 @@ must register `wake` to be called when data becomes ready on the socket, which will tell the executor that our future is ready to make progress. A simple `SocketRead` future might look something like this: -```rust +```rust,ignore {{#include ../../examples/02_02_future_trait/src/lib.rs:socket_read}} ``` @@ -39,7 +39,7 @@ operations without needing intermediate allocations. Running multiple futures at once or chaining futures together can be implemented via allocation-free state machines, like this: -```rust +```rust,ignore {{#include ../../examples/02_02_future_trait/src/lib.rs:join}} ``` @@ -47,7 +47,7 @@ This shows how multiple futures can be run simultaneously without needing separate allocations, allowing for more efficient asynchronous programs. Similarly, multiple sequential futures can be run one after another, like this: -```rust +```rust,ignore {{#include ../../examples/02_02_future_trait/src/lib.rs:and_then}} ``` @@ -56,12 +56,12 @@ control flow without requiring multiple allocated objects and deeply nested callbacks. With the basic control-flow out of the way, let's talk about the real `Future` trait and how it is different. -```rust +```rust,ignore {{#include ../../examples/02_02_future_trait/src/lib.rs:real_future}} ``` The first change you'll notice is that our `self` type is no longer `&mut self`, -but has changed to `Pin<&mut Self>`. We'll talk more about pinning in [a later +but has changed to `Pin<&mut Self>`. We'll talk more about pinning in [a later section][pinning], but for now know that it allows us to create futures that are immovable. Immovable objects can store pointers between their fields, e.g. `struct MyFut { a: i32, ptr_to_a: *const i32 }`. Pinning is necessary diff --git a/src/02_execution/03_wakeups.md b/src/02_execution/03_wakeups.md index 94a6c4e1..3cdcc033 100644 --- a/src/02_execution/03_wakeups.md +++ b/src/02_execution/03_wakeups.md @@ -34,13 +34,13 @@ thread to communicate that the timer has elapsed and the future should complete. We'll use a shared `Arc>` value to communicate between the thread and the future. -```rust +```rust,ignore {{#include ../../examples/02_03_timer/src/lib.rs:timer_decl}} ``` Now, let's actually write the `Future` implementation! -```rust +```rust,ignore {{#include ../../examples/02_03_timer/src/lib.rs:future_for_timer}} ``` @@ -55,7 +55,7 @@ being polled. Finally, we need the API to actually construct the timer and start the thread: -```rust +```rust,ignore {{#include ../../examples/02_03_timer/src/lib.rs:timer_new}} ``` diff --git a/src/02_execution/04_executor.md b/src/02_execution/04_executor.md index 29b70037..71ef1d34 100644 --- a/src/02_execution/04_executor.md +++ b/src/02_execution/04_executor.md @@ -32,7 +32,7 @@ futures-preview = "=0.3.0-alpha.17" Next, we need the following imports at the top of `src/main.rs`: -```rust +```rust,ignore {{#include ../../examples/02_04_executor/src/lib.rs:imports}} ``` @@ -47,7 +47,7 @@ Tasks themselves are just futures that can reschedule themselves, so we'll store them as a future paired with a sender that the task can use to requeue itself. -```rust +```rust,ignore {{#include ../../examples/02_04_executor/src/lib.rs:executor_decl}} ``` @@ -56,7 +56,7 @@ This method will take a future type, box it and put it in a FutureObj, and create a new `Arc` with it inside which can be enqueued onto the executor. -```rust +```rust,ignore {{#include ../../examples/02_04_executor/src/lib.rs:spawn_fn}} ``` @@ -70,7 +70,7 @@ the `waker_ref` or `.into_waker()` functions to turn an `Arc` into a `Waker`. Let's implement `ArcWake` for our tasks to allow them to be turned into `Waker`s and awoken: -```rust +```rust,ignore {{#include ../../examples/02_04_executor/src/lib.rs:arcwake_for_task}} ``` @@ -78,7 +78,7 @@ When a `Waker` is created from an `Arc`, calling `wake()` on it will cause a copy of the `Arc` to be sent onto the task channel. Our executor then needs to pick up the task and poll it. Let's implement that: -```rust +```rust,ignore {{#include ../../examples/02_04_executor/src/lib.rs:executor_run}} ``` @@ -86,7 +86,7 @@ Congratulations! We now have a working futures executor. We can even use it to run `async/.await` code and custom futures, such as the `TimerFuture` we wrote earlier: -```rust +```rust,edition2018,ignore {{#include ../../examples/02_04_executor/src/lib.rs:main}} ``` diff --git a/src/02_execution/05_io.md b/src/02_execution/05_io.md index d28f65b9..4639ac68 100644 --- a/src/02_execution/05_io.md +++ b/src/02_execution/05_io.md @@ -3,7 +3,7 @@ In the previous section on [The `Future` Trait], we discussed this example of a future that performed an asynchronous read on a socket: -```rust +```rust,ignore {{#include ../../examples/02_02_future_trait/src/lib.rs:socket_read}} ``` @@ -26,9 +26,9 @@ a thread to block on multiple asynchronous IO events, returning once one of the events completes. In practice, these APIs usually look something like this: -```rust +```rust,ignore struct IoBlocker { - ... + /* ... */ } struct Event { @@ -41,7 +41,7 @@ struct Event { impl IoBlocker { /// Create a new collection of asynchronous IO events to block on. - fn new() -> Self { ... } + fn new() -> Self { /* ... */ } /// Express an interest in a particular IO event. fn add_io_event_interest( @@ -54,10 +54,10 @@ impl IoBlocker { /// which an event should be triggered, paired with /// an ID to give to events that result from this interest. event: Event, - ) { ... } + ) { /* ... */ } /// Block until one of the events occurs. - fn block(&self) -> Event { ... } + fn block(&self) -> Event { /* ... */ } } let mut io_blocker = IoBlocker::new(); @@ -80,7 +80,7 @@ such as sockets that can configure callbacks to be run when a particular IO event occurs. In the case of our `SocketRead` example above, the `Socket::set_readable_callback` function might look like the following pseudocode: -```rust +```rust,ignore impl Socket { fn set_readable_callback(&self, waker: Waker) { // `local_executor` is a reference to the local executor. diff --git a/src/03_async_await/01_chapter.md b/src/03_async_await/01_chapter.md index 419b53bc..3d4d72f5 100644 --- a/src/03_async_await/01_chapter.md +++ b/src/03_async_await/01_chapter.md @@ -12,7 +12,7 @@ code to make progress while waiting on an operation to complete. There are two main ways to use `async`: `async fn` and `async` blocks. Each returns a value that implements the `Future` trait: -```rust +```rust,edition2018,ignore {{#include ../../examples/03_01_async_await/src/lib.rs:async_fn_and_block_examples}} ``` @@ -29,7 +29,7 @@ Unlike traditional functions, `async fn`s which take references or other non-`'static` arguments return a `Future` which is bounded by the lifetime of the arguments: -```rust +```rust,edition2018,ignore {{#include ../../examples/03_01_async_await/src/lib.rs:lifetimes_expanded}} ``` @@ -43,7 +43,7 @@ One common workaround for turning an `async fn` with references-as-arguments into a `'static` future is to bundle the arguments with the call to the `async fn` inside an `async` block: -```rust +```rust,edition2018,ignore {{#include ../../examples/03_01_async_await/src/lib.rs:static_future_with_borrow}} ``` @@ -57,7 +57,7 @@ closures. An `async move` block will take ownership of the variables it references, allowing it to outlive the current scope, but giving up the ability to share those variables with other code: -```rust +```rust,edition2018,ignore {{#include ../../examples/03_01_async_await/src/lib.rs:async_move_examples}} ``` diff --git a/src/04_pinning/01_chapter.md b/src/04_pinning/01_chapter.md index d4af93ed..cb761dd3 100644 --- a/src/04_pinning/01_chapter.md +++ b/src/04_pinning/01_chapter.md @@ -12,9 +12,9 @@ Pinning makes it possible to guarantee that an object won't ever be moved. To understand why this is necessary, we need to remember how `async`/`.await` works. Consider the following code: -```rust -let fut_one = ...; -let fut_two = ...; +```rust,edition2018,ignore +let fut_one = /* ... */; +let fut_two = /* ... */; async move { fut_one.await; fut_two.await; @@ -24,7 +24,7 @@ async move { Under the hood, this creates an anonymous type that implements `Future`, providing a `poll` method that looks something like this: -```rust +```rust,ignore // The `Future` type generated by our `async { ... }` block struct AsyncFuture { fut_one: FutOne, @@ -69,7 +69,7 @@ is able to successfully complete. However, what happens if we have an `async` block that uses references? For example: -```rust +```rust,edition2018,ignore async { let mut x = [0; 128]; let read_into_buf_fut = read_into_buf(&mut x); @@ -80,7 +80,7 @@ async { What struct does this compile down to? -```rust +```rust,ignore struct ReadIntoBuf<'a> { buf: &'a mut [u8], // points to `x` below } @@ -118,22 +118,22 @@ used as futures, and both implement `Unpin`. For example: -```rust +```rust,edition2018,ignore use pin_utils::pin_mut; // `pin_utils` is a handy crate available on crates.io // A function which takes a `Future` that implements `Unpin`. -fn execute_unpin_future(x: impl Future + Unpin) { ... } +fn execute_unpin_future(x: impl Future + Unpin) { /* ... */ } -let fut = async { ... }; +let fut = async { /* ... */ }; execute_unpin_future(fut); // Error: `fut` does not implement `Unpin` trait // Pinning with `Box`: -let fut = async { ... }; +let fut = async { /* ... */ }; let fut = Box::pin(fut); execute_unpin_future(fut); // OK // Pinning with `pin_mut!`: -let fut = async { ... }; +let fut = async { /* ... */ }; pin_mut!(fut); execute_unpin_future(fut); // OK ``` diff --git a/src/05_streams/01_chapter.md b/src/05_streams/01_chapter.md index e241e165..22d39788 100644 --- a/src/05_streams/01_chapter.md +++ b/src/05_streams/01_chapter.md @@ -3,7 +3,7 @@ The `Stream` trait is similar to `Future` but can yield multiple values before completing, similar to the `Iterator` trait from the standard library: -```rust +```rust,ignore {{#include ../../examples/05_01_streams/src/lib.rs:stream_trait}} ``` @@ -12,6 +12,6 @@ the `futures` crate. It will yield `Some(val)` every time a value is sent from the `Sender` end, and will yield `None` once the `Sender` has been dropped and all pending messages have been received: -```rust +```rust,edition2018,ignore {{#include ../../examples/05_01_streams/src/lib.rs:channels}} ``` diff --git a/src/05_streams/02_iteration_and_concurrency.md b/src/05_streams/02_iteration_and_concurrency.md index 4c0ebc26..3efdc875 100644 --- a/src/05_streams/02_iteration_and_concurrency.md +++ b/src/05_streams/02_iteration_and_concurrency.md @@ -9,7 +9,7 @@ Unfortunately, `for` loops are not usable with `Stream`s, but for imperative-style code, `while let` and the `next`/`try_next` functions can be used: -```rust +```rust,edition2018,ignore {{#include ../../examples/05_02_iteration_and_concurrency/src/lib.rs:nexts}} ``` @@ -19,6 +19,6 @@ writing async code in the first place. To process multiple items from a stream concurrently, use the `for_each_concurrent` and `try_for_each_concurrent` methods: -```rust +```rust,edition2018,ignore {{#include ../../examples/05_02_iteration_and_concurrency/src/lib.rs:try_for_each_concurrent}} ``` diff --git a/src/06_multiple_futures/02_join.md b/src/06_multiple_futures/02_join.md index 3d5c3817..4b15fc2d 100644 --- a/src/06_multiple_futures/02_join.md +++ b/src/06_multiple_futures/02_join.md @@ -8,7 +8,7 @@ futures to complete while executing them all concurrently. When performing multiple asynchronous operations, it's tempting to simply `.await` them in a series: -```rust +```rust,edition2018,ignore {{#include ../../examples/06_02_join/src/lib.rs:naiive}} ``` @@ -18,7 +18,7 @@ futures are ambiently run to completion, so two operations can be run concurrently by first calling the each `async fn` to start the futures, and then awaiting them both: -```rust +```rust,edition2018,ignore {{#include ../../examples/06_02_join/src/lib.rs:other_langs}} ``` @@ -28,7 +28,7 @@ This means that the two code snippets above will both run concurrently. To correctly run the two futures concurrently, use `futures::join!`: -```rust +```rust,edition2018,ignore {{#include ../../examples/06_02_join/src/lib.rs:join}} ``` @@ -45,7 +45,7 @@ has returned an `Err`. Unlike `join!`, `try_join!` will complete immediately if one of the subfutures returns an error. -```rust +```rust,edition2018,ignore {{#include ../../examples/06_02_join/src/lib.rs:try_join}} ``` @@ -53,6 +53,6 @@ Note that the futures passed to `try_join!` must all have the same error type. Consider using the `.map_err(|e| ...)` and `.err_into()` functions from `futures::future::TryFutureExt` to consolidate the error types: -```rust +```rust,edition2018,ignore {{#include ../../examples/06_02_join/src/lib.rs:try_join_map_err}} ``` diff --git a/src/06_multiple_futures/03_select.md b/src/06_multiple_futures/03_select.md index 3e1bfb7d..832b0369 100644 --- a/src/06_multiple_futures/03_select.md +++ b/src/06_multiple_futures/03_select.md @@ -3,7 +3,7 @@ The `futures::select` macro runs multiple futures simultaneously, allowing the user to respond as soon as any future completes. -```rust +```rust,edition2018 {{#include ../../examples/06_03_select/src/lib.rs:example}} ``` @@ -27,7 +27,7 @@ if none of the other futures are ready. being `select`ed over have completed and will no longer make progress. This is often handy when looping over a `select!`. -```rust +```rust,edition2018 {{#include ../../examples/06_03_select/src/lib.rs:default_and_complete}} ``` @@ -58,7 +58,7 @@ which implement this trait or have been wrapped using `.fuse()` will yield `FusedFuture` futures from their `.next()` / `.try_next()` combinators. -```rust +```rust,edition2018 {{#include ../../examples/06_03_select/src/lib.rs:fused_stream}} ``` @@ -75,7 +75,7 @@ Note the use of the `.select_next_some()` function. This can be used with `select` to only run the branch for `Some(_)` values returned from the stream, ignoring `None`s. -```rust +```rust,edition2018 {{#include ../../examples/06_03_select/src/lib.rs:fuse_terminated}} ``` @@ -85,6 +85,6 @@ to the one above, but will run each copy of `run_on_new_num_fut` to completion, rather than aborting them when a new one is created. It will also print out a value returned by `run_on_new_num_fut`. -```rust +```rust,edition2018 {{#include ../../examples/06_03_select/src/lib.rs:futures_unordered}} ``` diff --git a/src/07_workarounds/02_return_type.md b/src/07_workarounds/02_return_type.md index 4a2a795e..1d97b1a3 100644 --- a/src/07_workarounds/02_return_type.md +++ b/src/07_workarounds/02_return_type.md @@ -55,7 +55,7 @@ In practice, this means that returning `Box` objects from an This code will result in an error: -``` +```rust,edition2018,ignore async fn x() -> Box { Box::new("foo") } @@ -63,7 +63,7 @@ async fn x() -> Box { This issue can be worked around by manually casting using `as`: -``` +```rust,edition2018 async fn x() -> Box { Box::new("foo") as Box } diff --git a/src/07_workarounds/03_err_in_async_blocks.md b/src/07_workarounds/03_err_in_async_blocks.md index 9bf36759..3e947986 100644 --- a/src/07_workarounds/03_err_in_async_blocks.md +++ b/src/07_workarounds/03_err_in_async_blocks.md @@ -7,7 +7,10 @@ This can cause the compiler to fail to infer the error type of the For example, this code: -```rust +```rust,edition2018 +# struct MyError; +# async fn foo() -> Result<(), MyError> { Ok(()) } +# async fn bar() -> Result<(), MyError> { Ok(()) } let fut = async { foo().await?; bar().await?; @@ -32,7 +35,10 @@ to explicitly specify the return type of an `async` block. To work around this, use the "turbofish" operator to supply the success and error types for the `async` block: -```rust +```rust,edition2018 +# struct MyError; +# async fn foo() -> Result<(), MyError> { Ok(()) } +# async fn bar() -> Result<(), MyError> { Ok(()) } let fut = async { foo().await?; bar().await?; diff --git a/src/07_workarounds/04_send_approximation.md b/src/07_workarounds/04_send_approximation.md index 7312f164..385b5e98 100644 --- a/src/07_workarounds/04_send_approximation.md +++ b/src/07_workarounds/04_send_approximation.md @@ -19,7 +19,7 @@ struct NotSend(Rc<()>); Variables of type `NotSend` can briefly appear as temporaries in `async fn`s even when the resulting `Future` type returned by the `async fn` must be `Send`: -```rust +```rust,edition2018 # use std::rc::Rc; # #[derive(Default)] # struct NotSend(Rc<()>); @@ -39,14 +39,19 @@ fn main() { However, if we change `foo` to store `NotSend` in a variable, this example no longer compiles: -```rust +```rust,edition2018 # use std::rc::Rc; # #[derive(Default)] # struct NotSend(Rc<()>); +# async fn bar() {} async fn foo() { let x = NotSend::default(); bar().await; } +# fn require_send(_: impl Send) {} +# fn main() { +# require_send(foo()); +# } ``` ``` @@ -85,14 +90,19 @@ a block scope encapsulating any non-`Send` variables. This makes it easier for the compiler to tell that these variables do not live across an `.await` point. -```rust +```rust,edition2018 # use std::rc::Rc; # #[derive(Default)] # struct NotSend(Rc<()>); +# async fn bar() {} async fn foo() { { let x = NotSend::default(); } bar().await; } +# fn require_send(_: impl Send) {} +# fn main() { +# require_send(foo()); +# } ``` diff --git a/src/07_workarounds/05_recursion.md b/src/07_workarounds/05_recursion.md index 84d3ee2e..dee60fd7 100644 --- a/src/07_workarounds/05_recursion.md +++ b/src/07_workarounds/05_recursion.md @@ -4,7 +4,11 @@ Internally, `async fn` creates a state machine type containing each sub-`Future` being `.await`ed. This makes recursive `async fn`s a little tricky, since the resulting state machine type has to contain itself: -```rust +```rust,edition2018 +# async fn step_one() { /* ... */ } +# async fn step_two() { /* ... */ } +# struct StepOne; +# struct StepTwo; // This function: async fn foo() { step_one().await; @@ -48,6 +52,6 @@ Unfortunately, compiler limitations mean that just wrapping the calls to to make `recursive` into a non-`async` function which returns a `.boxed()` `async` block: -```rust +```rust,edition2018 {{#include ../../examples/07_05_recursion/src/lib.rs:example}} ```