use std::mem; use std::ptr::{self, addr_of}; fn basic_raw() { let mut x = 12; let x = &mut x; assert_eq!(*x, 12); let raw = x as *mut i32; unsafe { *raw = 42; } assert_eq!(*x, 42); let raw = x as *mut i32; unsafe { *raw = 12; } *x = 23; assert_eq!(*x, 23); } fn assign_overlapping() { // Test an assignment where LHS and RHS alias. // In Mir, that's UB (see `fail/overlapping_assignment.rs`), but in surface Rust this is allowed. let mut mem = [0u32; 4]; let ptr = &mut mem as *mut [u32; 4]; unsafe { *ptr = *ptr }; } fn deref_invalid() { unsafe { // `addr_of!(*ptr)` is never UB. let _val = addr_of!(*ptr::without_provenance::(0)); let _val = addr_of!(*ptr::without_provenance::(1)); // not aligned // Similarly, just mentioning the place is fine. let _ = *ptr::without_provenance::(0); let _ = *ptr::without_provenance::(1); } } fn deref_partially_dangling() { let x = (1, 13); let xptr = &x as *const _ as *const (i32, i32, i32); let val = unsafe { (*xptr).1 }; assert_eq!(val, 13); } fn deref_too_big_slice() { unsafe { let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); // `&*slice` would complain that the slice is too big, but in a raw pointer this is fine. let _val = addr_of!(*slice); } } fn main() { basic_raw(); assign_overlapping(); deref_invalid(); deref_partially_dangling(); deref_too_big_slice(); }