Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't ICE on mutable zst slices #62094

Merged
merged 4 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions src/librustc_mir/interpret/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)?;
}
}
}
Expand All @@ -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`
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/consts/issue-62045.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// compile-pass

fn main() {
assert_eq!(&mut [0; 1][..], &mut []);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)]

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down