| name | rust-unsafe |
| description | Work with unsafe Rust code safely, understand safety invariants, and review unsafe blocks. Use when writing unsafe code, reviewing unsafe blocks, understanding safety requirements, or working with FFI. Handles unsafe blocks, safety invariants, unsafe traits, and best practices for unsafe code. |
Unsafe Rust
Guidelines for working with unsafe Rust code safely and understanding safety invariants.
When to Use This Skill
- Writing unsafe code blocks
- Reviewing unsafe code for safety
- Understanding safety invariants
- Working with raw pointers
- Implementing unsafe traits
- Interfacing with FFI
Unsafe Operations
Unsafe Blocks
unsafe {
let raw_ptr = ptr::null_mut();
*raw_ptr = 42;
}
Unsafe Functions
pub fn safe_wrapper() {
unsafe {
}
}
pub unsafe fn unsafe_function(ptr: *mut i32) {
*ptr = 42;
}
Unsafe Traits
unsafe trait UnsafeTrait {
}
unsafe impl UnsafeTrait for MyType {
}
Safety Invariants
Pointer Validity
unsafe fn dereference_ptr(ptr: *const i32) -> i32 {
*ptr
}
pub fn safe_dereference(ptr: *const i32) -> Option<i32> {
if ptr.is_null() {
return None;
}
unsafe {
Some(*ptr)
}
}
Memory Safety
unsafe fn write_to_ptr(ptr: *mut i32, value: i32) {
*ptr = value;
}
Thread Safety
unsafe impl Send for MyType {
}
unsafe impl Sync for MyType {
}
Common Unsafe Patterns
Raw Pointers
use std::ptr;
unsafe fn manipulate_pointers() {
let mut value = 42;
let ptr: *mut i32 = &mut value;
unsafe {
*ptr = 100;
}
assert_eq!(value, 100);
}
Calling Unsafe Functions
extern "C" {
fn c_function(ptr: *mut i32) -> i32;
}
pub fn safe_wrapper(value: &mut i32) -> Result<i32> {
unsafe {
Ok(c_function(value as *mut i32))
}
}
Unsafe Traits
unsafe trait MarkerTrait {
}
unsafe impl MarkerTrait for MyType {
}
Safety Documentation
Documenting Safety Requirements
pub unsafe fn unsafe_operation(ptr: *mut i32) {
*ptr = 42;
}
Safety Comments
unsafe {
let value = *raw_ptr;
}
Best Practices
Minimize Unsafe Surface Area
pub fn safe_function(input: &[i32]) -> Vec<i32> {
let mut result = Vec::with_capacity(input.len());
unsafe {
let ptr = result.as_mut_ptr();
for (i, &value) in input.iter().enumerate() {
ptr.add(i).write(value);
}
result.set_len(input.len());
}
result
}
pub unsafe fn unsafe_function() {
}
Use Safe Abstractions
pub struct SafeWrapper {
inner: *mut CType,
}
impl SafeWrapper {
pub fn new() -> Self {
unsafe {
Self {
inner: c_create(),
}
}
}
pub fn get(&self) -> i32 {
unsafe {
c_get(self.inner)
}
}
}
impl Drop for SafeWrapper {
fn drop(&mut self) {
unsafe {
c_destroy(self.inner);
}
}
}
Validate Invariants
pub unsafe fn unsafe_operation(ptr: *mut i32, len: usize) {
assert!(!ptr.is_null(), "Pointer must not be null");
assert!(len > 0, "Length must be greater than 0");
for i in 0..len {
*ptr.add(i) = 0;
}
}
Important Rules
- Document safety requirements: Always document what callers must ensure
- Minimize unsafe scope: Keep unsafe blocks as small as possible
- Validate invariants: Check safety conditions before unsafe operations
- Use safe abstractions: Wrap unsafe code in safe APIs
- Review carefully: Unsafe code requires extra scrutiny
- Test thoroughly: Unsafe code needs comprehensive testing
Common Unsafe Operations
Dereferencing Raw Pointers
unsafe {
let value = *raw_ptr;
}
Calling Unsafe Functions
unsafe {
unsafe_function();
}
Accessing Static Mutables
static mut COUNTER: i32 = 0;
unsafe {
COUNTER += 1;
}
Implementing Unsafe Traits
unsafe impl Send for MyType {
}
Examples from Project
Look for unsafe code in:
- FFI bindings
- Performance-critical sections
- Low-level memory operations
- GPU operations (if using GPU features)
Safety Checklist
When writing unsafe code, ensure: