25.1 Overview of Unsafe Rust
25.1.1 What Is Unsafe Rust?
In safe Rust, the compiler prevents problems like data races, invalid memory access, and dangling pointers. However, there are situations where the compiler cannot confirm that an operation is safeāeven if the operation is correct when used carefully. This is when unsafe Rust comes into play.
Unsafe Rust permits five operations that safe Rust forbids:
- Dereferencing raw pointers (
*const T
and*mut T
). - Calling unsafe functions (including foreign C functions).
- Accessing and modifying mutable static variables.
- Implementing unsafe traits.
- Accessing union fields.
Aside from these operations, Rust's usual rules regarding ownership, borrowing, and type checking still apply. Unsafe Rust does not turn off all safety checks. It only relaxes restrictions on the five operations listed above.
25.1.2 Why Do We Need Unsafe Code?
Rust is designed to support low-level systems programming while maintaining high safety standards. Nevertheless, certain scenarios demand unsafe code:
- Hardware Interaction: Accessing memory-mapped I/O or device registers requires direct hardware manipulation, which is inherently unsafe.
- Foreign Function Interface (FFI): Interacting with C or other languages that do not preserve Rust's safety invariants.
- Advanced Data Structures: Implementing intrusive linked lists or lock-free structures may involve operations not expressible in safe Rust.
- Performance Optimizations: Specialized optimizations can require pointer arithmetic or custom memory layouts that exceed safe abstractions.
Because the compiler cannot verify correctness in these contexts, you must manually ensure that the code maintains all necessary safety properties.