thecodex.expert · The Codex Family of Knowledge
Language Reference

Rust

Memory safety without a garbage collector — the compiler enforces ownership rules that eliminate entire classes of bugs before your code ever runs.

Language Reference Rust 1.x stable Systems language Last verified:
New to Rust? This is the reference encyclopedia — dip in anytime. To learn step by step, start the Rust Course →
Canonical Definition

Rust is a systems programming language that achieves memory safety without a garbage collector through an ownership system enforced at compile time — eliminating use-after-free, null pointer dereferences, buffer overflows, and data races while compiling to native machine code with no runtime overhead.

📑 Rust Reference — All Topics

Ownership & Borrowing

Move semantics, references, lifetimes, stack vs heap.

Types & Traits

Structs, enums, traits, impl blocks, generics.

Error Handling & Concurrency

Result, Option, ? operator, threads, async/await.

What is Rust

A broken elevator, a Mozilla side project, and memory safety without a GC.

Setup and Cargo

rustup installs it; Cargo builds, tests, and manages dependencies.

Variables and Mutability

Immutable by default — mut is an explicit opt-in, not the default.

Data Types

Fixed-width integers, tuples, and arrays — the width is in the name.

Control Flow

if is an expression, and break can return a value from loop.

References and Slices

One mutable reference OR many immutable — never both, enforced at compile time.

Structs

Field-init shorthand, impl blocks, and tuple/unit structs — no classes.

Enums and Pattern Matching

No null — Option is an enum, and match must handle every case.

Generics

Monomorphization gives generics zero runtime cost, at the price of binary size.

Collections

Vec, String, and HashMap — the growable collections Rust code actually uses.

The Result Type

No exceptions — Result forces explicit handling, and ? makes propagation one character.

Closures

Fn, FnMut, FnOnce — the borrow checker needs to know how you use captures.

Iterators

Lazy by design — map and filter alone produce zero output until consumed.

Smart Pointers

Box for the heap, Rc for shared ownership, RefCell for runtime-checked mutation.

Lifetimes

Annotations describe an existing relationship — they change nothing at runtime.

Concurrency and Threads

“Fearless concurrency” — the borrow checker catches most data races before runtime.

Async/Await

std ships the syntax; you add Tokio for an actual runtime.

Modules and Crates

Private by default at every level — pub is the explicit opt-in.

Testing

#[test] and cargo test — tests live right next to the code, no install needed.

Macros

vec! and println! aren't functions — the ! means code generated before type checking.

Unsafe Rust

5 specific powers, not a safety-off switch — the borrow checker still applies.

Traits and Trait Objects

Static dispatch (zero cost) or dyn Trait dynamic dispatch — your choice, per use.

Cargo and Packages

cargo publish uploads forever — yank retires a version, nothing deletes it.

Standard Library

No async runtime, no HTTP client, no JSON — deliberately left to crates.io.

String Handling

No s[0] by design — UTF-8 characters can span 1-4 bytes.

Borrow Checker Deep Dive

NLL (2018+) made the checker smarter, not weaker — borrows now end at last use.

Performance and Memory

Zero-cost abstractions: iterators compile to the identical assembly as a manual loop.

One sentence

Rust achieves what was previously thought impossible: memory safety without a garbage collector — the compiler enforces rules about who owns data and when it is freed, catching entire classes of bugs that crash C and C++ programs before your code ever runs.

What Rust is

Rust is a systems programming language created by Graydon Hoare at Mozilla Research, with version 1.0 released in May 2015. Rust's central achievement is memory safety without garbage collection — it eliminates use-after-free, null pointer dereferences, buffer overflows, and data races at compile time through its ownership system, without any runtime overhead. Rust compiles to native machine code and matches C and C++ in performance, while providing the safety guarantees that those languages cannot.

Rust has been the most loved/admired programming language in the Stack Overflow Developer Survey every year from 2016 to 2024. It is used in the Linux kernel (since 2022), Android, the Windows NT kernel, Firefox, Cloudflare's infrastructure, AWS, Discord, Figma, and hundreds of production systems.

Rusthello.rs
fn main() {
    // Variables are immutable by default
    let name = "Priya";
    let mut count = 0;   // mut = mutable

    println!("Hello, {}!", name);

    // Loop with mutation
    while count < 5 {
        count += 1;
    }
    println!("Count: {}", count);

    // Ownership: each value has exactly one owner
    let s1 = String::from("hello");
    let s2 = s1;           // s1 is MOVED into s2 — s1 no longer valid
    // println!("{}", s1); // COMPILE ERROR: s1 was moved

    // Clone to make a deep copy
    let s3 = s2.clone();
    println!("{} and {}", s2, s3);
}

Ownership — the central concept

Rust's ownership system enforces three rules at compile time:

  1. Each value in Rust has exactly one owner.
  2. When the owner goes out of scope, the value is dropped (freed).
  3. There can only be one owner at a time — assignment moves ownership.

These rules let the compiler insert free calls automatically at the right points — no manual memory management, no garbage collector, no runtime overhead. Memory is always freed exactly once, exactly when the owner goes out of scope.

Rustownership.rs
fn main() {
    // Stack-allocated — Copy trait: integers, bools, chars
    let x = 5;
    let y = x;   // x is COPIED — both x and y are valid
    println!("x={}, y={}", x, y);

    // Heap-allocated — no Copy: String, Vec, Box
    let s1 = String::from("hello");
    let s2 = s1;   // s1 is MOVED — only s2 is valid now
    // println!("{}", s1);  // ERROR: value moved

    // Passing to function also moves
    let s = String::from("world");
    takes_ownership(s);
    // println!("{}", s);   // ERROR: s was moved into the function

    // Return ownership back
    let s3 = gives_ownership();
    println!("{}", s3);
}

fn takes_ownership(s: String) {
    println!("{}", s);
}   // s dropped here — memory freed

fn gives_ownership() -> String {
    String::from("hello")
}   // returned String moved to caller — not dropped here

Borrowing and references

Moving ownership to every function is impractical. Borrowing lets you pass a reference to a value without transferring ownership. The rules: you can have either one mutable reference OR any number of immutable references — but never both at the same time. This prevents data races at compile time.

Rustborrowing.rs
fn main() {
    let s = String::from("hello");

    // Immutable borrow — s not moved, caller retains ownership
    let len = calculate_length(&s);
    println!("'{}' has {} chars", s, len);

    // Multiple immutable borrows are OK
    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);

    // Mutable borrow — only ONE at a time
    let mut s = String::from("hello");
    let r = &mut s;
    r.push_str(", world");
    println!("{}", r);
    // Cannot have another reference to s while r is alive
}

fn calculate_length(s: &String) -> usize {
    s.len()
}   // s not dropped — we only borrowed it

Types: structs, enums, and Result/Option

Rust's enum is much more powerful than enums in C or Java — enum variants can carry data. The two most important enums in Rust: Option<T> (a value that may or may not be present) and Result<T, E> (an operation that may succeed or fail). Both eliminate null pointer exceptions and unhandled errors by making the compiler force you to handle every case.

Rusttypes.rs
// Struct
struct Point {
    x: f64,
    y: f64,
}

impl Point {
    fn new(x: f64, y: f64) -> Self { Point { x, y } }
    fn distance_from_origin(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

// Enum with data (algebraic data type)
enum Shape {
    Circle(f64),              // radius
    Rectangle(f64, f64),      // width, height
    Triangle(f64, f64, f64),  // sides
}

fn area(shape: &Shape) -> f64 {
    match shape {
        Shape::Circle(r)        => std::f64::consts::PI * r * r,
        Shape::Rectangle(w, h)  => w * h,
        Shape::Triangle(a,b,c)  => {
            let s = (a + b + c) / 2.0;
            (s*(s-a)*(s-b)*(s-c)).sqrt()  // Heron's formula
        }
    }
}

// Option: Some(value) or None
fn divide(a: f64, b: f64) -> Option<f64> {
    if b == 0.0 { None } else { Some(a / b) }
}

// Result: Ok(value) or Err(error)
fn parse_int(s: &str) -> Result<i32, std::num::ParseIntError> {
    s.parse::<i32>()
}

Lifetimes: references that outlive their data

The borrow checker prevents dangling references — references to data that has already been freed. When a function takes and returns references, the compiler needs to know how the reference lifetimes relate. Lifetime annotations ('a, 'b) make these relationships explicit. The compiler often infers lifetimes (lifetime elision), but complex cases require explicit annotations.

Rustlifetimes.rs
// The return reference must live at least as long as both inputs
// 'a says: the output lifetime is tied to the shorter of x and y
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

// Struct holding a reference — must annotate lifetime
struct Important<'a> {
    content: &'a str,   // content must outlive Important
}

fn main() {
    let s1 = String::from("long string");
    let result;
    {
        let s2 = String::from("xyz");
        result = longest(s1.as_str(), s2.as_str());
        println!("{}", result);   // OK — s2 still alive here
    }
    // println!("{}", result);    // ERROR — s2 dropped; result would dangle
}

Traits: Rust's interface system

A trait defines shared behaviour — like an interface in Java or a typeclass in Haskell. Types implement traits. Trait bounds constrain generics (T: Display + Clone). Rust's standard library is built on traits: Iterator, Display, Clone, Copy, Send, Sync.

Rusttraits.rs
use std::fmt;

trait Animal {
    fn name(&self) -> &str;
    fn speak(&self) -> String;
    // Default implementation
    fn description(&self) -> String {
        format!("{} says: {}", self.name(), self.speak())
    }
}

struct Dog { name: String }
struct Cat { name: String }

impl Animal for Dog {
    fn name(&self) -> &str { &self.name }
    fn speak(&self) -> String { String::from("Woof!") }
}

impl Animal for Cat {
    fn name(&self) -> &str { &self.name }
    fn speak(&self) -> String { String::from("Meow!") }
}

// Trait bound: T must implement Animal
fn print_animal<T: Animal>(animal: &T) {
    println!("{}", animal.description());
}

// Dynamic dispatch: dyn Animal — runtime polymorphism
fn make_sound(animals: &[Box<dyn Animal>]) {
    for a in animals { println!("{}", a.speak()); }
}

Fearless concurrency

Rust's ownership and type system prevent data races at compile time. The Send trait marks types safe to transfer between threads. The Sync trait marks types safe to share between threads via references. The compiler enforces these — if a type is not Send, you cannot send it to another thread. This is "fearless concurrency": concurrency bugs become compile errors.

Rustconcurrency.rs
use std::thread;
use std::sync::{Arc, Mutex};

fn main() {
    // Arc = Atomically Reference Counted (thread-safe Rc)
    // Mutex = mutual exclusion for shared mutation
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles { handle.join().unwrap(); }
    println!("Result: {}", *counter.lock().unwrap());  // 10

    // Channels: message passing (like Go goroutines)
    let (tx, rx) = std::sync::mpsc::channel();
    thread::spawn(move || { tx.send(42).unwrap(); });
    println!("Received: {}", rx.recv().unwrap());
}

Cargo: Rust's build system and package manager

Cargo is Rust's official build tool, package manager, and project scaffolder. cargo new project_name creates a new project. cargo build compiles. cargo run compiles and runs. cargo test runs tests. cargo doc generates documentation. Dependencies are declared in Cargo.toml; exact versions are locked in Cargo.lock. The package registry is crates.io — over 150,000 crates published.

Commonly confused
Rust does not have a garbage collector but it does automatically free memory. Memory is freed when the owner goes out of scope — deterministically, at compile-time-known points. This is neither manual management (like C) nor GC (like Java). It is ownership-based automatic memory management.
The borrow checker errors are not bugs in your logic — they are the compiler protecting you. "Value was moved" or "cannot borrow as mutable because it is also borrowed as immutable" are the compiler preventing use-after-free and data races that would be silent runtime bugs in C. Fighting the borrow checker usually means the logic has a latent safety problem.
Rust's async/await is not like JavaScript's. Rust futures are lazy — they do nothing until polled. You need an async runtime (Tokio, async-std) to drive them. JavaScript's event loop runs automatically. In Rust, calling an async function returns a Future; you must .await it or spawn it on an executor for it to run.

The ownership system: formal foundations

Rust's ownership system is formalized in RustBelt (Jung et al., 2017), a mechanized semantic model of the Rust type system built in Iris/Coq. RustBelt proved that Rust's core type system is sound — if the compiler accepts a program, it is memory-safe and data-race-free (assuming no unsafe blocks). The key insight: Rust's type system encodes a linear type discipline where values are consumed exactly once, combined with a region-based memory model where borrows are valid for exactly their declared lifetime. The proof covers the entire Rust standard library's use of unsafe, verifying that all unsafe abstractions maintain the safety invariants expected by safe code.

unsafe Rust and the safety boundary

Rust has an unsafe keyword that unlocks five additional capabilities: dereferencing raw pointers, calling unsafe functions, accessing mutable static variables, implementing unsafe traits, and accessing union fields. The programmer asserts these operations are correct; the compiler stops verifying them. unsafe does not disable the borrow checker or type system generally — it only permits those five operations within the unsafe block. The fundamental contract: safe Rust code may call into unsafe abstractions; those abstractions are responsible for maintaining the invariants that make the rest of the code safe. The Rust standard library itself uses unsafe internally for performance-critical operations (e.g. Vec::push) while presenting a safe public API.

Rust in the Linux kernel and Windows

Rust was accepted into the Linux kernel in version 6.1 (December 2022) as a second implementation language alongside C (Linus Torvalds merged the initial support; Miguel Ojeda leads the effort). Rust code in the kernel must be no_std (no standard library) and operate within the kernel's custom allocator. Microsoft has been rewriting portions of the Windows NT kernel in Rust since 2023, starting with the kernel-mode driver infrastructure. Both efforts cite the same motivation: eliminating the memory safety vulnerabilities (use-after-free, buffer overflows) that account for the majority of CVEs in both kernels.

Specification reference

Klabnik, S. & Nichols, C. (2022). The Rust Programming Language (2nd ed.). No Starch Press. doc.rust-lang.org/book/. Jung, R. et al. (2017). "RustBelt: Securing the Foundations of the Rust Programming Language." POPL 2018. dl.acm.org/doi/10.1145/3158154. Rust Reference: doc.rust-lang.org/reference/. Rust Nomicon (unsafe Rust): doc.rust-lang.org/nomicon/.

Sources

1
Klabnik, S. & Nichols, C. (2022). The Rust Programming Language (2nd ed.). No Starch Press. doc.rust-lang.org/book/. — Authoritative Rust reference.
2
Jung, R. et al. (2017). "RustBelt: Securing the Foundations of the Rust Programming Language." POPL 2018. dl.acm.org/doi/10.1145/3158154.
3
The Rust Reference. doc.rust-lang.org/reference/. — Formal language reference.
4
The Rustonomicon. doc.rust-lang.org/nomicon/. — unsafe Rust guide.
5
Rust Foundation. The Rust Programming Language Blog. blog.rust-lang.org. — Announcement of Rust 1.0 (May 2015) and ongoing releases.
Source confidence: High Last verified: Primary source: The Rust Programming Language — doc.rust-lang.org/book/