29
Unsafe
unsafe is not a magic word that turns off the borrow checker. It enables exactly five operations that the compiler can't prove sound: dereferencing raw pointers, calling unsafe functions, mutating statics, implementing unsafe traits, and reading union fields. Aliasing rules, lifetime rules, and the abstract machine still apply. You're promising to uphold them yourself.
- The five superpowers, in canonical order: deref
*mut T/*const T, callunsafe fn, accessstatic mut, implementunsafe trait, access fields of aunion. Anything else inside anunsafeblock is checked exactly as it would be in safe Rust.unsafe { let p: *mut i32 = some_raw_pointer(); let v = *p; // 1. dereference raw pointer do_unsafe_thing(); // 2. call unsafe fn // 3. static mut // 4. impl unsafe trait // 5. union field access } - The contract
unsafedoes not relax: you still cannot have a&mut Taliased by another&or&mutto the same memory at the same time. You still cannot produce a dangling reference, even briefly. Stacked borrows formalizes "at the same time" — coming up two sections from now.// safe code, undefined behavior: let mut x = 0i32; let r: &mut i32 = &mut x; let p: *mut i32 = r as *mut i32; unsafe { *p = 1; // OK — derived from r, r still active *r = 2; // OK *p = 3; // UB — using p after writing through r invalidates p }