the rustonomicon is the official guide to unsafe rust. i read it cover to cover over two weeks, writing small programs to test each concept as i went. these are the notes that survived the exercise.
the rules of unsafe
unsafe rust gives you five superpowers: dereference a raw pointer, call an unsafe function, access a mutable static, implement an unsafe trait, and access fields of a union. everything else — the borrow checker, the type system, the lifetime elision — keeps working exactly as it does in safe rust.
the common misconception is that unsafe turns off the borrow checker. it does not. it only lifts the specific restrictions that would make certain low-level operations impossible. the borrow checker still enforces aliasing rules across the unsafe boundary.
here is the pattern that finally made this click:
unsafe fn write_to(slot: *mut i32, value: i32) {
// unsafe: caller promises slot is valid and aligned
*slot = value;
}
the unsafe keyword on the function pushes the safety invariant to the caller. the function itself is written assuming the invariant holds. this is the contract that every unsafe function negotiates with its callers.
what surprised me
the strict aliasing rules are stricter than i expected. rust’s type system assumes that references of different types never alias the same memory. violating this assumption — through pointer casting, for example — is immediate undefined behavior, even if the memory layout is compatible.
i wrote a small program that cast a *const u32 to *const f32 and read the same bytes as a float. this is undefined behavior. the correct approach is ptr::read_unaligned or core::mem::transmute, both of which tell the compiler exactly what you are doing.
the parts that aged best
the chapter on phantom data and drop check is the most practical section in the book. the PhantomData type tells the compiler about ownership relationships that cannot be expressed through concrete fields. every custom allocator, every intrusive data structure, every type-erased container uses this pattern.
the rule of thumb: if your type has a lifetime parameter but no reference to that lifetime in its fields, you need a PhantomData to tell the drop checker how the lifetimes relate.
takeaway
unsafe rust is not a free pass. it is a language for writing safe abstractions around operations that the compiler cannot prove correct. the best unsafe code is wrapped in safe functions with minimal surface area and exhaustive documentation of the safety invariants. the rustonomicon teaches you to write that kind of code.