summary refs log tree commit diff
path: root/src/test/ui/mir-dataflow/indirect-mutation-offset.rs
blob: 8087a3e139915aa74257189f25be6f828474e8b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// compile-flags: -Zunleash-the-miri-inside-of-you

#![feature(core_intrinsics, rustc_attrs, const_raw_ptr_deref)]

use std::cell::UnsafeCell;
use std::intrinsics::rustc_peek;

#[repr(C)]
struct PartialInteriorMut {
    zst: [i32; 0],
    cell: UnsafeCell<i32>,
}

#[rustc_mir(rustc_peek_indirectly_mutable,stop_after_dataflow)]
const BOO: i32 = {
    let x = PartialInteriorMut {
        zst: [],
        cell: UnsafeCell::new(0),
    };

    let p_zst: *const _ = &x.zst ; // Doesn't cause `x` to get marked as indirectly mutable.

    let rmut_cell = unsafe {
        // Take advantage of the fact that `zst` and `cell` are at the same location in memory.
        // This trick would work with any size type if miri implemented `ptr::offset`.
        let p_cell = p_zst as *const UnsafeCell<i32>;

        let pmut_cell = (*p_cell).get();
        &mut *pmut_cell
    };

    *rmut_cell = 42;  // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
    let val = *rmut_cell;
    unsafe { rustc_peek(x) }; //~ ERROR rustc_peek: bit not set

    val
};

fn main() {
    println!("{}", BOO);
}