πŸ¦€

A language tour

The Safety of Rust

Memory safety without a garbage collector. Speed without undefined behaviour. The compiler as your partner.

scroll

01 β€” Ownership

Every value has exactly one owner

Rust's ownership system is its defining idea. Every piece of data has exactly one owner. When the owner goes out of scope, the data is freed. No garbage collector, no double-free, no use-after-free β€” guaranteed by the compiler.

"Rust gives you the choice between a safe, idiomatic form and a fast, machine-close form. You shouldn't need to choose one and sacrifice the other."

β€” The Rust Book
ownership.rs
fn main() {
    let s1 = String::from("hello");

    // Move: s1 is no longer valid β€” ownership transferred to s2
    let s2 = s1;
    // println!("{}", s1);  ← compile error: value moved
    println!("{}", s2);  // s2 is valid

    // Clone: explicit deep copy when you need two owners
    let s3 = s2.clone();
    println!("{} and {}", s2, s3);  // both valid

    // s2 and s3 are freed here β€” automatically, deterministically
}
// Copy types (i32, bool, f64) are cloned implicitly β€” they're cheap

Move semantics are not a performance optimisation in Rust β€” they're the mechanism that guarantees memory safety. The compiler tracks every value's owner at compile time, with zero runtime overhead.


02 β€” Borrowing

References without danger

Borrowing lets you use a value without taking ownership. The borrow checker enforces one rule: you can have many shared references, or one exclusive reference β€” never both at the same time. This eliminates data races at compile time.

borrowing.rs
fn length(s: &String) -> usize {
    s.len()  // borrows s, does not take ownership
}

fn first_word(s: &str) -> &str {
    let bytes = s.as_bytes();
    for (i, &byte) in bytes.iter().enumerate() {
        if byte == b' ' { return &s[..i]; }
    }
    &s[..]
}

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);  // immutable borrow
    // s.clear();  ← compile error: can't mutate while borrowed
    println!("first word: {word}");
}

The borrow checker ensures that word (a slice into s) cannot outlive s, and that s cannot be modified while word exists. Iterator invalidation bugs are impossible by construction.


03 β€” Result & Option

Errors and nulls as types

Rust has no null and no exceptions. Option<T> replaces null; Result<T, E> replaces exceptions. The compiler forces you to handle both cases. The ? operator propagates errors ergonomically without hiding them.

result.rs
use std::{fs, io};

fn read_username(path: &str) -> Result<String, io::Error> {
    let content = fs::read_to_string(path)?;  // ? propagates error
    let name = content.lines().next()
        .map(str::to_string)
        .ok_or(io::Error::other("empty file"))?;
    Ok(name)
}

fn main() {
    match read_username("user.txt") {
        Ok(name) => println!("Hello, {name}!"),
        Err(e)   => eprintln!("Error: {e}"),
    }
}

The ? operator desugars to: if this is Err, return that error from the current function; otherwise, unwrap the Ok value. It's monadic error propagation with no boilerplate.


04 β€” Traits

Shared behaviour, zero overhead

Traits define shared behaviour without inheritance. Implement a trait for any type β€” even types you don't own. Combined with monomorphisation, trait dispatch compiles to direct function calls, not virtual dispatch.

traits.rs
trait Area {
    fn area(&self) -> f64;
}

struct Circle   { radius: f64 }
struct Rectangle { w: f64, h: f64 }

impl Area for Circle    { fn area(&self) -> f64 { std::f64::consts::PI * self.radius.powi(2) } }
impl Area for Rectangle { fn area(&self) -> f64 { self.w * self.h } }

// Generic function β€” monomorphised at compile time, zero overhead
fn print_area<T: Area>(shape: &T) {
    println!("Area: {:.2}", shape.area());
}

fn main() {
    print_area(&Circle { radius: 5.0 });     // 78.54
    print_area(&Rectangle { w: 3.0, h: 4.0 }); // 12.00
}

The compiler generates two versions of print_area β€” one for Circle, one for Rectangle. Each is a direct function call. No vtable, no pointer indirection, no cache miss.


05 β€” Fearless Concurrency

Data races are impossible

The same ownership rules that prevent memory errors also prevent data races. If you can share data between threads, it's because the type system guarantees it's safe to do so. Rust threads don't just run fast β€” they run correctly.

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

fn main() {
    // Arc = atomically reference counted (shared ownership across threads)
    // Mutex = mutual exclusion β€” only one thread writes at a time
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

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

    for h in handles { h.join().unwrap(); }
    println!("{}", counter.lock().unwrap());  // always 10
}

You can't share &mut T between threads unless T: Send + Sync. The compiler verifies these traits at every thread boundary. Writing a data race is a compile error, not a runtime mystery.


06 β€” The Whole Picture

Why Rust is beloved

πŸ†

Most Loved Language

Stack Overflow's developer survey named Rust the most loved language nine years in a row. Developers who use it don't want to stop.

🌐

In the Linux Kernel

Rust is now an officially supported language for Linux kernel development β€” the first new language accepted in decades.

πŸ•ΈοΈ

WebAssembly

Rust is the premier language for WebAssembly. wasm-pack makes it trivial to compile Rust to run in the browser.

πŸ“¦

Cargo

Rust's package manager is widely considered the best in any language. Build, test, publish, document β€” all from one tool.

⚑

Async/Await

Rust's async model is zero-cost β€” futures compile to state machines with no heap allocation or runtime overhead.

πŸ”’

No Undefined Behaviour

Safe Rust has no undefined behaviour. The entire class of UB exploits that plague C and C++ simply do not exist.