Add downcast_ref to AnyViewHandle

Nathan Sobo created

I use unsafe code to transmute an AnyViewHandle to a ViewHandle<T> when
the type matches. Because ViewHandle<T> is repr(transparent) to the
wrapped AnyViewHandle, this is safe.

Change summary

crates/file_finder/src/file_finder.rs |  3 +--
crates/gpui/src/app.rs                |  9 +++++++++
crates/workspace/src/pane.rs          |  3 +--
crates/zed/src/zed.rs                 | 12 ++++--------
4 files changed, 15 insertions(+), 12 deletions(-)

Detailed changes

crates/file_finder/src/file_finder.rs 🔗

@@ -353,8 +353,7 @@ mod tests {
             assert_eq!(
                 active_item
                     .as_any()
-                    .clone()
-                    .downcast::<Editor>()
+                    .downcast_ref::<Editor>()
                     .unwrap()
                     .read(cx)
                     .title(cx),

crates/gpui/src/app.rs 🔗

@@ -4661,6 +4661,7 @@ impl<T> Clone for WeakModelHandle<T> {
 
 impl<T> Copy for WeakModelHandle<T> {}
 
+#[repr(transparent)]
 pub struct ViewHandle<T> {
     any_handle: AnyViewHandle,
     view_type: PhantomData<T>,
@@ -4877,6 +4878,14 @@ impl AnyViewHandle {
         }
     }
 
+    pub fn downcast_ref<T: View>(&self) -> Option<&ViewHandle<T>> {
+        if self.is::<T>() {
+            Some(unsafe { mem::transmute(self) })
+        } else {
+            None
+        }
+    }
+
     pub fn downgrade(&self) -> AnyWeakViewHandle {
         AnyWeakViewHandle {
             window_id: self.window_id,

crates/workspace/src/pane.rs 🔗

@@ -2279,8 +2279,7 @@ mod tests {
                 .map(|(ix, item)| {
                     let mut state = item
                         .as_any()
-                        .clone()
-                        .downcast::<TestItem>()
+                        .downcast_ref::<TestItem>()
                         .unwrap()
                         .read(cx)
                         .label

crates/zed/src/zed.rs 🔗

@@ -1021,8 +1021,7 @@ mod tests {
                     .active_item()
                     .unwrap()
                     .as_any()
-                    .clone()
-                    .downcast::<Editor>()
+                    .downcast_ref::<Editor>()
                     .unwrap()
                     .read(cx)
                     .title(cx),
@@ -1058,8 +1057,7 @@ mod tests {
                     .active_item()
                     .unwrap()
                     .as_any()
-                    .clone()
-                    .downcast::<Editor>()
+                    .downcast_ref::<Editor>()
                     .unwrap()
                     .read(cx)
                     .title(cx),
@@ -1095,8 +1093,7 @@ mod tests {
                     .active_item()
                     .unwrap()
                     .as_any()
-                    .clone()
-                    .downcast::<Editor>()
+                    .downcast_ref::<Editor>()
                     .unwrap()
                     .read(cx)
                     .title(cx),
@@ -1146,8 +1143,7 @@ mod tests {
                     .active_item()
                     .unwrap()
                     .as_any()
-                    .clone()
-                    .downcast::<Editor>()
+                    .downcast_ref::<Editor>()
                     .unwrap()
                     .read(cx)
                     .title(cx),