Unsafe Rust

unsafe is an escape hatch that tells the compiler you’ve manually verified code the borrow checker cannot.

Why does it exist?

The compiler prefers rejecting a correct program over accepting an incorrect one. Sometimes you genuinely need low-level tricks (FFI, memory-mapped I/O, type punning) that the compiler can’t verify. Get it wrong and you get every bug Rust tries to avoid: UB, races, segfaults, leaks.

Inside an unsafe block you can do five things normally forbidden:

  1. Call an unsafe function/method
  2. Access or modify a mutable static variable
  3. Implement an unsafe trait
  4. Access the fields of a union
  5. Dereference a raw pointer

unsafe is narrower than people think

The borrow checker still runs inside unsafe blocks. You don’t get to ignore the rules, you just get five extra operations.

Conventions:

  • Keep unsafe blocks small and document their safety conditions
  • An unsafe function says “caller is responsible for safety conditions”; calling one requires its own unsafe { ... } wrapper
  • Raw pointers can be created anywhere but dereferencing requires unsafe
  • Common uses: FFI into C, writing to specific memory addresses (memory-mapped I/O), unions

unsafe is not a rubber stamp

Wrapping a call in unsafe { ... } makes the compiler quiet but doesn’t prove correctness. A thorough reviewer still asks whether you read the function’s safety docs.