//@ check-fail extern "C" { // N.B., mutability can be easily incorrect in FFI calls -- as // in C, the default is mutable pointers. fn ffi(c: *mut u8); fn int_ffi(c: *mut i32); } fn static_u8() -> &'static u8 { &8 } unsafe fn ref_to_mut() { let num = &3i32; let _num = &mut *(num as *const i32 as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(num as *const i32).cast_mut(); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::ptr::from_ref(num).cast_mut(); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::ptr::from_ref({ num }).cast_mut(); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut(); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(num as *const i32).cast::().cast_mut(); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(num as *const i32).cast::().cast_mut().cast_const().cast_mut(); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(std::ptr::from_ref(static_u8()) as *mut i8); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::mem::transmute::<_, *mut i32>(num); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *std::cell::UnsafeCell::raw_get( //~^ ERROR casting `&T` to `&mut T` is undefined behavior num as *const i32 as *const std::cell::UnsafeCell ); let deferred = num as *const i32 as *mut i32; let _num = &mut *deferred; //~^ ERROR casting `&T` to `&mut T` is undefined behavior let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32; let _num = &mut *deferred; //~^ ERROR casting `&T` to `&mut T` is undefined behavior let deferred_rebind = deferred; let _num = &mut *deferred_rebind; //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(num as *const _ as usize as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior static NUM: &'static i32 = &2; let num = NUM as *const i32 as *mut i32; let num = num; let num = num; let _num = &mut *num; //~^ ERROR casting `&T` to `&mut T` is undefined behavior let cell = &std::cell::UnsafeCell::new(0); let _num = &mut *(cell as *const _ as *mut i32); //~^ ERROR casting `&T` to `&mut T` is undefined behavior unsafe fn generic_ref_cast_mut(this: &T) -> &mut T { &mut *((this as *const _) as *mut _) //~^ ERROR casting `&T` to `&mut T` is undefined behavior } fn as_mut(x: &T) -> &mut T { unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } //~^ ERROR casting `&T` to `&mut T` is undefined behavior } fn as_mut_i32(x: &i32) -> &mut i32 { unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } //~^ ERROR casting `&T` to `&mut T` is undefined behavior } } unsafe fn assign_to_ref() { let s = String::from("Hello"); let a = &s; let num = &3i32; *(a as *const _ as *mut _) = String::from("Replaced"); //~^ ERROR assigning to `&T` is undefined behavior *(a as *const _ as *mut String) += " world"; //~^ ERROR assigning to `&T` is undefined behavior *std::ptr::from_ref(num).cast_mut() += 1; //~^ ERROR assigning to `&T` is undefined behavior *std::ptr::from_ref({ num }).cast_mut() += 1; //~^ ERROR assigning to `&T` is undefined behavior *{ std::ptr::from_ref(num) }.cast_mut() += 1; //~^ ERROR assigning to `&T` is undefined behavior *(std::ptr::from_ref({ num }) as *mut i32) += 1; //~^ ERROR assigning to `&T` is undefined behavior *std::mem::transmute::<_, *mut i32>(num) += 1; //~^ ERROR assigning to `&T` is undefined behavior *(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1; //~^ ERROR assigning to `&T` is undefined behavior std::ptr::write( //~^ ERROR assigning to `&T` is undefined behavior std::mem::transmute::<*const i32, *mut i32>(num), -1i32, ); *((&std::cell::UnsafeCell::new(0)) as *const _ as *mut i32) = 5; //~^ ERROR assigning to `&T` is undefined behavior let value = num as *const i32 as *mut i32; *value = 1; //~^ ERROR assigning to `&T` is undefined behavior let value = num as *const i32; let value = value as *mut i32; *value = 1; //~^ ERROR assigning to `&T` is undefined behavior let value = num as *const i32 as *mut i32; *value = 1; //~^ ERROR assigning to `&T` is undefined behavior let value_rebind = value; *value_rebind = 1; //~^ ERROR assigning to `&T` is undefined behavior *(num as *const i32).cast::().cast_mut() = 2; //~^ ERROR assigning to `&T` is undefined behavior *(num as *const _ as usize as *mut i32) = 2; //~^ ERROR assigning to `&T` is undefined behavior std::ptr::write(value, 2); //~^ ERROR assigning to `&T` is undefined behavior std::ptr::write_unaligned(value, 2); //~^ ERROR assigning to `&T` is undefined behavior std::ptr::write_volatile(value, 2); //~^ ERROR assigning to `&T` is undefined behavior unsafe fn generic_assign_to_ref(this: &T, a: T) { *(this as *const _ as *mut _) = a; //~^ ERROR assigning to `&T` is undefined behavior } } #[repr(align(16))] struct I64(i64); #[repr(C)] struct Mat3 { a: Vec3, b: Vec3, c: Vec3, } #[repr(C)] struct Vec3(T, T, T); unsafe fn bigger_layout() { { let num = &mut 3i32; let _num = &*(num as *const i32 as *const i64); //~^ ERROR casting references to a bigger memory layout let _num = &mut *(num as *mut i32 as *mut i64); //~^ ERROR casting references to a bigger memory layout let _num = &mut *(num as *mut i32 as *mut I64); //~^ ERROR casting references to a bigger memory layout std::ptr::write(num as *mut i32 as *mut i64, 2); //~^ ERROR casting references to a bigger memory layout let _num = &mut *(num as *mut i32); } { let num = &mut [0i32; 3]; let _num = &mut *(num as *mut _ as *mut [i64; 2]); //~^ ERROR casting references to a bigger memory layout std::ptr::write_unaligned(num as *mut _ as *mut [i32; 4], [0, 0, 1, 1]); //~^ ERROR casting references to a bigger memory layout let _num = &mut *(num as *mut _ as *mut [u32; 3]); let _num = &mut *(num as *mut _ as *mut [u32; 2]); } { let num = &mut [0i32; 3] as &mut [i32]; let _num = &mut *(num as *mut _ as *mut i128); //~^ ERROR casting references to a bigger memory layout let _num = &mut *(num as *mut _ as *mut [i64; 4]); //~^ ERROR casting references to a bigger memory layout let _num = &mut *(num as *mut _ as *mut [u32]); let _num = &mut *(num as *mut _ as *mut [i16]); } { let mat3 = Mat3 { a: Vec3(0i32, 0, 0), b: Vec3(0, 0, 0), c: Vec3(0, 0, 0) }; let _num = &mut *(&mat3 as *const _ as *mut [[i64; 3]; 3]); //~^ ERROR casting `&T` to `&mut T` //~^^ ERROR casting references to a bigger memory layout let _num = &*(&mat3 as *const _ as *mut [[i64; 3]; 3]); //~^ ERROR casting references to a bigger memory layout let _num = &*(&mat3 as *const _ as *mut [[i32; 3]; 3]); } { let mut l: [u8; 2] = [0,1]; let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _; let w: *mut [u16] = unsafe {&mut *w}; //~^ ERROR casting references to a bigger memory layout } { fn foo() -> [i32; 1] { todo!() } let num = foo(); let _num = &*(&num as *const i32 as *const i64); //~^ ERROR casting references to a bigger memory layout let _num = &*(&foo() as *const i32 as *const i64); //~^ ERROR casting references to a bigger memory layout } { fn bar(_a: &[i32; 2]) -> &[i32; 1] { todo!() } let num = bar(&[0, 0]); let _num = &*(num as *const i32 as *const i64); let _num = &*(bar(&[0, 0]) as *const i32 as *const i64); } { fn foi() -> T { todo!() } let num = foi::(); let _num = &*(&num as *const i32 as *const i64); //~^ ERROR casting references to a bigger memory layout } { let x: Box = Box::new(0i32); let _z = unsafe { &*(&*x as *const dyn Send as *const i32) }; } unsafe fn from_ref(this: &i32) -> &i64 { &*(this as *const i32 as *const i64) } } const RAW_PTR: *mut u8 = 1 as *mut u8; unsafe fn no_warn() { let num = &3i32; let mut_num = &mut 3i32; let a = &String::from("ffi"); *(num as *const i32 as *mut i32); println!("{}", *(num as *const _ as *const i16)); println!("{}", *(mut_num as *mut _ as *mut i16)); ffi(a.as_ptr() as *mut _); int_ffi(num as *const _ as *mut _); int_ffi(&3 as *const _ as *mut _); let mut value = 3; let value: *const i32 = &mut value; *(value as *const i16 as *mut i16) = 42; *RAW_PTR = 42; // RAW_PTR is defined outside the function body, // make sure we don't ICE on it when trying to // determine if we should lint on it or not. let cell = &std::cell::UnsafeCell::new(0); let _num = &mut *(cell.get() as *mut i32); fn safe_as_mut(x: &std::cell::UnsafeCell) -> &mut T { unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } } fn cell_as_mut(x: &std::cell::Cell) -> &mut i32 { unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } } #[repr(transparent)] struct DoesContainUnsafeCell(std::cell::UnsafeCell); fn safe_as_mut2(x: &DoesContainUnsafeCell) -> &mut DoesContainUnsafeCell { unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) } } } fn main() {}