diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index c99f39977fe..5b19f879389 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -320,12 +320,19 @@ pub fn intern_const_alloc_recursive>( // We can't call the `intern_shallow` method here, as its logic is tailored to safe // references and a `leftover_allocations` set (where we only have a todo-list here). // So we hand-roll the interning logic here again. - if base_intern_mode != InternMode::Static { - // If it's not a static, it *must* be immutable. - // We cannot have mutable memory inside a constant. - // FIXME: ideally we would assert that they already are immutable, to double- - // check our static checks. - alloc.mutability = Mutability::Not; + match base_intern_mode { + InternMode::Static => {} + InternMode::Const | InternMode::ConstBase => { + // If it's not a static, it *must* be immutable. + // We cannot have mutable memory inside a constant. + // We use `delay_span_bug` here, because this can be reached in the presence + // of fancy transmutes. + if alloc.mutability == Mutability::Mut { + // For better errors later, mark the allocation as immutable + alloc.mutability = Mutability::Not; + ecx.tcx.sess.delay_span_bug(ecx.tcx.span, "mutable allocation in constant"); + } + } } let alloc = tcx.intern_const_alloc(alloc); tcx.alloc_map.lock().set_alloc_id_memory(alloc_id, alloc); @@ -337,6 +344,8 @@ pub fn intern_const_alloc_recursive>( } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { // dangling pointer throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into())) + } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() { + span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id); } } Ok(()) diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.rs b/src/test/ui/consts/miri_unleashed/mutable_const2.rs new file mode 100644 index 00000000000..97af1f2f993 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.rs @@ -0,0 +1,19 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" +// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" + +#![feature(const_raw_ptr_deref)] +#![feature(const_mut_refs)] +#![deny(const_err)] + +use std::cell::UnsafeCell; + +// make sure we do not just intern this as mutable +const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; +//~^ WARN: skipping const checks +//~| ERROR: mutable allocation in constant + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr new file mode 100644 index 00000000000..3493b7c54c4 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -0,0 +1,25 @@ +warning: skipping const checks + --> $DIR/mutable_const2.rs:15:38 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^ + +error: internal compiler error: mutable allocation in constant + --> $DIR/mutable_const2.rs:15:1 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:347:17 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc VERSION running on TARGET + +note: compiler flags: FLAGS +