diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 416b66daa059..f0d64e217a28 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -3,7 +3,6 @@ //! After a const evaluation has computed a value, before we destroy the const evaluator's session //! memory, we need to extract all memory allocations to the global memory pool so they stay around. -use rustc::ty::layout::LayoutOf; use rustc::ty::{Ty, TyCtxt, ParamEnv, self}; use rustc::mir::interpret::{ InterpResult, ErrorHandled, @@ -143,18 +142,15 @@ for // Handle Reference types, as these are the only relocations supported by const eval. // Raw pointers (and boxes) are handled by the `leftover_relocations` logic. let ty = mplace.layout.ty; - if let ty::Ref(_, _, mutability) = ty.sty { + if let ty::Ref(_, referenced_ty, mutability) = ty.sty { let value = self.ecx.read_immediate(mplace.into())?; // Handle trait object vtables if let Ok(meta) = value.to_meta() { - let layout = self.ecx.layout_of(ty.builtin_deref(true).unwrap().ty)?; - if layout.is_unsized() { - if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(layout.ty).sty { - if let Ok(vtable) = meta.unwrap().to_ptr() { - // explitly choose `Immutable` here, since vtables are immutable, even - // if the reference of the fat pointer is mutable - self.intern_shallow(vtable, Mutability::Immutable)?; - } + if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(referenced_ty).sty { + if let Ok(vtable) = meta.unwrap().to_ptr() { + // explitly choose `Immutable` here, since vtables are immutable, even + // if the reference of the fat pointer is mutable + self.intern_shallow(vtable, Mutability::Immutable)?; } } } @@ -178,8 +174,14 @@ for (InternMode::Static, hir::Mutability::MutMutable) => {}, // we statically prevent `&mut T` via `const_qualif` and double check this here (InternMode::ConstBase, hir::Mutability::MutMutable) | - (InternMode::Const, hir::Mutability::MutMutable) => - bug!("const qualif failed to prevent mutable references"), + (InternMode::Const, hir::Mutability::MutMutable) => { + match referenced_ty.sty { + ty::Array(_, n) if n.unwrap_usize(self.ecx.tcx.tcx) == 0 => {} + ty::Slice(_) + if value.to_meta().unwrap().unwrap().to_usize(self.ecx)? == 0 => {} + _ => bug!("const qualif failed to prevent mutable references"), + } + }, } // Compute the mutability with which we'll start visiting the allocation. This is // what gets changed when we encounter an `UnsafeCell` diff --git a/src/test/ui/consts/issue-62045.rs b/src/test/ui/consts/issue-62045.rs new file mode 100644 index 000000000000..9f41ed9a2452 --- /dev/null +++ b/src/test/ui/consts/issue-62045.rs @@ -0,0 +1,5 @@ +// compile-pass + +fn main() { + assert_eq!(&mut [0; 1][..], &mut []); +} diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs b/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs index 4a77534c6c70..4fcd89a74db6 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs @@ -3,6 +3,7 @@ // 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" #![allow(const_err)] diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr index ff2351e1fdc5..82569e260143 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr @@ -1,12 +1,12 @@ warning: skipping const checks - --> $DIR/mutable_references_ice.rs:26:9 + --> $DIR/mutable_references_ice.rs:27:9 | LL | *MUH.x.get() = 99; | ^^^^^^^^^^^^^^^^^ thread 'rustc' panicked at 'assertion failed: `(left != right)` left: `Const`, - right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:127:17 + right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites may arbitrarily decide to change, too.', src/librustc_mir/interpret/intern.rs:LL:CC note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic