Wrap AnyWeak handles with their typed counterparts

This commit is contained in:
Nathan Sobo 2023-04-02 15:42:03 -06:00
parent 82a713fd1d
commit aed8df96ff
4 changed files with 82 additions and 119 deletions

View file

@ -293,7 +293,7 @@ impl<T: Entity> PendingEntitySubscription<T> {
state state
.entities_by_type_and_remote_id .entities_by_type_and_remote_id
.insert(id, WeakSubscriber::Model(model.downgrade().into())); .insert(id, WeakSubscriber::Model(model.downgrade().into_any()));
drop(state); drop(state);
for message in messages { for message in messages {
self.client.handle_message(message, cx); self.client.handle_message(message, cx);
@ -457,10 +457,10 @@ impl Client {
cx: &mut ViewContext<T>, cx: &mut ViewContext<T>,
) -> Subscription { ) -> Subscription {
let id = (TypeId::of::<T>(), remote_id); let id = (TypeId::of::<T>(), remote_id);
self.state self.state.write().entities_by_type_and_remote_id.insert(
.write() id,
.entities_by_type_and_remote_id WeakSubscriber::View((&cx.weak_handle() as &AnyWeakViewHandle).clone()),
.insert(id, WeakSubscriber::View(cx.weak_handle().into())); );
Subscription::Entity { Subscription::Entity {
client: Arc::downgrade(self), client: Arc::downgrade(self),
id, id,
@ -504,7 +504,7 @@ impl Client {
let mut state = self.state.write(); let mut state = self.state.write();
state state
.models_by_message_type .models_by_message_type
.insert(message_type_id, model.downgrade().into()); .insert(message_type_id, model.downgrade().into_any());
let prev_handler = state.message_handlers.insert( let prev_handler = state.message_handlers.insert(
message_type_id, message_type_id,

View file

@ -2823,8 +2823,7 @@ impl AppContext {
} }
} }
pub fn is_child_focused(&self, view: impl Into<AnyViewHandle>) -> bool { pub fn is_child_focused(&self, view: &AnyViewHandle) -> bool {
let view = view.into();
if let Some(focused_view_id) = self.focused_view_id(view.window_id) { if let Some(focused_view_id) = self.focused_view_id(view.window_id) {
self.ancestors(view.window_id, focused_view_id) self.ancestors(view.window_id, focused_view_id)
.skip(1) // Skip self id .skip(1) // Skip self id
@ -4455,32 +4454,23 @@ pub enum EntityLocation {
} }
pub struct ModelHandle<T: Entity> { pub struct ModelHandle<T: Entity> {
model_id: usize, any_handle: AnyModelHandle,
model_type: PhantomData<T>, model_type: PhantomData<T>,
ref_counts: Arc<Mutex<RefCounts>>, }
#[cfg(any(test, feature = "test-support"))] impl<T: Entity> Deref for ModelHandle<T> {
handle_id: usize, type Target = AnyModelHandle;
fn deref(&self) -> &Self::Target {
&self.any_handle
}
} }
impl<T: Entity> ModelHandle<T> { impl<T: Entity> ModelHandle<T> {
fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self { fn new(model_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
ref_counts.lock().inc_model(model_id);
#[cfg(any(test, feature = "test-support"))]
let handle_id = ref_counts
.lock()
.leak_detector
.lock()
.handle_created(Some(type_name::<T>()), model_id);
Self { Self {
model_id, any_handle: AnyModelHandle::new(model_id, TypeId::of::<T>(), ref_counts.clone()),
model_type: PhantomData, model_type: PhantomData,
ref_counts: ref_counts.clone(),
#[cfg(any(test, feature = "test-support"))]
handle_id,
} }
} }
@ -4564,19 +4554,6 @@ impl<T: Entity> Debug for ModelHandle<T> {
unsafe impl<T: Entity> Send for ModelHandle<T> {} unsafe impl<T: Entity> Send for ModelHandle<T> {}
unsafe impl<T: Entity> Sync for ModelHandle<T> {} unsafe impl<T: Entity> Sync for ModelHandle<T> {}
impl<T: Entity> Drop for ModelHandle<T> {
fn drop(&mut self) {
let mut ref_counts = self.ref_counts.lock();
ref_counts.dec_model(self.model_id);
#[cfg(any(test, feature = "test-support"))]
ref_counts
.leak_detector
.lock()
.handle_dropped(self.model_id, self.handle_id);
}
}
impl<T: Entity> Handle<T> for ModelHandle<T> { impl<T: Entity> Handle<T> for ModelHandle<T> {
type Weak = WeakModelHandle<T>; type Weak = WeakModelHandle<T>;
@ -4601,10 +4578,24 @@ impl<T: Entity> Handle<T> for ModelHandle<T> {
} }
pub struct WeakModelHandle<T> { pub struct WeakModelHandle<T> {
model_id: usize, any_handle: AnyWeakModelHandle,
model_type: PhantomData<T>, model_type: PhantomData<T>,
} }
impl<T> WeakModelHandle<T> {
pub fn into_any(self) -> AnyWeakModelHandle {
self.any_handle
}
}
impl<T> Deref for WeakModelHandle<T> {
type Target = AnyWeakModelHandle;
fn deref(&self) -> &Self::Target {
&self.any_handle
}
}
impl<T> WeakHandle for WeakModelHandle<T> { impl<T> WeakHandle for WeakModelHandle<T> {
fn id(&self) -> usize { fn id(&self) -> usize {
self.model_id self.model_id
@ -4617,7 +4608,10 @@ unsafe impl<T> Sync for WeakModelHandle<T> {}
impl<T: Entity> WeakModelHandle<T> { impl<T: Entity> WeakModelHandle<T> {
fn new(model_id: usize) -> Self { fn new(model_id: usize) -> Self {
Self { Self {
model_id, any_handle: AnyWeakModelHandle {
model_id,
model_type: TypeId::of::<T>(),
},
model_type: PhantomData, model_type: PhantomData,
} }
} }
@ -4658,7 +4652,7 @@ impl<T: Entity> PartialEq<ModelHandle<T>> for WeakModelHandle<T> {
impl<T> Clone for WeakModelHandle<T> { impl<T> Clone for WeakModelHandle<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
model_id: self.model_id, any_handle: self.any_handle.clone(),
model_type: PhantomData, model_type: PhantomData,
} }
} }
@ -4681,23 +4675,13 @@ impl<T> Deref for ViewHandle<T> {
impl<T: View> ViewHandle<T> { impl<T: View> ViewHandle<T> {
fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self { fn new(window_id: usize, view_id: usize, ref_counts: &Arc<Mutex<RefCounts>>) -> Self {
ref_counts.lock().inc_view(window_id, view_id);
#[cfg(any(test, feature = "test-support"))]
let handle_id = ref_counts
.lock()
.leak_detector
.lock()
.handle_created(Some(type_name::<T>()), view_id);
Self { Self {
any_handle: AnyViewHandle { any_handle: AnyViewHandle::new(
window_id, window_id,
view_id, view_id,
view_type: TypeId::of::<T>(), TypeId::of::<T>(),
ref_counts: ref_counts.clone(), ref_counts.clone(),
#[cfg(any(test, feature = "test-support"))] ),
handle_id,
},
view_type: PhantomData, view_type: PhantomData,
} }
} }
@ -4918,12 +4902,6 @@ impl Clone for AnyViewHandle {
} }
} }
impl From<&AnyViewHandle> for AnyViewHandle {
fn from(handle: &AnyViewHandle) -> Self {
handle.clone()
}
}
impl<T: View> From<ViewHandle<T>> for AnyViewHandle { impl<T: View> From<ViewHandle<T>> for AnyViewHandle {
fn from(handle: ViewHandle<T>) -> Self { fn from(handle: ViewHandle<T>) -> Self {
handle.any_handle handle.any_handle
@ -4982,19 +4960,10 @@ impl AnyModelHandle {
pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> { pub fn downcast<T: Entity>(self) -> Option<ModelHandle<T>> {
if self.is::<T>() { if self.is::<T>() {
let result = Some(ModelHandle { Some(ModelHandle {
model_id: self.model_id, any_handle: self,
model_type: PhantomData, model_type: PhantomData,
ref_counts: self.ref_counts.clone(), })
#[cfg(any(test, feature = "test-support"))]
handle_id: self.handle_id,
});
unsafe {
Arc::decrement_strong_count(Arc::as_ptr(&self.ref_counts));
}
std::mem::forget(self);
result
} else { } else {
None None
} }
@ -5016,16 +4985,6 @@ impl AnyModelHandle {
} }
} }
impl<T: Entity> From<ModelHandle<T>> for AnyModelHandle {
fn from(handle: ModelHandle<T>) -> Self {
Self::new(
handle.model_id,
TypeId::of::<T>(),
handle.ref_counts.clone(),
)
}
}
impl Clone for AnyModelHandle { impl Clone for AnyModelHandle {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self::new(self.model_id, self.model_type, self.ref_counts.clone()) Self::new(self.model_id, self.model_type, self.ref_counts.clone())
@ -5045,7 +5004,7 @@ impl Drop for AnyModelHandle {
} }
} }
#[derive(Hash, PartialEq, Eq, Debug)] #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
pub struct AnyWeakModelHandle { pub struct AnyWeakModelHandle {
model_id: usize, model_id: usize,
model_type: TypeId, model_type: TypeId,
@ -5063,10 +5022,10 @@ impl AnyWeakModelHandle {
TypeId::of::<T>() == self.model_type TypeId::of::<T>() == self.model_type
} }
pub fn downcast<T: Entity>(&self) -> Option<WeakModelHandle<T>> { pub fn downcast<T: Entity>(self) -> Option<WeakModelHandle<T>> {
if self.is::<T>() { if self.is::<T>() {
let result = Some(WeakModelHandle { let result = Some(WeakModelHandle {
model_id: self.model_id, any_handle: self,
model_type: PhantomData, model_type: PhantomData,
}); });
@ -5077,19 +5036,9 @@ impl AnyWeakModelHandle {
} }
} }
impl<T: Entity> From<WeakModelHandle<T>> for AnyWeakModelHandle {
fn from(handle: WeakModelHandle<T>) -> Self {
AnyWeakModelHandle {
model_id: handle.model_id,
model_type: TypeId::of::<T>(),
}
}
}
#[derive(Debug, Copy)] #[derive(Debug, Copy)]
pub struct WeakViewHandle<T> { pub struct WeakViewHandle<T> {
window_id: usize, any_handle: AnyWeakViewHandle,
view_id: usize,
view_type: PhantomData<T>, view_type: PhantomData<T>,
} }
@ -5102,8 +5051,11 @@ impl<T> WeakHandle for WeakViewHandle<T> {
impl<T: View> WeakViewHandle<T> { impl<T: View> WeakViewHandle<T> {
fn new(window_id: usize, view_id: usize) -> Self { fn new(window_id: usize, view_id: usize) -> Self {
Self { Self {
window_id, any_handle: AnyWeakViewHandle {
view_id, window_id,
view_id,
view_type: TypeId::of::<T>(),
},
view_type: PhantomData, view_type: PhantomData,
} }
} }
@ -5116,16 +5068,27 @@ impl<T: View> WeakViewHandle<T> {
self.window_id self.window_id
} }
pub fn into_any(self) -> AnyWeakViewHandle {
self.any_handle
}
pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> { pub fn upgrade(&self, cx: &impl UpgradeViewHandle) -> Option<ViewHandle<T>> {
cx.upgrade_view_handle(self) cx.upgrade_view_handle(self)
} }
} }
impl<T> Deref for WeakViewHandle<T> {
type Target = AnyWeakViewHandle;
fn deref(&self) -> &Self::Target {
&self.any_handle
}
}
impl<T> Clone for WeakViewHandle<T> { impl<T> Clone for WeakViewHandle<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
window_id: self.window_id, any_handle: self.any_handle.clone(),
view_id: self.view_id,
view_type: PhantomData, view_type: PhantomData,
} }
} }
@ -5141,11 +5104,11 @@ impl<T> Eq for WeakViewHandle<T> {}
impl<T> Hash for WeakViewHandle<T> { impl<T> Hash for WeakViewHandle<T> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.window_id.hash(state); self.any_handle.hash(state);
self.view_id.hash(state);
} }
} }
#[derive(Debug, Clone, Copy)]
pub struct AnyWeakViewHandle { pub struct AnyWeakViewHandle {
window_id: usize, window_id: usize,
view_id: usize, view_id: usize,
@ -5162,13 +5125,11 @@ impl AnyWeakViewHandle {
} }
} }
impl<T: View> From<WeakViewHandle<T>> for AnyWeakViewHandle { impl Hash for AnyWeakViewHandle {
fn from(handle: WeakViewHandle<T>) -> Self { fn hash<H: Hasher>(&self, state: &mut H) {
AnyWeakViewHandle { self.window_id.hash(state);
window_id: handle.window_id, self.view_id.hash(state);
view_id: handle.view_id, self.view_type.hash(state);
view_type: TypeId::of::<T>(),
}
} }
} }
@ -6340,8 +6301,8 @@ mod tests {
cx.focus(&view_1); cx.focus(&view_1);
cx.focus(&view_2); cx.focus(&view_2);
}); });
assert!(cx.is_child_focused(view_1.clone())); assert!(cx.is_child_focused(&view_1));
assert!(!cx.is_child_focused(view_2.clone())); assert!(!cx.is_child_focused(&view_2));
assert_eq!( assert_eq!(
mem::take(&mut *view_events.lock()), mem::take(&mut *view_events.lock()),
[ [
@ -6366,8 +6327,8 @@ mod tests {
); );
view_1.update(cx, |_, cx| cx.focus(&view_1)); view_1.update(cx, |_, cx| cx.focus(&view_1));
assert!(!cx.is_child_focused(view_1.clone())); assert!(!cx.is_child_focused(&view_1));
assert!(!cx.is_child_focused(view_2.clone())); assert!(!cx.is_child_focused(&view_2));
assert_eq!( assert_eq!(
mem::take(&mut *view_events.lock()), mem::take(&mut *view_events.lock()),
["view 2 blurred", "view 1 focused"], ["view 2 blurred", "view 1 focused"],

View file

@ -1231,7 +1231,9 @@ impl Project {
File::from_dyn(buffer.file()).and_then(|file| file.project_entry_id(cx)) File::from_dyn(buffer.file()).and_then(|file| file.project_entry_id(cx))
}) })
.ok_or_else(|| anyhow!("no project entry"))?; .ok_or_else(|| anyhow!("no project entry"))?;
Ok((project_entry_id, buffer.into()))
let buffer: &AnyModelHandle = &buffer;
Ok((project_entry_id, buffer.clone()))
}) })
} }

View file

@ -234,7 +234,7 @@ impl Eq for Box<dyn SearchableItemHandle> {}
pub trait WeakSearchableItemHandle: WeakItemHandle { pub trait WeakSearchableItemHandle: WeakItemHandle {
fn upgrade(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>; fn upgrade(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
fn to_any(self) -> AnyWeakViewHandle; fn into_any(self) -> AnyWeakViewHandle;
} }
impl<T: SearchableItem> WeakSearchableItemHandle for WeakViewHandle<T> { impl<T: SearchableItem> WeakSearchableItemHandle for WeakViewHandle<T> {
@ -242,8 +242,8 @@ impl<T: SearchableItem> WeakSearchableItemHandle for WeakViewHandle<T> {
Some(Box::new(self.upgrade(cx)?)) Some(Box::new(self.upgrade(cx)?))
} }
fn to_any(self) -> AnyWeakViewHandle { fn into_any(self) -> AnyWeakViewHandle {
self.into() self.into_any()
} }
} }