Multi-page · for Rust engineers
Rust internals

Rust internals

The borrow checker, async state machines, trait objects, drop and RAII, memory layout, Send/Sync, smart pointers, monomorphisation, unsafe, the allocator API — and the chapter where ownership and async collide. Eleven mechanisms that decide how Rust programs actually behave at compile time and at runtime.

11 sub-pages, all live. Each is a long-form walkthrough with source links and references.


Deep dives

The mechanisms

01Live

The borrow checker

Non-lexical lifetimes, MIR, two-phase borrows. The mechanism that proves your program is memory-safe without a GC — at compile time, by tracking which references are live where.

MIR · NLL · two-phase borrows · borrow regions · polonius
Read
02Live

Async runtime & Pin

How async fn compiles to a state machine. The Future trait, Pin, Wakers, executors. Why tokio exists, what the runtime actually does, and what blocks it.

Future · Pin · Waker · state machine · tokio · executor
Read
03Live

Trait objects & vtables

dyn Trait is a fat pointer: data pointer + vtable pointer. Object safety, method dispatch costs, niche optimisations. The full mechanics of dynamic dispatch.

fat pointers · vtable · object safety · unsized types · dispatch cost
Read
04Live

Ownership meets async

Where the borrow checker and async state machines collide. Why Pin had to be invented, what Send/Sync actually constrain about a future, why spawn requires 'static, and how to read the famous "future cannot be sent between threads safely" error in one sentence.

Pin · Send/Sync · 'static on spawn · self-references · select! borrows
Read
05Live

Drop, RAII, and destructor order

How Drop runs deterministically. The destructor order rules, drop flags, the drop check, mem::forget, ManuallyDrop. RAII as the foundation that makes ownership work.

Drop trait · destructor order · drop check · leaks · ManuallyDrop
Read
06Live

Memory layout & #[repr]

How fields are laid out in memory. #[repr(Rust)] vs #[repr(C)] vs #[repr(transparent)]. Niche optimisations — why Option<&T> is one word, not two.

#[repr] · padding · alignment · niches · enum layout
Read
07Live

Send + Sync (auto-traits)

How auto-traits are derived, why Rc isn't Send, what Mutex<T: Send>: Sync means. The marker-trait machinery that makes data races a compile error.

auto-traits · Send · Sync · PhantomData · unsafe impl
Read
08Live

Box, Rc, Arc, RefCell, Cell

The standard smart pointers — what they own, how they count references, the interior-mutability story down to UnsafeCell. When to pick each; how they interact with the borrow checker.

Box · Rc · Arc · Cell · RefCell · Weak
Read
09Live

Generics & monomorphisation

How <T> compiles to a specialised function per concrete type. Zero-cost abstractions, the bill in binary size and compile time, the fate of polymorphisation, and when to reach for dyn instead.

monomorphisation · codegen units · polymorphisation · binary size · compile time
Read
10Live

Unsafe, raw pointers, UB

What unsafe actually permits, where the language relies on it (Vec, split_at_mut, FFI), and the rules you must uphold to avoid UB. Stacked and Tree Borrows, with miri as your testing tool.

unsafe · raw pointers · UB · stacked borrows · miri · FFI
Read
11Live

The allocator API

GlobalAlloc, the system allocator, swapping in jemalloc or mimalloc. OOM handling, the allocator-aware collections proposal, and why it matters for embedded and high-perf code.

GlobalAlloc · jemalloc · mimalloc · allocator_api · OOM
Read