From 087a0136d01d0ee05d4e8c5e91f2e01978244a67 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 13 Feb 2023 21:07:46 +0000 Subject: [PATCH] Don't ICE in might_permit_raw_init if reference is polymorphic --- .../src/util/might_permit_raw_init.rs | 9 +++++-- .../dont_yeet_assert.generic.InstCombine.diff | 24 +++++++++++++++++++ tests/mir-opt/dont_yeet_assert.rs | 11 +++++++++ tests/ui/lint/invalid_value-polymorphic.rs | 8 +++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff create mode 100644 tests/mir-opt/dont_yeet_assert.rs create mode 100644 tests/ui/lint/invalid_value-polymorphic.rs diff --git a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs index 48961b7aac6..a2db98683b5 100644 --- a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs +++ b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs @@ -1,5 +1,5 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::{ParamEnv, TyCtxt, TypeVisitable}; use rustc_session::Limit; use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants}; @@ -108,7 +108,12 @@ fn might_permit_raw_init_lax<'tcx>( // Special magic check for references and boxes (i.e., special pointer types). if let Some(pointee) = this.ty.builtin_deref(false) { - let pointee = cx.layout_of(pointee.ty).expect("need to be able to compute layouts"); + let Ok(pointee) = cx.layout_of(pointee.ty) else { + // Reference is too polymorphic, it has a layout but the pointee does not. + // So we must assume that there may be some substitution that is valid. + assert!(pointee.ty.needs_subst()); + return true; + }; // We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied. if pointee.align.abi.bytes() > 1 { // 0x01-filling is not aligned. diff --git a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff new file mode 100644 index 00000000000..fb08ad582d9 --- /dev/null +++ b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff @@ -0,0 +1,24 @@ +- // MIR for `generic` before InstCombine ++ // MIR for `generic` after InstCombine + + fn generic() -> () { + let mut _0: (); // return place in scope 0 at $DIR/dont_yeet_assert.rs:+0:21: +0:21 + let _1: (); // in scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61 +- _1 = assert_mem_uninitialized_valid::<&T>() -> bb1; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61 +- // mir::Constant +- // + span: $DIR/dont_yeet_assert.rs:10:5: 10:59 +- // + user_ty: UserType(0) +- // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<&T>}, val: Value() } ++ goto -> bb1; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61 + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/dont_yeet_assert.rs:+1:61: +1:62 + _0 = const (); // scope 0 at $DIR/dont_yeet_assert.rs:+0:21: +2:2 + return; // scope 0 at $DIR/dont_yeet_assert.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/dont_yeet_assert.rs b/tests/mir-opt/dont_yeet_assert.rs new file mode 100644 index 00000000000..7cec761eaba --- /dev/null +++ b/tests/mir-opt/dont_yeet_assert.rs @@ -0,0 +1,11 @@ +// compile-flags: --crate-type=lib +// unit-test: InstCombine + +#![feature(core_intrinsics)] + +// Want to make sure this assertion isn't compiled away in generic code. + +// EMIT_MIR dont_yeet_assert.generic.InstCombine.diff +pub fn generic() { + core::intrinsics::assert_mem_uninitialized_valid::<&T>(); +} diff --git a/tests/ui/lint/invalid_value-polymorphic.rs b/tests/ui/lint/invalid_value-polymorphic.rs new file mode 100644 index 00000000000..055173e9842 --- /dev/null +++ b/tests/ui/lint/invalid_value-polymorphic.rs @@ -0,0 +1,8 @@ +// compile-flags: --crate-type=lib -Zmir-enable-passes=+InstCombine +// build-pass + +#![feature(core_intrinsics)] + +pub fn generic() { + core::intrinsics::assert_mem_uninitialized_valid::<&T>(); +}