about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-02-13 21:07:46 +0000
committerMichael Goulet <michael@errs.io>2023-02-14 01:03:06 +0000
commit087a0136d01d0ee05d4e8c5e91f2e01978244a67 (patch)
tree732dfdecbfdfffb6075d43398a935d2d8da98d97
parent0b439b119b8d49450bddbbea317afeb0d4166f70 (diff)
downloadrust-087a0136d01d0ee05d4e8c5e91f2e01978244a67.tar.gz
rust-087a0136d01d0ee05d4e8c5e91f2e01978244a67.zip
Don't ICE in might_permit_raw_init if reference is polymorphic
-rw-r--r--compiler/rustc_const_eval/src/util/might_permit_raw_init.rs9
-rw-r--r--tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff24
-rw-r--r--tests/mir-opt/dont_yeet_assert.rs11
-rw-r--r--tests/ui/lint/invalid_value-polymorphic.rs8
4 files changed, 50 insertions, 2 deletions
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(<ZST>) }
++         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<T>() {
+    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<T>() {
+    core::intrinsics::assert_mem_uninitialized_valid::<&T>();
+}