Add AnyWeakModelHandle

Max Brunsfeld and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/gpui/src/app.rs       | 62 +++++++++++++++++++++++++++++++++++++
crates/gpui/src/presenter.rs | 10 ++++-
2 files changed, 68 insertions(+), 4 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -84,6 +84,8 @@ pub trait UpgradeModelHandle {
         &self,
         handle: &WeakModelHandle<T>,
     ) -> Option<ModelHandle<T>>;
+
+    fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle>;
 }
 
 pub trait UpgradeViewHandle {
@@ -570,7 +572,11 @@ impl UpgradeModelHandle for AsyncAppContext {
         &self,
         handle: &WeakModelHandle<T>,
     ) -> Option<ModelHandle<T>> {
-        self.0.borrow_mut().upgrade_model_handle(handle)
+        self.0.borrow().upgrade_model_handle(handle)
+    }
+
+    fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
+        self.0.borrow().upgrade_any_model_handle(handle)
     }
 }
 
@@ -1764,6 +1770,10 @@ impl UpgradeModelHandle for MutableAppContext {
     ) -> Option<ModelHandle<T>> {
         self.cx.upgrade_model_handle(handle)
     }
+
+    fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
+        self.cx.upgrade_any_model_handle(handle)
+    }
 }
 
 impl UpgradeViewHandle for MutableAppContext {
@@ -1888,6 +1898,19 @@ impl UpgradeModelHandle for AppContext {
             None
         }
     }
+
+    fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
+        if self.models.contains_key(&handle.model_id) {
+            self.ref_counts.lock().inc_model(handle.model_id);
+            Some(AnyModelHandle {
+                model_id: handle.model_id,
+                model_type: handle.model_type,
+                ref_counts: self.ref_counts.clone(),
+            })
+        } else {
+            None
+        }
+    }
 }
 
 impl UpgradeViewHandle for AppContext {
@@ -2280,6 +2303,10 @@ impl<M> UpgradeModelHandle for ModelContext<'_, M> {
     ) -> Option<ModelHandle<T>> {
         self.cx.upgrade_model_handle(handle)
     }
+
+    fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
+        self.cx.upgrade_any_model_handle(handle)
+    }
 }
 
 impl<M> Deref for ModelContext<'_, M> {
@@ -2610,6 +2637,10 @@ impl<V> UpgradeModelHandle for ViewContext<'_, V> {
     ) -> Option<ModelHandle<T>> {
         self.cx.upgrade_model_handle(handle)
     }
+
+    fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
+        self.cx.upgrade_any_model_handle(handle)
+    }
 }
 
 impl<V> UpgradeViewHandle for ViewContext<'_, V> {
@@ -3290,6 +3321,13 @@ impl AnyModelHandle {
         }
     }
 
+    pub fn downgrade(&self) -> AnyWeakModelHandle {
+        AnyWeakModelHandle {
+            model_id: self.model_id,
+            model_type: self.model_type,
+        }
+    }
+
     pub fn is<T: Entity>(&self) -> bool {
         self.model_type == TypeId::of::<T>()
     }
@@ -3306,12 +3344,34 @@ impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
     }
 }
 
+impl Clone for AnyModelHandle {
+    fn clone(&self) -> Self {
+        self.ref_counts.lock().inc_model(self.model_id);
+        Self {
+            model_id: self.model_id,
+            model_type: self.model_type,
+            ref_counts: self.ref_counts.clone(),
+        }
+    }
+}
+
 impl Drop for AnyModelHandle {
     fn drop(&mut self) {
         self.ref_counts.lock().dec_model(self.model_id);
     }
 }
 
+pub struct AnyWeakModelHandle {
+    model_id: usize,
+    model_type: TypeId,
+}
+
+impl AnyWeakModelHandle {
+    pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option<AnyModelHandle> {
+        cx.upgrade_any_model_handle(self)
+    }
+}
+
 pub struct WeakViewHandle<T> {
     window_id: usize,
     view_id: usize,

crates/gpui/src/presenter.rs 🔗

@@ -6,9 +6,9 @@ use crate::{
     json::{self, ToJson},
     platform::Event,
     text_layout::TextLayoutCache,
-    Action, AnyAction, AnyViewHandle, AssetCache, ElementBox, Entity, FontSystem, ModelHandle,
-    ReadModel, ReadView, Scene, UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle,
-    WeakModelHandle, WeakViewHandle,
+    Action, AnyAction, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
+    Entity, FontSystem, ModelHandle, ReadModel, ReadView, Scene, UpgradeModelHandle,
+    UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle,
 };
 use pathfinder_geometry::vector::{vec2f, Vector2F};
 use serde_json::json;
@@ -280,6 +280,10 @@ impl<'a> UpgradeModelHandle for LayoutContext<'a> {
     ) -> Option<ModelHandle<T>> {
         self.app.upgrade_model_handle(handle)
     }
+
+    fn upgrade_any_model_handle(&self, handle: &AnyWeakModelHandle) -> Option<AnyModelHandle> {
+        self.app.upgrade_any_model_handle(handle)
+    }
 }
 
 impl<'a> UpgradeViewHandle for LayoutContext<'a> {