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 unsafe raw 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; technical governance via Project teams + RFC process.
  • One main implementation: rustc (LLVM-based). gccrs (GCC frontend) and rustc_codegen_cranelift (faster debug builds) emerging.
  • Editions: 2015, 2018, 2021, 2024 — opt-in syntactic/semantic shifts; libraries from different editions interoperate.
  • Compiler messages and tooling (cargo, rustup, clippy) are best-in-class.

2. Getting started

  • Install: rustup is the official toolchain manager: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh (or winget install Rustlang.Rustup).

  • Version manager: rustup itself: rustup install stable|beta|nightly, rustup default stable, rustup target add wasm32-unknown-unknown. Override per-dir with rust-toolchain.toml.

  • Hello, world:

    fn main() { println!("Hello, world!"); }

    Create + run: cargo new hello && cd hello && cargo run.

  • Project layout: Cargo.toml (manifest) + Cargo.lock (locked deps); src/main.rs (binary) or src/lib.rs (library); src/bin/<name>.rs for additional binaries; tests/ (integration), benches/, examples/. Workspaces for multi-crate.

  • Build tool: cargo is everything: cargo build, run, test, bench, doc, publish, add, update, clippy, fmt, tree. Crates from crates.io.

  • REPL/playground: Rust Playground (https://play.rust-lang.org/). evcxr (Jupyter kernel + REPL).

3. Basics

  • Primitives: bool, char (4-byte Unicode scalar), signed/unsigned ints i8..i128/isize, u8..u128/usize, f32/f64. Literals: 0x, 0b, 0o, _ separators (1_000_000), suffixes (42u32, 3.14f64), byte literals b'x'.
  • Variables: let x = 1; (immutable by default), let mut x, const FOO: u32 = 42;, static. Shadowing allowed (let x = x + 1;). Block-scoped, expression-oriented (last expression returns).
  • Control flow: if/else (expression), match (exhaustive pattern-matching, the workhorse), loop/while/while let/for x in iter, break/continue with labels, if let/let else. Patterns: literal, range, struct, enum, tuple, slice, or-patterns, guards.
  • Functions: fn f(x: i32) -> i32 { x + 1 }. No default args / no overloading. Closures |x| x + 1 (auto-traits Fn/FnMut/FnOnce). Generics + traits substitute for overloading. First-class via fn pointers, closures, dyn Trait.
  • Strings: &str (string slice, UTF-8) and owning String (heap, growable). Format with format!("{x}") / println!; raw strings r"...", r#"..."#. No interpolation outside macros.
  • Collections: arrays [T; N], slices &[T]/&mut [T], Vec<T>, HashMap<K, V> / BTreeMap<K, V>, HashSet<T> / BTreeSet<T>, VecDeque<T>, tuples (T1, T2), Option<T>, Result<T, E>. Plus Box<T>/Rc<T>/Arc<T>/Cell<T>/RefCell<T> smart pointers.

4. Intermediate

  • Generics & traits: fn f<T: Trait>(x: T) or where T: Trait. Trait objects dyn Trait (vtable). Associated types, generic associated types (GATs, stable 1.65). Higher-ranked trait bounds for<'a> Fn(&'a T) -> .... Lifetimes are part of types: &'a str, fn f<'a>(x: &'a str) -> &'a str. Variance is computed structurally.
  • Modules/packages: crate = compilation unit; module tree via mod foo; or mod foo { ... }, pub/pub(crate)/pub(super). Cargo packages contain one or more crates and are published to crates.io.
  • Error handling: Result<T, E> + ? operator for propagation. Option<T> for absence. panic! for unrecoverable bugs. Libraries use thiserror (derive); apps use anyhow (Box<dyn Error> + context).
  • Concurrency: std::thread::spawn + scoped threads (std::thread::scope, 1.63), channels (std::sync::mpsc), Mutex<T>/RwLock<T>/Arc<T>, std::sync::atomic, std::sync::Barrier, OnceLock/LazyLock. Async: async fn + .await (compiler desugars to state machines implementing Future); requires a runtime — Tokio is dominant; async-std, smol alternatives.
  • I/O & networking: std::fs, std::io (Read/Write traits + BufReader/BufWriter), std::net (TCP/UDP), std::process. Async I/O via Tokio (tokio::fs, tokio::net, tokio::io::AsyncReadExt).
  • Stdlib highlights: Iterator (the most powerful trait — map/filter/collect and 80 more), From/Into/TryFrom/TryInto, Display/Debug, Default, Clone/Copy, Drop, Deref, IntoIterator. std::collections, std::sync, std::env, std::process, std::time.

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. Drop trait runs on scope exit. No GC, no runtime memory tracking. NLL (Non-Lexical Lifetimes) makes borrows scope-tight. Polonius (next-gen borrow checker) ongoing.
  • Concurrency deep dive: Send (transferable across threads) + Sync (shareable across threads) auto-traits enforce thread safety at compile time. Pin<T>/Unpin for self-referential types (used by async). Lock-free via std::sync::atomic. Async runtimes: Tokio’s work-stealing scheduler, scoped tasks, structured concurrency (cancellation, JoinSet).
  • FFI/interop: extern "C" fn for C ABI; bindgen generates Rust bindings from C headers, cbindgen generates C headers from Rust. cxx for C++ interop (safe bidirectional). pyo3 for Python, napi-rs for Node.js, uniffi for cross-lang bindings (Mozilla). WASM: wasm-bindgen + wasm-pack.
  • Reflection: none at runtime (no RTTI). Substitute: std::any::TypeId/Any for downcasting, Debug for printing, derive macros for compile-time codegen.
  • Performance tooling: cargo bench + Criterion, cargo flamegraph, samply, perf, valgrind/cachegrind, cargo-llvm-lines (codegen size), cargo-bloat (binary size), hyperfine (CLI bench), heaptrack/bytehound. Compile flags: --release, RUSTFLAGS=-C target-cpu=native, lto = "fat", codegen-units = 1 in Cargo.toml. PGO + BOLT supported.

6. God mode

  • Macros: declarative macro_rules! foo { ($x:expr) => { ... } } — pattern-matched token transformations; procedural macros — derive, attribute, function-like; receive TokenStream, return TokenStream. Built with syn + quote + proc-macro2.
  • unsafe Rust: unlocks raw pointers (*const T/*mut T), unchecked indexing, calling unsafe fn, mutating statics, implementing unsafe traits, dereferencing pointers, transmute. The Rustonomicon is the spec; miri interprets MIR to detect UB in unsafe code.
  • Lifetimes deep: variance (covariant/contravariant/invariant), HRTBs (for<'a> ...), 'static, lifetime elision rules, PhantomData<T> for declaring variance/drop semantics on zero-sized types.
  • Zero-sized types (ZSTs): unit (), empty structs, marker types — take 0 bytes; Vec<()> is just a length counter.
  • Pin/Unpin and async internals: Future::poll returns Poll<T>; async fns desugar to a state-machine struct with each .await becoming a state. Pin enforces self-referential safety. Wakers + Tasks + Executors form the runtime.
  • no_std: disable libstd for embedded / kernels; opt into alloc for heap. Targets like thumbv7em-none-eabihf for Cortex-M.
  • Custom allocators: #[global_allocator] static A: MyAlloc = MyAlloc; (e.g., mimalloc, jemallocator); allocator API for per-collection allocators (unstable).
  • MIR inspection: cargo +nightly rustc -- -Zunpretty=mir (or =hir, =hir-tree, =ast). Cranelift backend for fast debug.
  • Embedded HAL: embedded-hal crate trait ecosystem; RTIC / Embassy async runtimes for microcontrollers; probe-rs for flashing/debugging.
  • Cargo build scripts (build.rs) — compile C dependencies, generate code, set link flags. Custom Cargo subcommands: any binary named cargo-foo on PATH becomes cargo foo.
  • Specialization (unstable nightly), const generics + const evaluation, GATs, async traits in traits (1.75 stable for static dispatch, 1.86+ for dyn).

7. Idioms & style

  • Naming: snake_case for vars, fns, modules, crates; PascalCase for types, traits, enum variants; SCREAMING_SNAKE_CASE for consts/statics; lifetime params short ('a, 'de).
  • Formatter: rustfmt (cargo fmt) — universally applied. Linter: clippy (cargo clippy) with hundreds of opinionated lints; CI gate.
  • Idiomatic Rust: prefer iterators over indexed loops (map/filter/collect); use ? for error propagation; return Result<_, E> not panic; build small types and impl traits on them; favor borrowing over cloning; newtype wrappers for type safety; trait-based extension over inheritance; From/Into for conversion; use derive for Debug/Clone/PartialEq; let the compiler guide you. API guidelines are the canonical doc.
  • Reviewers look for: unnecessary .clone(), unwrap()/expect() in non-test code, missing #[must_use], lifetime elision opportunities, missing Send/Sync bounds, unsafe without // SAFETY: comments, public API ergonomics (accept impl AsRef<Path> not &Path).

8. Ecosystem

  • Web: Axum (Tokio team), Actix Web, Rocket, Warp, Poem. Frontend: Yew, Leptos, Dioxus, Sycamore (WASM).
  • Async runtimes: Tokio (dominant), async-std, smol, glommio (thread-per-core, io_uring).
  • CLI: clap (the standard), argh, structopt (deprecated, use clap-derive). Output: indicatif (progress), ratatui (TUI), owo-colors.
  • Data/serialization: serde + serde_json / toml / bincode / rmp-serde. Database: sqlx, diesel, sea-orm, rusqlite, tokio-postgres.
  • Game/graphics: Bevy (ECS), wgpu (cross-platform GPU), ggez, macroquad, rend3.
  • Embedded: embassy, RTIC, embedded-hal, defmt (logging), probe-rs.
  • Testing: stdlib #[test] + cargo test; proptest / quickcheck (property-based), criterion (benchmarks), insta (snapshot), mockall, rstest (parameterized).
  • Doc tools: cargo doc + rustdoc (HTML, doctest); mdBook for long-form. Auto-published on docs.rs.
  • Notable users: Linux kernel (since 6.1), Mozilla (Servo, Stylo), Cloudflare (Pingora, workers), Discord, Dropbox (Magic Pocket), Microsoft (Windows components, Azure), Meta, Amazon (Firecracker, Bottlerocket), Google (Android, Fuchsia), npm registry, Figma, 1Password.

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: String vs &str vs &String vs Box<str>; APIs accept &str, return String; 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_add explicitly.
  • 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::pin to heap-pin.
  • Trait object limitations: dyn Trait requires object safety (no generic methods, no Self returns).
  • Lifetime variance bugs: invariant types unexpectedly reject lifetime shortening (e.g., &mut T is invariant in T).
  • async fn in traits historically required workarounds (async-trait crate); 1.75+ supports static dispatch natively.
  • Send/Sync propagation: holding a Rc<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.

10. Citations