liveBook · Manning

Unsafe Rust

As explained in Learn Rust in a Month of Lunches

Unsafe Rust is the part of Rust that permits operations whose memory-safety conditions cannot be fully verified by the compiler and therefore require programmer responsibility.

Rust normally checks rules that help prevent unsafe memory access. Some jobs need operations the compiler cannot verify: working with hardware memory addresses, calling functions from other languages, or accessing a mutable static. The `unsafe` keyword allows those operations, but it puts responsibility for their safety on the programmer. It does not mean every line inside an unsafe block is dangerous. section 16.4.1 section 16.4

Calling an unsafe function

An `unsafe fn` cannot be called like an ordinary function. A call to `unsafe fn uh_oh() {}` needs a block such as `unsafe { uh_oh(); }`. Without it, the compiler reports that the call requires an unsafe function or block. The block marks where you take responsibility; it does not prove the call is safe. section 16.4.1

A `static mut` is a static value that can be changed directly. Even reading one to print it requires an unsafe block. Why the caution? If two threads update the same value at once, both can read the old value and write back the same new value. A larger thread experiment produced different totals instead of the expected 1,000,000. Data races can cause undefined behavior; types such as `Arc<Mutex>` offer a safer way to coordinate access. section 16.4.2

error[E0133]: use of mutable static is unsafe and requires unsafe function
or block
 --> src/main.rs:4:5
  |
4 |     NUMBER += 1;
  |     ^^^^^^^^^^^ use of mutable static
  |
  = note: mutable statics can be mutated by multiple threads: aliasing
violations or data races will cause undefined behavior

The compiler error identifies the unguarded mutable-static access and explains the risk of data races and undefined behavior. section 16.4.2

Unsafe methods can also rely on a promise you must keep. `Option::unwrap_unchecked()` assumes the value is `Some`; using it on `None` causes undefined behavior. It is not guaranteed to be faster than the safe alternative. If ordinary safe Rust meets your needs, you may never need an unsafe block. section 16.4.4 section 16.4.1

fn main() {
    let my_option = Some(10);
    // SAFETY: my_option is declared as Some(10). It will never be None
    let unwrapped = unsafe {
        my_option.unwrap_unchecked()
    };
    println!("{unwrapped}");
}

The safety comment records why this particular unchecked unwrap is expected to receive `Some`. section 16.4.4

How Learn Rust in a Month of Lunches covers it

How deep it goes
Works through unsafe-function calls, compiler feedback, mutable-static races, and unchecked methods, but does not develop low-level safety proofs.
Examples
Uses an unsafe-function compiler error, concurrent increments of a mutable static, and `Option::unwrap_unchecked()` with a safety comment.
What it assumes
Builds on basic Rust functions, statics, and `Option`, while explaining why unsafe blocks are needed.
What you can do after
Diagnose/debug with compiler errors that require unsafe blocks, and evaluate whether an unchecked operation or mutable static is justified.
How it connects
Links unsafe blocks to mutable statics, undefined behavior, data races, threads, `Arc<Mutex>`, and foreign-language functions.

Also explained in

Compare how 4 books explain unsafe Rust →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.