Unsafe Basics
unsafe is a special zone where Rust trusts you to follow the safety rules yourself, since it can't check everything there.In this page:
unsafe {
// operations the compiler cannot verify
}
unsafe fn name() {}
What unsafe Unlocks
An unsafe block allows a small set of extra operations, such as dereferencing raw pointers or calling unsafe functions, that the compiler cannot fully verify are safe on its own.
Example: What unsafe Unlocks
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `value`, set to `10`
let value = 10;
// Declare an immutable variable `raw_pointer`, set to `&value as *const i32`
let raw_pointer = &value as *const i32;
unsafe {
// Print "Value through raw pointer: {}" to the console, substituting in `*raw_pointer` (with a trailing newline)
println!("Value through raw pointer: {}", *raw_pointer);
}
}
Login to try C/C++/Java/PHP code in the editor
Calling an Unsafe Function
Functions marked unsafe fn can only be called from inside an unsafe block, signaling that the caller must uphold certain safety guarantees the function relies on.
Example: Calling an Unsafe Function
unsafe fn dangerous_operation() -> i32 {
42
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `result`, set to `unsafe { dangerous_operation() }`
let result = unsafe { dangerous_operation() };
// Print "Result: {}" to the console, substituting in `result` (with a trailing newline)
println!("Result: {}", result);
}
Login to try C/C++/Java/PHP code in the editor
Safe Rust Still Applies Around unsafe
Code outside an unsafe block, and even most code inside it, still follows all of Rust's normal type checking and ownership rules -- unsafe only lifts a few specific restrictions.
Example: Safe Rust Still Applies Around unsafe
// Entry point: execution of the program starts here
fn main() {
// Declare a mutable variable `value`, initialized to `5`
let mut value = 5;
{
// Declare an immutable variable `pointer`, set to `&mut value as *mut i32`
let pointer = &mut value as *mut i32;
unsafe {
*pointer += 10;
}
}
// Print "value = {}" to the console, substituting in `value` (with a trailing newline)
println!("value = {}", value);
}
Login to try C/C++/Java/PHP code in the editor
Wrapping unsafe in a Safe API
A common pattern is to keep unsafe code small and private, exposing only a safe public function that guarantees its preconditions are met before using the unsafe operation internally.
Example: Wrapping unsafe in a Safe API
// Define the function `safe_get` taking `arr`, `index` and returning a `Option<i32>`
fn safe_get(arr: &[i32], index: usize) -> Option<i32> {
// Check whether `index < arr.len()`
if index < arr.len() {
Some(unsafe { *arr.get_unchecked(index) })
// Otherwise, run this branch
} else {
None
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `data`, set to `[1, 2, 3]`
let data = [1, 2, 3];
// Print "{:?}" to the console, substituting in `safe_get(&data, 1)` (with a trailing newline)
println!("{:?}", safe_get(&data, 1));
// Print "{:?}" to the console, substituting in `safe_get(&data, 10)` (with a trailing newline)
println!("{:?}", safe_get(&data, 10));
}
Login to try C/C++/Java/PHP code in the editor
- Reaching for
unsafeto fix an ordinary borrow-checker error, when the real fix is almost always restructuring the safe code. - Assuming
unsafeturns off all of Rust's checks -- it only unlocks a small specific set of extra abilities, like dereferencing raw pointers. - Writing a large
unsafeblock when only one specific line actually needs the extra capability, making it harder to audit.
unsafeblocks unlock a small set of extra abilities not allowed in safe Rust, such as dereferencing raw pointers.- Using
unsafedoes not disable the borrow checker or type checking elsewhere in the code. - Safe abstractions are often built around a small
unsafecore, exposing a fully safe API to callers. unsafeshould be used sparingly and kept as small as possible to make manual review easier.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: