mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 04:57:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			37 lines
		
	
	
		
			1.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			37 lines
		
	
	
		
			1.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| // 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);
 | |
| }
 | 
