experiment with a way to recover the any entities when downcasting fails

Mikayla created

Change summary

crates/gpui2/src/app/entity_map.rs | 16 ++++++++++++----
crates/gpui2/src/view.rs           | 21 +++++++++++++++++++--
2 files changed, 31 insertions(+), 6 deletions(-)

Detailed changes

crates/gpui2/src/app/entity_map.rs 🔗

@@ -172,14 +172,14 @@ impl AnyModel {
         }
     }
 
-    pub fn downcast<T: 'static>(self) -> Option<Model<T>> {
+    pub fn downcast<T: 'static>(self) -> Result<Model<T>, AnyModel> {
         if TypeId::of::<T>() == self.entity_type {
-            Some(Model {
-                any_model: self.clone(),
+            Ok(Model {
+                any_model: self,
                 entity_type: PhantomData,
             })
         } else {
-            None
+            Err(self)
         }
     }
 }
@@ -243,6 +243,14 @@ impl PartialEq for AnyModel {
 
 impl Eq for AnyModel {}
 
+impl std::fmt::Debug for AnyModel {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("AnyModel")
+            .field("entity_id", &self.entity_id.as_u64())
+            .finish()
+    }
+}
+
 #[derive(Deref, DerefMut)]
 pub struct Model<T> {
     #[deref]

crates/gpui2/src/view.rs 🔗

@@ -211,6 +211,7 @@ trait ViewObject: Send + Sync {
     fn initialize(&self, cx: &mut WindowContext) -> AnyBox;
     fn layout(&self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId;
     fn paint(&self, bounds: Bounds<Pixels>, element: &mut AnyBox, cx: &mut WindowContext);
+    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
 }
 
 impl<V> ViewObject for View<V>
@@ -256,14 +257,24 @@ where
             });
         });
     }
+
+    fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct(&format!("AnyView<{}>", std::any::type_name::<V>()))
+            .field("entity_id", &ViewObject::entity_id(self).as_u64())
+            .finish()
+    }
 }
 
 #[derive(Clone)]
 pub struct AnyView(Arc<dyn ViewObject>);
 
 impl AnyView {
-    pub fn downcast<V: 'static + Send>(self) -> Option<View<V>> {
-        self.0.model().downcast().map(|model| View { model })
+    pub fn downcast<V: 'static + Send>(self) -> Result<View<V>, AnyView> {
+        self.0
+            .model()
+            .downcast()
+            .map(|model| View { model })
+            .map_err(|_| self)
     }
 
     pub(crate) fn entity_type(&self) -> TypeId {
@@ -326,6 +337,12 @@ impl Element<()> for AnyView {
     }
 }
 
+impl std::fmt::Debug for AnyView {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.0.debug(f)
+    }
+}
+
 struct EraseAnyViewState<ParentViewState> {
     view: AnyView,
     parent_view_state_type: PhantomData<ParentViewState>,