1 #![feature(maybe_uninit_extra)]
2 use std::mem::MaybeUninit;
3 use std::cell::{Cell, RefCell, UnsafeCell};
4 
main()5 fn main() {
6     aliasing_mut_and_shr();
7     aliasing_frz_and_shr();
8     into_interior_mutability();
9     unsafe_cell_2phase();
10 }
11 
aliasing_mut_and_shr()12 fn aliasing_mut_and_shr() {
13     fn inner(rc: &RefCell<i32>, aliasing: &mut i32) {
14         *aliasing += 4;
15         let _escape_to_raw = rc as *const _;
16         *aliasing += 4;
17         let _shr = &*rc;
18         *aliasing += 4;
19         // also turning this into a frozen ref now must work
20         let aliasing = &*aliasing;
21         let _val = *aliasing;
22         let _escape_to_raw = rc as *const _; // this must NOT unfreeze
23         let _val = *aliasing;
24         let _shr = &*rc; // this must NOT unfreeze
25         let _val = *aliasing;
26     }
27 
28     let rc = RefCell::new(23);
29     let mut bmut = rc.borrow_mut();
30     inner(&rc, &mut *bmut);
31     drop(bmut);
32     assert_eq!(*rc.borrow(), 23+12);
33 }
34 
aliasing_frz_and_shr()35 fn aliasing_frz_and_shr() {
36     fn inner(rc: &RefCell<i32>, aliasing: &i32) {
37         let _val = *aliasing;
38         let _escape_to_raw = rc as *const _; // this must NOT unfreeze
39         let _val = *aliasing;
40         let _shr = &*rc; // this must NOT unfreeze
41         let _val = *aliasing;
42     }
43 
44     let rc = RefCell::new(23);
45     let bshr = rc.borrow();
46     inner(&rc, &*bshr);
47     assert_eq!(*rc.borrow(), 23);
48 }
49 
50 // Getting a pointer into a union with interior mutability used to be tricky
51 // business (https://github.com/rust-lang/miri/issues/615), but it should work
52 // now.
into_interior_mutability()53 fn into_interior_mutability() {
54     let mut x: MaybeUninit<(Cell<u32>, u32)> = MaybeUninit::uninit();
55     x.as_ptr();
56     x.write((Cell::new(0), 1));
57     let ptr = unsafe { x.assume_init_ref() };
58     assert_eq!(ptr.1, 1);
59 }
60 
61 // Two-phase borrows of the pointer returned by UnsafeCell::get() should not
62 // invalidate aliases.
unsafe_cell_2phase()63 fn unsafe_cell_2phase() { unsafe {
64     let x = &UnsafeCell::new(vec![]);
65     let x2 = &*x;
66     (*x.get()).push(0);
67     let _val = (*x2.get()).get(0);
68 } }
69