// compile-flags: -Zmiri-track-raw-pointers use std::ptr; // Test various stacked-borrows-related things. fn main() { read_does_not_invalidate1(); read_does_not_invalidate2(); mut_raw_then_mut_shr(); mut_shr_then_mut_raw(); mut_raw_mut(); partially_invalidate_mut(); drop_after_sharing(); direct_mut_to_const_raw(); two_raw(); shr_and_raw(); disjoint_mutable_subborrows(); raw_ref_to_part(); array_casts(); } // Make sure that reading from an `&mut` does, like reborrowing to `&`, // NOT invalidate other reborrows. fn read_does_not_invalidate1() { fn foo(x: &mut (i32, i32)) -> &i32 { let xraw = x as *mut (i32, i32); let ret = unsafe { &(*xraw).1 }; let _val = x.1; // we just read, this does NOT invalidate the reborrows. ret } assert_eq!(*foo(&mut (1, 2)), 2); } // Same as above, but this time we first create a raw, then read from `&mut` // and then freeze from the raw. fn read_does_not_invalidate2() { fn foo(x: &mut (i32, i32)) -> &i32 { let xraw = x as *mut (i32, i32); let _val = x.1; // we just read, this does NOT invalidate the raw reborrow. let ret = unsafe { &(*xraw).1 }; ret } assert_eq!(*foo(&mut (1, 2)), 2); } // Escape a mut to raw, then share the same mut and use the share, then the raw. // That should work. fn mut_raw_then_mut_shr() { let mut x = 2; let xref = &mut x; let xraw = &mut *xref as *mut _; let xshr = &*xref; assert_eq!(*xshr, 2); unsafe { *xraw = 4; } assert_eq!(x, 4); } // Create first a shared reference and then a raw pointer from a `&mut` // should permit mutation through that raw pointer. fn mut_shr_then_mut_raw() { let xref = &mut 2; let _xshr = &*xref; let xraw = xref as *mut _; unsafe { *xraw = 3; } assert_eq!(*xref, 3); } // Ensure that if we derive from a mut a raw, and then from that a mut, // and then read through the original mut, that does not invalidate the raw. // This shows that the read-exception for `&mut` applies even if the `Shr` item // on the stack is not at the top. fn mut_raw_mut() { let mut x = 2; { let xref1 = &mut x; let xraw = xref1 as *mut _; let _xref2 = unsafe { &mut *xraw }; let _val = *xref1; unsafe { *xraw = 4; } // we can now use both xraw and xref1, for reading assert_eq!(*xref1, 4); assert_eq!(unsafe { *xraw }, 4); assert_eq!(*xref1, 4); assert_eq!(unsafe { *xraw }, 4); // we cannot use xref2; see `compile-fail/stacked-borows/illegal_read4.rs` } assert_eq!(x, 4); } fn partially_invalidate_mut() { let data = &mut (0u8, 0u8); let reborrow = &mut *data as *mut (u8, u8); let shard = unsafe { &mut (*reborrow).0 }; data.1 += 1; // the deref overlaps with `shard`, but that is ok; the access does not overlap. *shard += 1; // so we can still use `shard`. assert_eq!(*data, (1, 1)); } // Make sure that we can handle the situation where a loaction is frozen when being dropped. fn drop_after_sharing() { let x = String::from("hello!"); let _len = x.len(); } // Make sure that coercing &mut T to *const T produces a writeable pointer. fn direct_mut_to_const_raw() { // TODO: This is currently disabled, waiting on a decision on /*let x = &mut 0; let y: *const i32 = x; unsafe { *(y as *mut i32) = 1; } assert_eq!(*x, 1); */ } // Make sure that we can create two raw pointers from a mutable reference and use them both. fn two_raw() { unsafe { let x = &mut 0; let y1 = x as *mut _; let y2 = x as *mut _; *y1 += 2; *y2 += 1; } } // Make sure that creating a *mut does not invalidate existing shared references. fn shr_and_raw() { unsafe { use std::mem; let x = &mut 0; let y1: &i32 = mem::transmute(&*x); // launder lifetimes let y2 = x as *mut _; let _val = *y1; *y2 += 1; } } fn disjoint_mutable_subborrows() { struct Foo { a: String, b: Vec, } unsafe fn borrow_field_a<'a>(this:*mut Foo) -> &'a mut String { &mut (*this).a } unsafe fn borrow_field_b<'a>(this:*mut Foo) -> &'a mut Vec { &mut (*this).b } let mut foo = Foo { a: "hello".into(), b: vec![0,1,2], }; let ptr = &mut foo as *mut Foo; let a = unsafe{ borrow_field_a(ptr) }; let b = unsafe{ borrow_field_b(ptr) }; b.push(4); a.push_str(" world"); eprintln!("{:?} {:?}", a, b); } fn raw_ref_to_part() { struct Part { _lame: i32, } #[repr(C)] struct Whole { part: Part, extra: i32, } let it = Box::new(Whole { part: Part { _lame: 0 }, extra: 42 }); let whole = ptr::addr_of_mut!(*Box::leak(it)); let part = unsafe { ptr::addr_of_mut!((*whole).part) }; let typed = unsafe { &mut *(part as *mut Whole) }; assert!(typed.extra == 42); drop(unsafe { Box::from_raw(whole) }); } /// When casting an array reference to a raw element ptr, that should cover the whole array. fn array_casts() { let mut x: [usize; 2] = [0, 0]; let p = &mut x as *mut usize; unsafe { *p.add(1) = 1; } let x: [usize; 2] = [0, 1]; let p = &x as *const usize; assert_eq!(unsafe { *p.add(1) }, 1); }