Rust — Reference
Source: https://doc.rust-lang.org/book/
Rust
- Created: 2010 by Graydon Hoare at Mozilla; 1.0 released 2015-05-15
- Latest stable: Rust 1.95.0 (2026-04-16); 6-week release cycle
- Paradigms: multi-paradigm — imperative, functional, generic, concurrent, low-level systems
- Typing: static, strong, nominal, with Hindley-Milner-flavored inference; traits (type classes); ADTs (enum/struct)
- Memory: borrow-checked (ownership + lifetimes, no GC); manual via
unsaferaw pointers - Compilation: AOT to native via LLVM; monomorphized generics; produces single static binary by default
- Primary domains: systems, embedded, WebAssembly, CLI tools, blockchain, game/graphics engines, databases, browser engines (Servo, Stylo), OS development (Linux kernel, Windows components)
- Official docs: https://doc.rust-lang.org/
1. At a glance
- Stewarded by the Rust Foundation (independent non-profit since 2021, with Platinum members Amazon/Google/Microsoft/Meta/Huawei/Mozilla); technical governance via Project teams (compiler, lang, libs, infra, dev-tools, release, moderation) + RFC process on GitHub.
- One main implementation: rustc (LLVM-based, written in Rust, with the codegen backend pluggable). gccrs (GCC frontend, separately implemented — reached self-hosting feature parity goals in GCC 15) and
rustc_codegen_cranelift(faster debug builds, no LLVM dep) emerging.rustc_codegen_gccuses libgccjit for backend (parity work ongoing). - Editions: 2015, 2018, 2021, 2024 (default since Rust 1.85, Feb 2025) — opt-in syntactic/semantic shifts; libraries from different editions interoperate freely.
edition = "2024"inCargo.toml. - Compiler messages and tooling (cargo, rustup, clippy, rust-analyzer) are best-in-class — diagnostic spans, hint suggestions, machine-applicable fixes via
--fix. - 6-week release cadence (same as Chrome/Firefox); LTS-like patterns through company-level toolchain pinning (Google/AWS/Microsoft typically lag 2-3 releases).
- Rust Survey 2025 (annual): ~95% of users use stable, ~30% nightly; Tokio + serde + clap dominate; “compile times” remains top pain point.
2. Getting started
-
Install:
rustupis the official toolchain manager:curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh(orwinget install Rustlang.Rustup). Configurescargo+rustc+rust-std+rust-docs+clippy+rustfmtper channel. -
Version manager: rustup itself:
rustup install stable|beta|nightly,rustup default stable,rustup target add wasm32-unknown-unknown,rustup component add rust-src. Override per-dir withrust-toolchain.toml:[toolchain] channel = "1.83.0" components = ["rustfmt", "clippy", "rust-src"] targets = ["wasm32-wasip1", "x86_64-unknown-linux-musl"] -
Hello, world:
fn main() { println!("Hello, world!"); }Create + run:
cargo new hello && cd hello && cargo run.Cargo.tomlgenerated:[package] name = "hello" version = "0.1.0" edition = "2024" rust-version = "1.85" [dependencies] -
Project layout:
Cargo.toml(manifest) +Cargo.lock(locked deps; commit for binaries, optional for libs);src/main.rs(binary entry point) orsrc/lib.rs(library entry point);src/bin/<name>.rsfor additional binaries;tests/(integration tests, each file its own crate),benches/(Criterion lives here),examples/(runnable withcargo run --example foo). Workspaces (top-levelCargo.tomlwith[workspace]) for multi-crate monorepos — sharetarget/directory and dependency graph. -
Build tool:
cargois everything:cargo build,run,test(orcargo nextest run),bench,doc,publish,add,update,tree,clippy,fmt,check(type-check without codegen — fastest feedback),expand(macro output),audit,deny,machete. Crates from crates.io (108k+ as of 2026); private registries via Artifactory, Cloudsmith, Shipyard, JFrog. Workspace-level[workspace.dependencies]and[workspace.lints](1.74+) keep monorepos consistent. -
REPL/playground: Rust Playground (https://play.rust-lang.org/) — share with shortlink, run on stable/beta/nightly, see ASM/MIR/LLVM-IR output.
evcxr(Jupyter kernel + REPL — interactive Rust with reloadable cells, used by data-science folks).miriplayground for visualizing UB.rust.godbolt.org(Compiler Explorer) for cross-version disassembly.
3. Basics
- Primitives:
bool,char(4-byte Unicode scalar value, not a byte), signed/unsigned intsi8..i128/isize,u8..u128/usize,f32/f64,()unit type,!never type (in return/expr positions). Literals:0x,0b,0o,_separators (1_000_000), suffixes (42u32,3.14f64), byte literalsb'x', raw byte stringsbr"...". - Variables:
let x = 1;(immutable by default),let mut x,const FOO: u32 = 42;(compile-time, inlined at each use site),static FOO: u32 = 42;(single memory location). Shadowing allowed (let x = x + 1;re-binds, can change type). Block-scoped, expression-oriented (last expression without;returns).let _ = exprto explicitly discard. - Control flow:
if/else(an expression —let x = if cond { 1 } else { 2 };),match(exhaustive pattern-matching, the workhorse — compiler checks all variants covered),loop(infinite, canbreak value),while,while let Some(x) = it.next(),for x in iter,break/continuewith labels ('outer: loop { ... break 'outer; }),if let/let else(1.65+) for one-arm match. Patterns: literal, range, struct, enum, tuple, slice ([head, .., tail]), or-patterns (A | B), guards (Some(x) if x > 5), bindings (x @ 1..=5). - Functions:
fn f(x: i32) -> i32 { x + 1 }. No default args / no overloading (use builder pattern orOption<T>). Closures|x| x + 1(auto-traitsFn/FnMut/FnOncedetermined by capture mode). Generics + traits substitute for overloading. First-class viafnpointers (zero-cost, no captures), closures (impl Fn, may capture),dyn Trait(vtable, type-erased). Async closures (async |x| { ... }) stable in 1.85+. - Strings:
&str(string slice, UTF-8, fat pointer = ptr + len) and owningString(heap, growable Vecguaranteed UTF-8). Format with format!("{x}")/println!; raw stringsr"...",r#"..."#(any number of#to disambiguate from"in content). No interpolation outside macros.String::from,.to_string(),.to_owned(),.into()all convert&str → String.OsString/OsStrfor OS-native (Windows UTF-16, Unix bytes);Path/PathBuffor filesystem paths;CString/CStrfor NUL-terminated C interop. - Collections: arrays
[T; N](stack-allocated fixed size), slices&[T]/&mut [T](fat pointer view),Vec<T>(heap-allocated growable),HashMap<K, V>(SipHash 1-3 default — DoS resistant but slower; swap forahash/fxhashif input is trusted) /BTreeMap<K, V>(ordered, B-tree, better cache behavior than tree map),HashSet<T>/BTreeSet<T>,VecDeque<T>(ring buffer),BinaryHeap<T>(max-heap by default), tuples(T1, T2),Option<T>(sum type for nullability — no null pointers),Result<T, E>(sum type for fallible operations). Smart pointers:Box<T>(single-owner heap),Rc<T>(single-threaded ref-counted),Arc<T>(thread-safe ref-counted),Cell<T>(interior mutability forCopytypes),RefCell<T>(runtime borrow-checked interior mutability),Mutex<T>,RwLock<T>,OnceLock<T>/OnceCell<T>(1.70+ — lazy init),LazyLock<T>/LazyCell<T>(1.80+).
4. Intermediate
- Generics & traits:
fn f<T: Trait>(x: T)orwhere T: Trait. Trait objectsdyn Trait(vtable; only object-safe traits — no generic methods, noSelfreturns by value). Associated types (type Item;in trait), Generic Associated Types (GATs, stable 1.65 —type Item<'a>;for lifetime-parameterized return types from a trait). Higher-ranked trait boundsfor<'a> Fn(&'a T) -> .... Lifetimes are part of types:&'a str,fn f<'a>(x: &'a str) -> &'a str. Variance is computed structurally —&'a Tis covariant in'a,&'a mut Tis invariant. Default type parameters<T = String>. Opaque types viaimpl Traitin arg or return position. - Modules/packages: crate = compilation unit; module tree via
mod foo;(loads fromfoo.rsorfoo/mod.rs) ormod foo { ... }(inline),pub/pub(crate)/pub(super)/pub(in crate::path)for graduated visibility. Cargo packages contain one or more crates (one library + multiple binaries + tests + benches + examples) and are published to crates.io. Workspaces ([workspace]in top-levelCargo.toml) sharetarget/andCargo.lock. - Error handling:
Result<T, E>+?operator for propagation (auto-converts viaFrom<E1> for E2).Option<T>for absence.panic!for unrecoverable bugs (can unwind or abort based onpanic =profile). Libraries usethiserror(derive macro forError+Display); apps useanyhow(anyhow::Result<T>=Result<T, anyhow::Error>+.context(...)for stack-like attached info);miettefor rustc-quality diagnostics;color-eyrefor prettier panic backtraces;eyreas anyhow alternative with custom reports. - Concurrency:
std::thread::spawn+ scoped threads (std::thread::scope, 1.63 — can borrow from caller’s stack), channels (std::sync::mpsc— single-producer single-consumer-ish; for mpmc usecrossbeam-channelorflumeortokio::sync::broadcast),Mutex<T>/RwLock<T>/Arc<T>,std::sync::atomic(withOrdering::{Relaxed, Acquire, Release, AcqRel, SeqCst}),std::sync::Barrier,OnceLock/LazyLock,parking_lotcrate (faster, smaller Mutex/RwLock). Async:async fn+.await(compiler desugars to state machines implementingFuture); requires a runtime — Tokio is dominant (multi-threaded work-stealing); smol, glommio, monoio (thread-per-core, io_uring on Linux). Async sync primitives:tokio::sync::Mutex/RwLock/Semaphore/Notify/watch/broadcast/mpsc/oneshot. - I/O & networking:
std::fs,std::io(Read/Writetraits +BufReader/BufWriter— buffer your I/O!),std::net(TCP/UDP),std::process. Async I/O via Tokio (tokio::fs,tokio::net::TcpListener,tokio::io::AsyncReadExt/AsyncWriteExt). For HTTP client: reqwest (most popular), ureq (sync, no Tokio), hyper (low-level — what reqwest is built on). Server-side: hyper + axum/actix-web. - Stdlib highlights:
Iterator(the most powerful trait —map/filter/collect/fold/scan/flat_map/zip/chain/take/skip/step_by/enumerate/peekable/fuse/inspect/by_ref+ 80 more, all lazy until terminalcollect/sum/count/fold),From/Into(infallible conversion)/TryFrom/TryInto(fallible),Display/Debug({}vs{:?}),Default,Clone(explicit deep copy)/Copy(memcpy semantics),Drop(destructor),Deref/DerefMut(smart pointer auto-coercion),IntoIterator/FromIterator,Eq/Ord/Hash.std::collections,std::sync,std::env,std::process,std::time(Instant,Duration),std::path(Path/PathBuf),std::ffi(CStr/CString/OsStr/OsString).
5. Advanced
- Memory & ownership: every value has exactly one owner; borrows are either one mutable or many shared (the borrow-check rule); lifetimes encode reference validity.
Droptrait runs on scope exit. No GC, no runtime memory tracking. NLL (Non-Lexical Lifetimes) makes borrows scope-tight. Polonius (next-gen borrow checker, in nightly + opt-in 1.83+) accepts strictly more programs — particularly around conditional borrows; targeting stabilization 2026-27. - Concurrency deep dive:
Send(transferable across threads) +Sync(shareable across threads) auto-traits enforce thread safety at compile time.Pin<T>/Unpinfor self-referential types (used by async). Lock-free viastd::sync::atomic. Async runtimes: Tokio’s work-stealing scheduler, scoped tasks, structured concurrency (cancellation,JoinSet,task::AbortHandle).std::thread::scope(1.63+) gives borrow-checked thread spawning that can’t outlive borrows. - FFI/interop:
extern "C" fnfor C ABI;bindgengenerates Rust bindings from C headers,cbindgengenerates C headers from Rust.cxx(David Tolnay) for C++ interop (safe bidirectional) — production at Mozilla (Servo, Firefox), Google (Chromium), in the Linux kernel.autocxx(Google) extends cxx with auto-generation.pyo3+maturinfor Python (used by Pydantic, Polars, ruff).napi-rsfor Node.js.uniffifor cross-lang bindings (Mozilla; generates Kotlin, Swift, Python, Ruby from a single UDL).diplomatfor FFI-friendly idiomatic APIs across many targets. WASM:wasm-bindgen+wasm-packfor browsers;wasi-sdkandcargo-componentfor the Component Model + WIT (WebAssembly Interface Types). - Reflection: none at runtime (no RTTI). Substitute:
std::any::TypeId/Anyfor downcasting,Debugfor printing, derive macros for compile-time codegen.bevy_reflectprovides runtime reflection in the Bevy ecosystem;facet(Amos) explores a general-purpose reflection-without-derive design. - Performance tooling:
cargo bench+ Criterion (statistical benchmarks with regression detection),cargo flamegraph,samply(cross-platform sampling profiler, Firefox Profiler UI),perf, valgrind/cachegrind,cargo-llvm-lines(codegen size — find generic instantiation explosions),cargo-bloat(binary size — what’s taking space),hyperfine(CLI bench),heaptrack/bytehound(memory profilers),cargo-nextest(parallel test runner, 50-60% faster thancargo test),cargo-mutants(mutation testing),cargo-fuzz+libFuzzer+afl.rs(fuzzing). Compile flags:--release,RUSTFLAGS=-C target-cpu=native,lto = "fat"or"thin",codegen-units = 1inCargo.toml(slower compile, faster code),panic = "abort"(smaller binary, no unwinding tables). PGO + BOLT supported viacargo-pgo.cargo-flamegraphfor one-line CPU flamegraphs. - Compile-time tooling:
cargo-sweep(clean old artifacts),sccache(Mozilla, distributed compile cache),cargo-chef(Docker layer caching),craneliftbackend (-Zcodegen-backend=cranelift, nightly) — 30% faster debug builds, used by Cloudflare. Watch crate count: each new dep adds to incremental compile time.
6. God mode
- Macros: declarative
macro_rules! foo { ($x:expr) => { ... } }— pattern-matched token transformations; procedural macros — derive, attribute, function-like; receiveTokenStream, returnTokenStream. Built withsyn(parser) +quote(quote! { ... }template) +proc-macro2(cross-versionTokenStream). Inspect output withcargo expand. Famous proc-macros:#[derive(Serialize, Deserialize)](serde),#[tokio::main],#[wasm_bindgen],#[sqlx::query!](compile-time SQL checks),#[bitflags]. unsafeRust: unlocks raw pointers (*const T/*mut T), unchecked indexing, callingunsafe fn, mutating statics, implementingunsafetraits, dereferencing pointers,mem::transmute. TheRustonomiconis the spec;miriinterprets MIR to detect UB inunsafecode (out-of-bounds, use-after-free, invalidtransmute, data races, alignment violations). Run withcargo +nightly miri test.cargo-carefulruns with extra checks.- Lifetimes deep: variance (covariant/contravariant/invariant), HRTBs (
for<'a> ...),'static, lifetime elision rules,PhantomData<T>for declaring variance/drop semantics on zero-sized types.PhantomPinnedfor explicit!Unpin. - Zero-sized types (ZSTs): unit
(), empty structs, marker types — take 0 bytes;Vec<()>is just a length counter. Used heavily for type-state patterns (Door<Open>/Door<Closed>), unit-struct policy parameters, marker traits. Pin/Unpinand async internals:Future::pollreturnsPoll<T>; async fns desugar to a state-machine struct with each.awaitbecoming a state.Pinenforces self-referential safety. Wakers + Tasks + Executors form the runtime.async fnin traits stable since 1.75 (static dispatch only);RPITIT(return-positionimpl Traitin traits) stable 1.75;dynasync traits require crates likeasync-traitor the boxed-future workaround. Async closures stable in 1.85+ (async |x| { ... }syntax).no_std: disable libstd for embedded / kernels; opt intoalloc(forBox/Vec/Stringagainst a global allocator) or stay pure (coreonly). Targets likethumbv7em-none-eabihffor Cortex-M,riscv32imac-unknown-none-elffor RISC-V,x86_64-unknown-uefifor UEFI apps.- Custom allocators:
#[global_allocator] static A: MyAlloc = MyAlloc;(e.g., mimalloc, jemallocator, tikv-jemallocator, snmalloc-rs); allocator API for per-collection allocators (Allocatortrait, stable asallocator_api2shim). - MIR inspection:
cargo +nightly rustc -- -Zunpretty=mir(or=hir,=hir-tree,=ast). Cranelift backend for fast debug.cargo asm/cargo-show-asmto view generated assembly per function. - Embedded HAL:
embedded-hal1.0 (stable Jan 2024) crate trait ecosystem — drivers written once work across vendors; RTIC (Real-Time Interrupt-driven Concurrency) and Embassy async runtimes for microcontrollers; probe-rs for flashing/debugging with cargo-embed/cargo-flash; defmt for low-overhead logging; vendor HALs: esp-hal (Espressif official, supersedes esp-rs), nrf-hal, rp-hal (Raspberry Pi RP2040), stm32-rs. - Cargo build scripts (
build.rs) — compile C dependencies viacccrate, generate code, set link flags, conditionally compile viacargo:rustc-cfg=. Custom Cargo subcommands: any binary namedcargo-fooonPATHbecomescargo foo. - Specialization (unstable nightly), const generics (stable +
feature(generic_const_exprs)for arithmetic), const evaluation, GATs (stable 1.65), async traits in traits (1.75 stable for static dispatch, dyn dispatch via crate).let chainsstabilized 1.83.let-elsestable 1.65. Never type!partially stable (function returns, exhaustive match arms). - Rust for Linux: merged in kernel 6.1 (Dec 2022), driver support growing — Apple AGX GPU driver, Nova Nvidia driver in nightly, Asahi Linux contributions; some maintainer drama 2024-25 around the C/Rust boundary. By 2026, Rust-written drivers are routine in mainline.
Trait & type pattern catalog
// Newtype for type safety
struct UserId(u64);
struct OrderId(u64);
fn lookup(u: UserId, o: OrderId) { /* can't accidentally swap */ }
// Type-state pattern with PhantomData
use std::marker::PhantomData;
struct Door<State>(PhantomData<State>);
struct Open; struct Closed;
impl Door<Closed> { fn open(self) -> Door<Open> { Door(PhantomData) } }
impl Door<Open> { fn close(self) -> Door<Closed> { Door(PhantomData) } }
// Builder pattern
#[derive(Default)]
struct ServerBuilder { port: Option<u16>, host: Option<String> }
impl ServerBuilder {
fn port(mut self, p: u16) -> Self { self.port = Some(p); self }
fn host(mut self, h: impl Into<String>) -> Self { self.host = Some(h.into()); self }
fn build(self) -> Server {
Server { port: self.port.unwrap_or(8080), host: self.host.unwrap_or_else(|| "0.0.0.0".into()) }
}
}
// Extension trait
trait StrExt { fn shout(&self) -> String; }
impl StrExt for str { fn shout(&self) -> String { self.to_uppercase() + "!" } }
// Sealed trait (prevent external impls)
mod sealed { pub trait Sealed {} }
pub trait MyTrait: sealed::Sealed { /* ... */ }
impl sealed::Sealed for MyType {}
impl MyTrait for MyType {}
// Visitor pattern with enum + match
enum Shape { Circle(f64), Square(f64), Rect(f64, f64) }
impl Shape {
fn area(&self) -> f64 {
match self {
Self::Circle(r) => std::f64::consts::PI * r * r,
Self::Square(s) => s * s,
Self::Rect(w, h) => w * h,
}
}
}7. Idioms & style
- Naming:
snake_casefor vars, fns, modules, crates;PascalCasefor types, traits, enum variants;SCREAMING_SNAKE_CASEfor consts/statics; lifetime params short ('a,'de,'tcxin rustc itself). - Formatter:
rustfmt(cargo fmt) — universally applied;rustfmt.tomlfor project tweaks; near-zero configurable variance. Linter:clippy(cargo clippy) with 700+ opinionated lints acrosscorrectness,suspicious,style,complexity,perf,pedantic,nursery,cargo; CI gate (cargo clippy -- -D warnings). - Idiomatic Rust: prefer iterators over indexed loops (
map/filter/collect); use?for error propagation; returnResult<_, E>notpanic; build small types and impl traits on them; favor borrowing over cloning; newtype wrappers for type safety (struct UserId(u64)); trait-based extension over inheritance;From/Intofor conversion; usederiveforDebug/Clone/PartialEq; let the compiler guide you. API guidelines (rust-lang.github.io/api-guidelines/) are the canonical doc. - Error patterns:
thiserrorfor libraries (derivesError+Display),anyhowfor apps (anyhow::Result<T>+.context("loading config")),miettefor fancy diagnostic-style errors (powers rustc-quality error reports in CLIs likeoxc,dprint). - Reviewers look for: unnecessary
.clone(),unwrap()/expect()in non-test code, missing#[must_use], lifetime elision opportunities, missingSend/Syncbounds,unsafewithout// SAFETY:comments, public API ergonomics (acceptimpl AsRef<Path>not&Path), missing#[non_exhaustive]on enums that may grow,pub usere-exports for clean module surface, missing#[derive(Default)]where sensible.
8. Ecosystem
- Web (server): Axum (Tokio team, dominant in 2024-26), Actix Web (still fast, less idiomatic), Rocket, Warp, Poem, Loco (Rails-inspired), Salvo.
- Web (frontend, WASM): Leptos (fine-grained, SSR + hydration), Dioxus (React-like, multi-platform), Yew, Sycamore, Sauron, Maud / Askama (HTML templating).
- GUI (native): Tauri 2 (lightweight Electron alternative, web frontend + Rust backend, multi-platform incl. mobile), egui (immediate-mode, GPU-accelerated, used by Rerun + Embark), iced (Elm-architecture, native), Slint (declarative UI for desktop/embedded), gtk4-rs, Dioxus Desktop, Druid (deprecated).
- Async runtimes: Tokio (dominant, multi-threaded work-stealing), smol (single-binary, simple), async-std (deprecated / unmaintained), glommio (thread-per-core, io_uring, Datadog), monoio (Bytedance, thread-per-core, io_uring), bastion (actor model), embassy (no_std async for embedded).
- CLI: clap (the standard, both derive + builder), argh (Google, simpler), structopt (deprecated, use clap-derive). Output: indicatif (progress bars), ratatui (TUI framework, fork of tui-rs), crossterm (cross-platform terminal), owo-colors, anstyle, dialoguer (interactive prompts), inquire.
- Data/serialization: serde + serde_json / toml / bincode (binary, compact) / rmp-serde (MessagePack) / postcard (no_std friendly) / ciborium (CBOR) / ron (Rust-native human-readable). Fast JSON: simd-json (Cloudflare port), sonic-rs (Bytedance, even faster), serde-json-core (no_std). Database: sqlx (compile-time query checking), diesel (sync ORM, fastest), sea-orm (async ORM), rusqlite, tokio-postgres, mongodb-rust.
- Game/graphics: Bevy (ECS-based game engine, fast-moving), wgpu (cross-platform GPU API, runs on WebGPU/Vulkan/Metal/DX12, used by Firefox), ggez, macroquad (small/simple), rend3, Fyrox, Ambient.
- Embedded: embassy (async no_std), RTIC (interrupt-driven), embedded-hal 1.0 (stable), defmt (microscopic logging), probe-rs (cargo-embed, cargo-flash), postcard (serialization), heapless (stack-only collections).
- Logging/tracing: tracing (Tokio team, structured + spans, dominant), log + env_logger (legacy simple), slog (older structured), flexi_logger, tracing-subscriber (formatter/filter layer), opentelemetry-rust (OTLP export).
- Testing: stdlib
#[test]+cargo test(orcargo nextest runfor 60% faster runs); proptest / quickcheck (property-based), criterion (benchmarks with regression detection), insta (snapshot testing, Armin Ronacher), mockall, rstest (parameterized + fixtures), fake (data generation), wiremock (HTTP mocking). - Fuzzing: cargo-fuzz + libFuzzer, afl.rs, honggfuzz-rs. Used at scale by Cloudflare, Mozilla, Microsoft (OSS-Fuzz integration).
- Doc tools:
cargo doc+ rustdoc (HTML, doctest — examples in docs run as tests); mdBook for long-form (used by the Rust book itself). Auto-published on docs.rs. - Quality / security: clippy (idiom lints), cargo-audit (RustSec advisory DB), cargo-deny (license + advisory + dupe-version gates), cargo-machete (find unused deps), cargo-msrv (find minimum supported Rust version), cargo-tarpaulin (coverage, Linux), grcov (cross-platform coverage), cargo-llvm-cov.
- Notable users: Linux kernel (since 6.1 — drivers including Apple GPU, network, Nova nvidia in nightly), Microsoft (Windows components in
win32k.sys/DWriteCore, Azure CBL-Mariner, M365 cores), Google (Android Bluetooth + Crosvm + Fuchsia core), Apple (parts of Darwin), Mozilla (Servo revival 2024 under Linux Foundation, Stylo), Cloudflare (Pingora proxy — replaced NGINX, workerd, Quiche QUIC), Discord, Dropbox (Magic Pocket), Meta (source control Sapling), Amazon (Firecracker, Bottlerocket, Lambda components), Figma (multiplayer server), 1Password, Postman (Insomnia successor), Vercel (turbo + turbopack), npm registry, Asahi Linux.
Async Rust deep dive
Async Rust is the most powerful and most controversial feature of the language. Key concepts:
async fndesugars tofn() -> impl Future<Output = T>— the function body becomes a state machine struct that implementsFuture..awaitis a suspension point — the executor callsFuture::poll, and if the future returnsPoll::Pending, the current task yields back to the runtime.- No async runtime in std — Rust ships the
Futuretrait andasync/awaitsyntax but no executor. Pick Tokio (default for most), smol, glommio, monoio, embassy (no_std embedded). Send/Syncinfect everything — async functions inherit auto-traits from their captures. Hold aRc<T>across an.awaitand your future is!Send, breaking Tokio’s multi-threaded runtime. UseArc<T>instead.- Pinning ensures self-referential async state machines don’t move after polling starts.
Box::pin(fut)is the heap-allocated escape hatch;tokio::pin!(fut)for stack-pinning a local. - Cancellation: dropping a future cancels it (no
kill -9-style coercion). Cooperative — the future stops being polled. Usetokio::select! { _ = fut => ..., _ = ctx.cancelled() => ... }for race / cancel. async fnin traits (1.75+) works for static dispatch viaimpl Trait-in-return-position. For dynamic dispatch (dyn AsyncTrait), useasync-traitcrate or manual boxed-future. Full stabilization landed 1.86.- Common foot-guns: blocking inside async (
std::thread::sleepinstead oftokio::time::sleep), holding sync mutexes across.await(usetokio::sync::Mutex), spawning detached tasks that outlive the runtime (handles must be awaited or detached deliberately).
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let h1 = tokio::spawn(async { sleep(Duration::from_millis(100)).await; 1 });
let h2 = tokio::spawn(async { sleep(Duration::from_millis(200)).await; 2 });
let (r1, r2) = tokio::join!(h1, h2);
println!("{} {}", r1.unwrap(), r2.unwrap());
}Memory + ownership cookbook
// Borrow split — let two non-overlapping fields be borrowed mutably
struct Pair { a: String, b: String }
fn use_both(p: &mut Pair) {
let Pair { a, b } = p; // structural pattern split borrows by field
a.push('!'); b.push('?');
}
// Cow<'_, T> — clone-on-write, avoid allocation if input is already owned-shape
use std::borrow::Cow;
fn normalize(s: &str) -> Cow<'_, str> {
if s.chars().all(|c| c.is_ascii_lowercase()) { Cow::Borrowed(s) }
else { Cow::Owned(s.to_lowercase()) }
}
// Interior mutability — shared aliasing + mutation through Cell / RefCell / Mutex
use std::cell::RefCell;
let v = RefCell::new(vec![1, 2]);
v.borrow_mut().push(3);9. Gotchas
- Borrow checker frustration: “cannot borrow as mutable because it is also borrowed as immutable” — the compiler is right; restructure (split borrows, scope shorter, intermediate
let). - Strings:
Stringvs&strvs&StringvsBox<str>; APIs accept&str, returnString; index by byte (UTF-8 boundary panic if mid-char) — use.chars()or.char_indices(). - Integer overflow: panics in debug, wraps in release. Use
checked_add/wrapping_add/saturating_addexplicitly. Rc<RefCell<T>>is a smell: indicates fighting the borrow checker — usually restructure ownership instead.- Pinning self-referential structs in
async: can’t move once polled.Box::pinto heap-pin. - Trait object limitations:
dyn Traitrequires object safety (no generic methods, noSelfreturns). - Lifetime variance bugs: invariant types unexpectedly reject lifetime shortening (e.g.,
&mut Tis invariant inT). async fnin traits historically required workarounds (async-traitcrate); 1.75+ supports static dispatch natively.Send/Syncpropagation: holding aRc<T>makes a future!Send, breaking Tokio multi-threaded executor.- Cargo features are additive across the workspace: enabling a feature in one crate enables it everywhere — leads to surprise bloat.
unwrap()in production hides errors at runtime.- Macros’ error messages can be opaque;
cargo expand(cargo-expand) reveals what they emit. - Slow compile times are real — Bevy / Tokio / serde-heavy projects easily hit 10+ minute fresh builds. Mitigations:
sccache,cargo-chef(Docker),moldlinker (-C link-arg=-fuse-ld=mold— 5-10x faster link),craneliftbackend (debug only), workspace splitting, fewer generics. impl Traitin different positions has different semantics — argument position is generic, return position is opaque type, type alias is for impl blocks. Easy to confuse.- Borrow-check vs
RefCellruntime borrow panic —RefCell::borrow_mut()while a borrow is live panics; one of the few Rust panics that’s hard to debug. droporder is LIFO within a scope but reversed across struct fields (declaration order, then top-down on enclosing). Matters when types implementDropinteractively (locks).- Cargo’s
default-features = truecan pull surprises when used in workspaces; disable withdefault-features = falsethen opt in explicitly. 'staticdoesn’t mean “lives forever” — it means “no borrowed references inside.”Stringis'static,&'static stris a string literal, distinguish carefully.
2024 Edition (Feb 2025 stable)
Rust 1.85 enabled Edition 2024 by default for new projects. Headline changes:
if lettemporary scope shrinks — fewer surprising borrow-extensions.- Migrating to
let chains(stable 1.83):if let Some(x) = opt && x > 5 { ... }. unsafe extern { fn ... }— explicit unsafe on extern blocks.unsafeattributes for#[no_mangle],#[link_section],#[export_name]— they’re now#[unsafe(no_mangle)].genkeyword reserved for generator blocks (gen { yield x; }) — generators in nightly.- Tail expressions in blocks dropped temporaries at end-of-block instead of end-of-scope — eliminates many spurious borrow-check errors.
macro_rules!fragment specifiers tightened (e.g.,expr_2021).
Cargo.toml deep dive
[package]
name = "myapp"
version = "0.1.0"
edition = "2024"
rust-version = "1.85" # MSRV
description = "..."
license = "MIT OR Apache-2.0"
repository = "https://github.com/me/myapp"
keywords = ["cli", "demo"]
categories = ["command-line-utilities"]
[dependencies]
tokio = { version = "1.40", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
clap = { version = "4", features = ["derive"] }
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] }
anyhow = "1"
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
[dev-dependencies]
criterion = { version = "0.5", features = ["html_reports"] }
proptest = "1"
insta = "1"
[build-dependencies]
cc = "1"
[features]
default = ["json"]
json = ["dep:serde_json"]
postgres = ["dep:tokio-postgres"]
[[bench]]
name = "core_bench"
harness = false # use Criterion's main, not stdlib's
[profile.release]
opt-level = 3
lto = "fat" # full link-time optimization
codegen-units = 1 # slower compile, better code
panic = "abort" # smaller binary, no unwinding
strip = true
[profile.release-debug]
inherits = "release"
debug = true # keep symbols for profiling
[workspace]
members = ["crates/*"]
resolver = "3" # 2024 edition default
[workspace.dependencies]
tokio = { version = "1.40", features = ["full"] }
[workspace.lints.rust]
unsafe_code = "forbid"
[workspace.lints.clippy]
all = "warn"
pedantic = "warn"Compile-time + runtime characteristics (real-world 2026 numbers)
- Release-build binary size: hello-world ~300 KB stripped;
cargo new --binwith serde + tokio + reqwest typical 5-15 MB stripped.panic = "abort"+strip = true+lto = "fat"+opt-level = "z"shrinks 40-60%. - Compile time (Bevy game, ~300k LOC, cold): ~3 min clean release; ~10 s incremental. Cranelift backend: ~2 min cold debug, half the linker time.
- Throughput: Axum + Tokio serves ~1M req/s on a 32-core box for “hello world” — within 5% of fasthttp (Go), 2x net/http (Go), 3-5x Express (Node), 10x Flask (Python).
- Memory: 8 KB initial stack per task (vs Tokio’s 16 KB-ish per task incl. waker), no GC pauses. Idiomatic services run at fraction of equivalent JVM memory.
Rust version timeline (1.0 → 1.95)
Rust ships every 6 weeks. Notable releases:
| Version | Date | Headline |
|---|---|---|
| 1.0 | May 2015 | First stable |
| 1.31 | Dec 2018 | Edition 2018 — NLL, async/await preview |
| 1.39 | Nov 2019 | Stable async/await |
| 1.51 | Mar 2021 | Const generics MVP |
| 1.56 | Oct 2021 | Edition 2021 — disjoint closure captures, panic in const fn |
| 1.65 | Nov 2022 | GATs, let-else |
| 1.70 | Jun 2023 | OnceLock/OnceCell |
| 1.74 | Nov 2023 | Lint config in Cargo.toml |
| 1.75 | Dec 2023 | async fn in traits (static dispatch), RPITIT |
| 1.78 | May 2024 | Lock APIs in std::io, diagnostic_namespace |
| 1.80 | Jul 2024 | LazyLock/LazyCell, exclusive ranges in patterns |
| 1.83 | Nov 2024 | const traits + let chains |
| 1.85 | Feb 2025 | Edition 2024 default, async closures |
| 1.88 | Aug 2025 | let chains in if/while everywhere |
| 1.90 | Oct 2025 | More const-evaluation features |
| 1.95 | Apr 2026 | (latest as of writing) |
Roadmap focus areas through 2026-27: full async traits with dyn, Polonius borrow checker, more const-generics expressions, gradual #![forbid(unsafe_op_in_unsafe_fn)] migration, formal language spec.
Real code patterns
Axum REST API with sqlx + Postgres
use axum::{routing::{get, post}, Router, extract::{State, Path, Json}, http::StatusCode};
use sqlx::PgPool;
use serde::{Serialize, Deserialize};
use std::sync::Arc;
#[derive(Clone)]
struct AppState { db: PgPool }
#[derive(Serialize, sqlx::FromRow)]
struct User { id: i64, email: String, name: String }
#[derive(Deserialize)]
struct CreateUser { email: String, name: String }
async fn get_user(State(s): State<Arc<AppState>>, Path(id): Path<i64>)
-> Result<Json<User>, StatusCode>
{
let user = sqlx::query_as!(User, "SELECT id, email, name FROM users WHERE id = $1", id)
.fetch_optional(&s.db).await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
.ok_or(StatusCode::NOT_FOUND)?;
Ok(Json(user))
}
async fn create_user(State(s): State<Arc<AppState>>, Json(input): Json<CreateUser>)
-> Result<Json<User>, StatusCode>
{
let user = sqlx::query_as!(User,
"INSERT INTO users (email, name) VALUES ($1, $2) RETURNING id, email, name",
input.email, input.name)
.fetch_one(&s.db).await
.map_err(|_| StatusCode::CONFLICT)?;
Ok(Json(user))
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let db = PgPool::connect(&std::env::var("DATABASE_URL")?).await?;
let state = Arc::new(AppState { db });
let app = Router::new()
.route("/users/:id", get(get_user))
.route("/users", post(create_user))
.with_state(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
axum::serve(listener, app).await?;
Ok(())
}Tokio + reqwest concurrent fetch with structured cancellation
use futures::future::join_all;
use std::time::Duration;
async fn fetch_with_timeout(client: &reqwest::Client, url: &str) -> anyhow::Result<String> {
let resp = tokio::time::timeout(Duration::from_secs(5), client.get(url).send()).await??;
Ok(resp.text().await?)
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = reqwest::Client::new();
let urls = vec!["https://example.com", "https://rust-lang.org"];
let results = join_all(urls.iter().map(|u| fetch_with_timeout(&client, u))).await;
for r in results {
match r {
Ok(body) => println!("got {} bytes", body.len()),
Err(e) => eprintln!("error: {e:#}"),
}
}
Ok(())
}WASM + Component Model (2026)
Rust is the lingua franca of WebAssembly because of its no-GC, small binary, and no_std story.
wasm-bindgen+wasm-packfor browser JS interop.cargo-componentfor WASI 0.2 / Component Model (WIT-based interface definitions).wit-bindgengenerates Rust bindings from WIT (WebAssembly Interface Types).- WASI Preview 2: stable as of late 2024;
wasm32-wasip2target. - Runtimes: Wasmtime (Bytecode Alliance), WasmEdge (CNCF), Wasmer, Spin (Fermyon, serverless), Fastly Compute@Edge, Cloudflare workerd.
- Use cases: Cloudflare Workers, Vercel Edge, Shopify Functions, Suborbital, Microsoft AKS WASM nodes, Adobe Photoshop Web, Figma plugins.
Embedded + bare-metal Rust
Rust’s no_std + alloc + cargo + embedded-hal 1.0 (stable Jan 2024) make it the most ergonomic systems language for microcontrollers in 2026 — and the only modern alternative to C/C++ for hard real-time.
The hardware targets that ship Rust today:
| Family | Targets | Notable boards |
|---|---|---|
| RP2040 / RP2350 | thumbv6m-none-eabi, thumbv8m.main-none-eabihf | Raspberry Pi Pico, Pico 2, Pimoroni Tiny 2040 |
| ESP32 (Xtensa) | xtensa-esp32-none-elf (+esp channel) | Espressif dev kits, M5Stack, Adafruit |
| ESP32-C3 / C6 / S3 (RISC-V + Xtensa) | riscv32imc-unknown-none-elf, riscv32imac-unknown-none-elf | C3 supermini, C6 wifi6/zigbee, S3 + AI |
| STM32 F4/F7/H7 | thumbv7em-none-eabihf | STM32F411 BlackPill, F4 Discovery, H743 Nucleo |
| nRF52840 (Nordic) | thumbv7em-none-eabihf | nRF52840 DK, Adafruit Feather Bluefruit |
| Microchip SAMD51 | thumbv7em-none-eabihf | Adafruit Feather M4, ItsyBitsy M4, PyGamer |
Dev workflow:
# Install target + tools
rustup target add thumbv7em-none-eabihf
cargo install probe-rs --features cli
cargo install cargo-embed cargo-flash cargo-binutils
# Scaffold from a template
cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart
# Flash + run via probe-rs (USB SWD/JTAG probe)
cargo embed --release # flash + open RTT (real-time transfer) console
cargo flash --chip STM32F411CEUx # flash only
DEFMT_LOG=info cargo embed # filter defmt logsEmbassy vs RTIC:
- Embassy —
async/awaiton bare metal. Theembassy-executoris a no-alloc executor designed to live in a single static. Async HALs (embassy-stm32,embassy-nrf,embassy-rp,embassy-esp) for SPI, I2C, UART, USB, net, timers. Dominant for new projects 2025-26.
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use embassy_stm32::gpio::{Level, Output, Speed};
use embassy_time::{Duration, Timer};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
let mut led = Output::new(p.PC13, Level::High, Speed::Low);
loop {
led.toggle();
Timer::after(Duration::from_millis(500)).await;
}
}- RTIC 2 — message-passing + priority-based preemption via interrupt vectors. Hard real-time with deterministic latency. v2 (2024) added async tasks alongside hardware-priority tasks.
defmt— deferred formatting; ~10 bytes/log on the wire, host PC reformats. 100x faster thanuart_writeln!. Pair withprobe-rs runfor live RTT streaming.
no_std + alloc opt-in gives you Box / Vec / String against a global allocator (e.g. embedded-alloc bump-pointer). For zero-alloc code, heapless has stack-only Vec<T, N>, String<N>, FnvIndexMap<K, V, N> with capacity in the type.
Rust web ecosystem 2026 (real-world stacks)
Reference 2026 web service stack: Axum + Tower + Tracing + sqlx + Postgres + Redis — used at Discord, parts of Cloudflare, Shopify, AWS internal services.
use axum::{Router, routing::get};
use sqlx::PgPool;
use tower_http::{trace::TraceLayer, compression::CompressionLayer};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[derive(Clone)]
struct AppState { db: PgPool }
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::new("info"))
.with(tracing_subscriber::fmt::layer().json())
.init();
let db = PgPool::connect(&std::env::var("DATABASE_URL")?).await?;
sqlx::migrate!("./migrations").run(&db).await?;
let app = Router::new()
.route("/health", get(|| async { "ok" }))
.layer(TraceLayer::new_for_http())
.layer(CompressionLayer::new())
.with_state(AppState { db });
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
axum::serve(listener, app).await?;
Ok(())
}ORM landscape:
- sqlx — compile-time SQL checking against a live dev DB; dominant for greenfield.
- Diesel 2.x — synchronous, fastest ORM, DSL-based;
diesel-asyncfor async. - sea-orm — async, ActiveRecord-style, codegen from DB schema.
Pooling: deadpool-postgres if you skip the ORM; redis-rs + fred for Redis; mongodb crate is official.
Edge / serverless platforms with native Rust support:
| Platform | Build/dev | Cold start | Runtime |
|---|---|---|---|
| Cloudflare Workers | wrangler dev + worker-rs → wasm32-unknown-unknown | <1ms | V8 isolate + wasm |
| Fermyon Spin | spin watch + spin-sdk → wasm32-wasip2 | ~5ms | Wasmtime |
| Fastly Compute@Edge | viceroy local + fastly crate → wasm32-wasip1 | ~10ms | Lucet/Wasmtime |
| AWS Lambda | cargo lambda build --release --arm64 | ~80ms | Firecracker μVM |
Cloudflare Workers Rust example:
use worker::*;
#[event(fetch)]
async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> {
Router::new()
.get_async("/users/:id", |_req, ctx| async move {
let id = ctx.param("id").unwrap();
let kv = ctx.kv("USERS")?;
match kv.get(id).text().await? {
Some(v) => Response::ok(v),
None => Response::error("not found", 404),
}
})
.run(req, env).await
}Build: wrangler deploy --compatibility-date=2026-01-01. Pair with Durable Objects + R2 + D1 for stateful edge.
10. Citations
- The Rust Programming Language (“the book”): https://doc.rust-lang.org/book/
- Rust Reference: https://doc.rust-lang.org/reference/
- Standard library docs: https://doc.rust-lang.org/std/
- Rust 1.95 release post (2026-04-16) + recent releases: https://blog.rust-lang.org/
- Rustonomicon (unsafe Rust): https://doc.rust-lang.org/nomicon/
- Rust Async Book: https://rust-lang.github.io/async-book/
- API Guidelines: https://rust-lang.github.io/api-guidelines/
- Cargo Book: https://doc.rust-lang.org/cargo/
- Rustfmt + Clippy: https://github.com/rust-lang/rustfmt ; https://doc.rust-lang.org/clippy/
- Editions guide: https://doc.rust-lang.org/edition-guide/
- Rust Foundation: https://foundation.rust-lang.org/