01 — ownership
Every value has one owner; borrowing is checked at compile time — use-after-free cannot exist.
let ships = vec!["perch", "sundial"];
let first = &ships[0];
// ships.push("graymail"); // ✗ borrow in use
println!("{first}");← the guideMulticore & Missions
§ 02 — Eras · 2015
memory safety without a garbage collector
Left: era context, features, and the 101 hello. Right: 3 core concepts, 4 deeper 201 lessons, the factorial specimen, and where Rust lives today — each column scrolls on its own.
Systems code without memory bugs: ownership instead of garbage collection, safety without a runtime tax.
The borrow checker’s learning curve — months of fighting the compiler — and compile times that reward patience.
Session one is the smallest program that still counts as speaking Rust: what every tutorial prints first, in the dialect that mattered when the language arrived (2015).
fn main() {
println!("Hello, world");
}101First contact — hello world and 3 ideas that define how Rust reads. 201 — 4 lessons on mechanisms you meet after the factorial specimen: the sharp edges practitioners actually use.
3 fragments, each naming a habit of mind in Rust. Read the note, then the code — together they are the 101 in one sitting.
01 — ownership
Every value has one owner; borrowing is checked at compile time — use-after-free cannot exist.
let ships = vec!["perch", "sundial"];
let first = &ships[0];
// ships.push("graymail"); // ✗ borrow in use
println!("{first}");02 — enums & match
Sum types plus exhaustive matching — errors become part of the type.
enum Result { Ok(i64), Err(String) }
match fact(5) {
Result::Ok(n) => println!("{n}"),
Result::Err(e) => eprintln!("{e}"),
}03 — traits
Shared behavior without inheritance; generics monomorphize to zero cost.
trait Tonnage {
fn tons(&self) -> u32;
}
impl Tonnage for Ship {
fn tons(&self) -> u32 { self.weight }
}The 201 assumes you have read the 101 and the specimen. Each lesson is one mechanism — what it is for, how it looks in code, and the trap or payoff that makes Rust distinctive at scale.
A lifetime annotation says how long a reference must stay valid; the compiler proves it, and elision means you rarely write one by hand.
fn longest<'a>(a: &'a str, b: &'a str) -> &'a str {
if a.len() > b.len() { a } else { b }
}Generics dispatch statically and cost nothing; trait objects dispatch dynamically and cost one pointer. The choice is a design decision, not an optimization.
fn draw_all(items: &[Box<dyn Draw>]) { ... } // dynamic
fn draw_one<T: Draw>(item: &T) { ... } // staticResult with the ? operator keeps error paths short; thiserror for libraries, anyhow for applications.
fn parse(s: &str) -> Result<i32, ParseError> {
let n = s.parse().map_err(ParseError::Num)?;
Ok(n)
}Holding a borrow across an await is usually wrong; that is why async blocks are their own futures, and why Send bounds appear in signatures.
let data = reqwest::get(url).await?.text().await?;The borrow: every value has one owner, every reference a lease — memory safety without a garbage collector, enforced before the program exists.
let ships = vec!["perch", "sundial"];
let first = &ships[0];
// ships.push("graymail"); // error: borrow in use
println!("{first}");installbrew install rust
runrustc fact.rs -o fact && ./fact
In the Linux kernel, Firefox’s engine, Cloudflare’s edge, Discord’s hot paths — and it is Stack Overflow’s most-loved language, a decade running.