about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-10-02 19:20:49 +0000
committerMichael Goulet <michael@errs.io>2022-10-02 19:21:06 +0000
commitc7d1ec009c56546268a84525d1cb0797d68997c1 (patch)
tree45c0bc1122164adeaec59b784ac328c0b15b2d68
parentf914b82a754c6d85c0a909ab152f5b611defef73 (diff)
downloadrust-c7d1ec009c56546268a84525d1cb0797d68997c1.tar.gz
rust-c7d1ec009c56546268a84525d1cb0797d68997c1.zip
Don't ICE when trying to copy unsized value in const prop
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs16
-rw-r--r--src/test/ui/const_prop/issue-102553.rs24
2 files changed, 35 insertions, 5 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 7a01b85381a..eeeb7d6d3e5 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -640,11 +640,17 @@ where
         // avoid force_allocation.
         let src = match self.read_immediate_raw(src)? {
             Ok(src_val) => {
-                assert!(!src.layout.is_unsized(), "cannot copy unsized immediates");
-                assert!(
-                    !dest.layout.is_unsized(),
-                    "the src is sized, so the dest must also be sized"
-                );
+                // FIXME(const_prop): Const-prop can possibly evaluate an
+                // unsized copy operation when it thinks that the type is
+                // actually sized, due to a trivially false where-clause
+                // predicate like `where Self: Sized` with `Self = dyn Trait`.
+                // See #102553 for an example of such a predicate.
+                if src.layout.is_unsized() {
+                    throw_inval!(SizeOfUnsizedType(src.layout.ty));
+                }
+                if dest.layout.is_unsized() {
+                    throw_inval!(SizeOfUnsizedType(dest.layout.ty));
+                }
                 assert_eq!(src.layout.size, dest.layout.size);
                 // Yay, we got a value that we can write directly.
                 return if layout_compat {
diff --git a/src/test/ui/const_prop/issue-102553.rs b/src/test/ui/const_prop/issue-102553.rs
new file mode 100644
index 00000000000..523a9d7ac72
--- /dev/null
+++ b/src/test/ui/const_prop/issue-102553.rs
@@ -0,0 +1,24 @@
+// compile-flags: --crate-type=lib
+// check-pass
+
+pub trait Widget<E> {
+    fn boxed<'w>(self) -> Box<dyn WidgetDyn<E> + 'w>
+    where
+        Self: Sized + 'w;
+}
+
+pub trait WidgetDyn<E> {}
+
+impl<T, E> WidgetDyn<E> for T where T: Widget<E> {}
+
+impl<E> Widget<E> for dyn WidgetDyn<E> + '_ {
+    fn boxed<'w>(self) -> Box<dyn WidgetDyn<E> + 'w>
+    where
+        Self: Sized + 'w,
+    {
+        // Even though this is illegal to const evaluate, this should never
+        // trigger an ICE because it can never be called from actual code
+        // (due to the trivially false where-clause predicate).
+        Box::new(self)
+    }
+}