{
    "slug": "rust_async_await",
    "term": "Rust async/await",
    "category": "rust",
    "difficulty": "advanced",
    "short": "Rust's async/await syntax builds state-machine futures that run on an executor, enabling concurrency without blocking OS threads.",
    "long": "Rust's async/await lets you write asynchronous code that reads like sequential code while compiling down to efficient state machines. An `async fn` or `async` block returns a value implementing the `Future` trait. A future is lazy: it does nothing until polled. The `.await` operator suspends the current future until the awaited future is ready, yielding control back to the executor so other tasks can make progress on the same thread.\n\nUnlike threads, futures are zero-cost abstractions with no inherent runtime. Rust's standard library defines the `Future` trait and the language provides syntax, but it deliberately ships no executor. You must bring a runtime such as Tokio or async-std to actually drive futures to completion by repeatedly calling `poll`. The runtime also supplies async I/O primitives, timers, and task spawning.\n\nA key mental model: awaiting does not spawn concurrency by itself. `let a = fetch().await; let b = fetch().await;` runs sequentially. To run futures concurrently you combine them with `join!`, `select!`, or spawn separate tasks. Because the compiler transforms async functions into state machines that capture locals across await points, borrowed references held across `.await` must satisfy lifetime and `Send` requirements, which is why some types like `MutexGuard` from `std::sync` cannot be held across awaits in multithreaded runtimes.\n\nError handling uses the normal `Result` and `?` operator inside async functions. Cancellation happens by dropping a future, so any cleanup must be drop-safe rather than relying on code after an await that may never run. Pinning (`Pin`) appears because self-referential state machines must not move in memory once polled; most users rely on `Box::pin` or runtime helpers rather than manipulating `Pin` directly. Mastering async/await means understanding laziness, the missing runtime, concurrent combinators, and the `Send`/lifetime constraints the borrow checker enforces across suspension points.",
    "aliases": [
        "rust futures",
        "async fn rust",
        "tokio async"
    ],
    "tags": [
        "rust",
        "async-await",
        "concurrency",
        "futures",
        "tokio"
    ],
    "misconception": "Calling an async function starts running it immediately, like a background thread. In reality futures are lazy and do nothing until awaited or spawned on an executor.",
    "why_it_matters": "Misunderstanding laziness, missing runtimes, or holding non-Send guards across awaits leads to code that never runs, deadlocks, or fails to compile in production services handling thousands of concurrent connections.",
    "common_mistakes": [
        "Calling an async fn and forgetting to .await or spawn it, so the future never executes.",
        "Awaiting futures sequentially when they could run concurrently with join! or tokio::spawn.",
        "Holding a std::sync::MutexGuard across an .await, causing Send errors or deadlocks under a multithreaded executor.",
        "Doing CPU-heavy blocking work inside an async task and starving the executor instead of using spawn_blocking.",
        "Assuming code after an .await always runs, ignoring that dropping a future cancels it mid-flight."
    ],
    "when_to_use": [
        "Handling many concurrent I/O-bound connections such as HTTP servers or database clients.",
        "Building network services where blocking a thread per request would not scale.",
        "Composing multiple independent I/O operations to run concurrently with join! or select!."
    ],
    "avoid_when": [
        "The workload is purely CPU-bound with no I/O, where threads or rayon are simpler and faster.",
        "A small synchronous CLI tool where adding a runtime is unnecessary complexity.",
        "You only need a single blocking network call and the extra async machinery adds no value."
    ],
    "related": [
        "processes_vs_threads",
        "event_driven",
        "py_generators"
    ],
    "prerequisites": [
        "future",
        "trait",
        "rust_ownership",
        "concurrency",
        "future",
        "trait",
        "rust_ownership",
        "concurrency"
    ],
    "refs": [
        "https://rust-lang.github.io/async-book/",
        "https://doc.rust-lang.org/std/future/trait.Future.html",
        "https://tokio.rs/tokio/tutorial",
        "https://doc.rust-lang.org/reference/expressions/await-expr.html"
    ],
    "bad_code": "use std::sync::Mutex;\nuse std::time::Duration;\n\nasync fn fetch(id: u32) -> u32 { id * 2 }\n\nasync fn run(state: &Mutex<u32>) {\n    // Sequential awaits: these run one after another, not concurrently.\n    let a = fetch(1).await;\n    let b = fetch(2).await;\n\n    // Holding a std::sync guard across .await -> not Send, can deadlock.\n    let mut g = state.lock().unwrap();\n    tokio::time::sleep(Duration::from_millis(10)).await;\n    *g += a + b;\n}\n\nfn main() {\n    let state = Mutex::new(0);\n    // No runtime: this future is never polled, so run() never executes.\n    let _ = run(&state);\n}",
    "good_code": "use tokio::sync::Mutex;\nuse tokio::join;\nuse std::time::Duration;\n\nasync fn fetch(id: u32) -> u32 { id * 2 }\n\nasync fn run(state: &Mutex<u32>) {\n    // Run independent futures concurrently.\n    let (a, b) = join!(fetch(1), fetch(2));\n\n    // Async-aware lock can be held across .await safely.\n    let mut g = state.lock().await;\n    tokio::time::sleep(Duration::from_millis(10)).await;\n    *g += a + b;\n}\n\n#[tokio::main]\nasync fn main() {\n    let state = Mutex::new(0);\n    run(&state).await; // future is actually driven to completion\n    println!(\"{}\", *state.lock().await);\n}",
    "quick_fix": "Bring a runtime (e.g. #[tokio::main]) and ensure every future is awaited or spawned; use join! to run independent futures concurrently.",
    "severity": "medium",
    "effort": "medium",
    "created": "2026-06-04",
    "updated": "2026-06-05",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/rust_async_await",
        "html_url": "https://codeclaritylab.com/glossary/rust_async_await",
        "json_url": "https://codeclaritylab.com/glossary/rust_async_await.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Rust async/await](https://codeclaritylab.com/glossary/rust_async_await) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/rust_async_await"
            }
        }
    }
}