1 //@compile-flags: -Zmiri-retag-fields
2 #![feature(allocator_api)]
5 // Test various stacked-borrows-related things.
7 read_does_not_invalidate1();
8 read_does_not_invalidate2();
9 mut_raw_then_mut_shr();
10 mut_shr_then_mut_raw();
12 partially_invalidate_mut();
14 direct_mut_to_const_raw();
17 disjoint_mutable_subborrows();
21 wide_raw_ptr_in_tuple();
24 // Make sure that reading from an `&mut` does, like reborrowing to `&`,
25 // NOT invalidate other reborrows.
26 fn read_does_not_invalidate1() {
27 fn foo(x: &mut (i32, i32)) -> &i32 {
28 let xraw = x as *mut (i32, i32);
29 let ret = unsafe { &(*xraw).1 };
30 let _val = x.1; // we just read, this does NOT invalidate the reborrows.
33 assert_eq!(*foo(&mut (1, 2)), 2);
35 // Same as above, but this time we first create a raw, then read from `&mut`
36 // and then freeze from the raw.
37 fn read_does_not_invalidate2() {
38 fn foo(x: &mut (i32, i32)) -> &i32 {
39 let xraw = x as *mut (i32, i32);
40 let _val = x.1; // we just read, this does NOT invalidate the raw reborrow.
41 let ret = unsafe { &(*xraw).1 };
44 assert_eq!(*foo(&mut (1, 2)), 2);
47 // Escape a mut to raw, then share the same mut and use the share, then the raw.
49 fn mut_raw_then_mut_shr() {
52 let xraw = &mut *xref as *mut _;
61 // Create first a shared reference and then a raw pointer from a `&mut`
62 // should permit mutation through that raw pointer.
63 fn mut_shr_then_mut_raw() {
66 let xraw = xref as *mut _;
73 // Ensure that if we derive from a mut a raw, and then from that a mut,
74 // and then read through the original mut, that does not invalidate the raw.
75 // This shows that the read-exception for `&mut` applies even if the `Shr` item
76 // on the stack is not at the top.
81 let xraw = xref1 as *mut _;
82 let _xref2 = unsafe { &mut *xraw };
87 // we can now use both xraw and xref1, for reading
88 assert_eq!(*xref1, 4);
89 assert_eq!(unsafe { *xraw }, 4);
90 assert_eq!(*xref1, 4);
91 assert_eq!(unsafe { *xraw }, 4);
92 // we cannot use xref2; see `compile-fail/stacked-borows/illegal_read4.rs`
97 fn partially_invalidate_mut() {
98 let data = &mut (0u8, 0u8);
99 let reborrow = &mut *data as *mut (u8, u8);
100 let shard = unsafe { &mut (*reborrow).0 };
101 data.1 += 1; // the deref overlaps with `shard`, but that is ok; the access does not overlap.
102 *shard += 1; // so we can still use `shard`.
103 assert_eq!(*data, (1, 1));
106 // Make sure that we can handle the situation where a loaction is frozen when being dropped.
107 fn drop_after_sharing() {
108 let x = String::from("hello!");
112 // Make sure that coercing &mut T to *const T produces a writeable pointer.
113 fn direct_mut_to_const_raw() {
114 // TODO: This is currently disabled, waiting on a decision on <https://github.com/rust-lang/rust/issues/56604>
116 let y: *const i32 = x;
117 unsafe { *(y as *mut i32) = 1; }
122 // Make sure that we can create two raw pointers from a mutable reference and use them both.
126 let y1 = x as *mut _;
127 let y2 = x as *mut _;
133 // Make sure that creating a *mut does not invalidate existing shared references.
138 let y1: &i32 = mem::transmute(&*x); // launder lifetimes
139 let y2 = x as *mut _;
145 fn disjoint_mutable_subborrows() {
151 unsafe fn borrow_field_a<'a>(this: *mut Foo) -> &'a mut String {
155 unsafe fn borrow_field_b<'a>(this: *mut Foo) -> &'a mut Vec<u32> {
159 let mut foo = Foo { a: "hello".into(), b: vec![0, 1, 2] };
161 let ptr = &mut foo as *mut Foo;
163 let a = unsafe { borrow_field_a(ptr) };
164 let b = unsafe { borrow_field_b(ptr) };
166 a.push_str(" world");
167 eprintln!("{:?} {:?}", a, b);
170 fn raw_ref_to_part() {
181 let it = Box::new(Whole { part: Part { _lame: 0 }, extra: 42 });
182 let whole = ptr::addr_of_mut!(*Box::leak(it));
183 let part = unsafe { ptr::addr_of_mut!((*whole).part) };
184 let typed = unsafe { &mut *(part as *mut Whole) };
185 assert!(typed.extra == 42);
186 drop(unsafe { Box::from_raw(whole) });
189 /// When casting an array reference to a raw element ptr, that should cover the whole array.
191 let mut x: [usize; 2] = [0, 0];
192 let p = &mut x as *mut usize;
197 let x: [usize; 2] = [0, 1];
198 let p = &x as *const usize;
199 assert_eq!(unsafe { *p.add(1) }, 1);
202 /// Transmuting &&i32 to &&mut i32 is fine.
206 let p = unsafe { core::mem::transmute::<&&i32, &&mut i32>(&y) };
211 fn wide_raw_ptr_in_tuple() {
212 let mut x: Box<dyn std::any::Any> = Box::new("ouch");
213 let r = &mut *x as *mut dyn std::any::Any;
214 // This triggers the visitor-based recursive retagging. It is *not* supposed to retag raw
215 // pointers, but then the visitor might recurse into the "fields" of a wide raw pointer and
216 // finds a reference (to a vtable) there that it wants to retag... and that would be Wrong.
218 let r = unsafe { &mut *pair.0 };
219 // Make sure the fn ptr part of the vtable is still fine.