about summary refs log tree commit diff
diff options
context:
space:
mode:
-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)
+    }
+}