Skip to content

Commit

Permalink
consolidate miri-unleashed tests for mutable refs into one file
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Jul 13, 2024
1 parent c1e3f03 commit 90c9e32
Show file tree
Hide file tree
Showing 4 changed files with 399 additions and 427 deletions.
90 changes: 87 additions & 3 deletions tests/ui/consts/miri_unleashed/mutable_references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@
//@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
//@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"

#![allow(static_mut_refs)]
#![deny(const_eval_mutable_ptr_in_final_value)]
use std::cell::UnsafeCell;
use std::sync::atomic::*;

// # Plain `&mut` in the final value

// This requires walking nested statics.
static FOO: &&mut u32 = &&mut 42;
//~^ ERROR it is undefined behavior to use this value

//~| pointing to read-only memory
static OH_YES: &mut i32 = &mut 42;
//~^ ERROR it is undefined behavior to use this value
//~| pointing to read-only memory
static BAR: &mut () = &mut ();
//~^ ERROR encountered mutable pointer in final value of static
//~| WARNING this was previously accepted by the compiler
Expand All @@ -19,15 +26,92 @@ static BOO: &mut Foo<()> = &mut Foo(());
//~^ ERROR encountered mutable pointer in final value of static
//~| WARNING this was previously accepted by the compiler

const BLUNT: &mut i32 = &mut 42;
//~^ ERROR: it is undefined behavior to use this value
//~| pointing to read-only memory

const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC };
//~^ ERROR: it is undefined behavior to use this value
//~| static

// # Interior mutability

struct Meh {
x: &'static UnsafeCell<i32>,
}
unsafe impl Sync for Meh {}
static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
//~^ ERROR it is undefined behavior to use this value
//~| `UnsafeCell` in read-only memory
// Same with a const:
// the following will never be ok! no interior mut behind consts, because
// all allocs interned here will be marked immutable.
const MUH: Meh = Meh {
//~^ ERROR it is undefined behavior to use this value
//~| `UnsafeCell` in read-only memory
x: &UnsafeCell::new(42),
};

struct Synced {
x: UnsafeCell<i32>,
}
unsafe impl Sync for Synced {}

// Make sure we also catch this behind a type-erased `dyn Trait` reference.
const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
//~^ ERROR: it is undefined behavior to use this value
//~| `UnsafeCell` in read-only memory

// # Check for mutable references to read-only memory

static READONLY: i32 = 0;
static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
//~^ ERROR: it is undefined behavior to use this value
//~| pointing to read-only memory

// # Check for consts pointing to mutable memory

static mut MUTABLE: i32 = 42;
const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; //~ERROR: undefined behavior
//~| encountered reference to mutable memory
static mut MUTABLE_REF: &mut i32 = &mut 42;
const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
//~^ ERROR: evaluation of constant value failed
//~| accesses mutable global memory

const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
//~^ ERROR: mutable pointer in final value
//~| WARNING this was previously accepted by the compiler

const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
//~^ ERROR: mutable pointer in final value
//~| WARNING this was previously accepted by the compiler

const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
//~^ ERROR: mutable pointer in final value
//~| WARNING this was previously accepted by the compiler

struct SyncPtr<T> {
x: *const T,
}
unsafe impl<T> Sync for SyncPtr<T> {}

// These pass the lifetime checks because of the "tail expression" / "outer scope" rule.
// (This relies on `SyncPtr` being a curly brace struct.)
// However, we intern the inner memory as read-only, so this must be rejected.
// (Also see `static-no-inner-mut` for similar tests on `static`.)
const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
//~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler

const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
//~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler

const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
//~^ ERROR mutable pointer in final value
//~| WARNING this was previously accepted by the compiler

static OH_YES: &mut i32 = &mut 42;
//~^ ERROR it is undefined behavior to use this value

fn main() {
unsafe {
Expand Down
Loading

0 comments on commit 90c9e32

Please sign in to comment.