| //@ run-pass |
| //@ compile-flags: -O |
| |
| // Make sure that `Ref` and `RefMut` do not make false promises about aliasing, |
| // because once they drop, their reference/pointer can alias other writes. |
| |
| // Adapted from comex's proof of concept: |
| // https://github.com/rust-lang/rust/issues/63787#issuecomment-523588164 |
| |
| use std::cell::RefCell; |
| use std::ops::Deref; |
| |
| pub fn break_if_r_is_noalias(rc: &RefCell<i32>, r: impl Deref<Target = i32>) -> i32 { |
| let ptr1 = &*r as *const i32; |
| let a = *r; |
| drop(r); |
| *rc.borrow_mut() = 2; |
| let r2 = rc.borrow(); |
| let ptr2 = &*r2 as *const i32; |
| if ptr2 != ptr1 { |
| panic!(); |
| } |
| // If LLVM knows the pointers are the same, and if `r` was `noalias`, |
| // then it may replace this with `a + a`, ignoring the earlier write. |
| a + *r2 |
| } |
| |
| fn main() { |
| let mut rc = RefCell::new(1); |
| let res = break_if_r_is_noalias(&rc, rc.borrow()); |
| assert_eq!(res, 3); |
| |
| *rc.get_mut() = 1; |
| let res = break_if_r_is_noalias(&rc, rc.borrow_mut()); |
| assert_eq!(res, 3); |
| } |