Basic

A future is a recipe, not a result

The value returned by an async call does nothing until someone runs it. That is the whole surprise of async in Rust, and the surprise is a rule rather than a trap.

What you will see

One line. Every future in a codebase needs a named driver above it.

About 1 min of reading

Try It

Prove a future does nothing

1

Build a future and drop it

printf 'fn main() { let f = do_work(); }\n' > /tmp/a.rs; grep -c await /tmp/a.rs

Before you run it, say out loud what it will print. Then open the answer.

What it prints
0. No await and no spawn means no work happened, even though the file compiles.
2

Drive it to completion

printf 'fn main() { let f = do_work(); run_to_completion(f); }\n' > /tmp/b.rs; grep -c run_to_completion /tmp/b.rs

Before you run it, say out loud what it will print. Then open the answer.

What it prints
1. The driver is the thing that makes the value do work.
3

Name the driver in the file

printf 'driver=run_to_completion\n' >> /tmp/b.rs; tail -1 /tmp/b.rs

Before you run it, say out loud what it will print. Then open the answer.

What it prints
One line. Every future in a codebase needs a named driver above it.

Data Flow

An async call to work
1 The call builds a future
↓
2 The future is handed to a driver
↓
3 The driver runs it to completion
↓
4 The result is read
Why this works
The shape of the mistake

The mistake is a value that is created and dropped. That shape is legal, which is why the mistake survives review.

What makes the intent visible

The await or the spawn written on the same line as the call. A line that only builds a value is a line that does no work.

Examples

Nothing happened

A future that is never driven performs no work. The code compiles, runs, and the file is never written.

Why laziness is the design

Laziness lets the caller decide when work starts. An eager call would start work the caller may want to cancel.

The compiler cannot see the bug

An unused future is a used value. The type system checks the value, not the intent to run it.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Why async exists at all
Previous Lesson
Why async exists at all
Next Lesson
Await compiles to a state machine
Await compiles to a state machine →