diff --git a/crates/gpui2/src/action.rs b/crates/gpui2/src/action.rs index 9e3db6f83e..b6420c2b82 100644 --- a/crates/gpui2/src/action.rs +++ b/crates/gpui2/src/action.rs @@ -19,7 +19,7 @@ pub trait Action: Any + Send + Sync { impl Action for A where - A: for<'a> Deserialize<'a> + Any + PartialEq + Clone + Default + Send + Sync, + A: for<'a> Deserialize<'a> + PartialEq + Any + Send + Sync + Clone + Default, { fn qualified_name() -> SharedString { type_name::().into() diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 4674893693..2dc5e1510c 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -23,7 +23,9 @@ use slotmap::SlotMap; use std::{ any::{type_name, Any, TypeId}, borrow::Borrow, + marker::PhantomData, mem, + ops::{Deref, DerefMut}, sync::{atomic::Ordering::SeqCst, Arc, Weak}, time::Duration, }; @@ -179,7 +181,7 @@ pub struct AppContext { pub(crate) svg_renderer: SvgRenderer, pub(crate) image_cache: ImageCache, pub(crate) text_style_stack: Vec, - pub(crate) globals_by_type: HashMap>, + pub(crate) globals_by_type: HashMap, pub(crate) unit_entity: Handle<()>, pub(crate) entities: EntityMap, pub(crate) windows: SlotMap>, @@ -554,19 +556,16 @@ impl AppContext { .unwrap() } - pub fn set_global(&mut self, global: T) { - let global_type = TypeId::of::(); + pub fn set_global(&mut self, global: G) { + let global_type = TypeId::of::(); self.push_effect(Effect::NotifyGlobalObservers { global_type }); self.globals_by_type.insert(global_type, Box::new(global)); } - pub fn update_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R - where - G: 'static + Send + Sync, - { + pub fn update_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R { let mut global = self.lease_global::(); - let result = f(global.as_mut(), self); - self.restore_global(global); + let result = f(&mut global, self); + self.end_global_lease(global); result } @@ -583,19 +582,19 @@ impl AppContext { ) } - pub(crate) fn lease_global(&mut self) -> Box { - self.globals_by_type - .remove(&TypeId::of::()) - .ok_or_else(|| anyhow!("no global registered of type {}", type_name::())) - .unwrap() - .downcast() - .unwrap() + pub(crate) fn lease_global(&mut self) -> GlobalLease { + GlobalLease::new( + self.globals_by_type + .remove(&TypeId::of::()) + .ok_or_else(|| anyhow!("no global registered of type {}", type_name::())) + .unwrap(), + ) } - pub(crate) fn restore_global(&mut self, global: Box) { + pub(crate) fn end_global_lease(&mut self, lease: GlobalLease) { let global_type = TypeId::of::(); self.push_effect(Effect::NotifyGlobalObservers { global_type }); - self.globals_by_type.insert(global_type, global); + self.globals_by_type.insert(global_type, lease.global); } pub(crate) fn push_text_style(&mut self, text_style: TextStyleRefinement) { @@ -648,21 +647,21 @@ impl AppContext { } impl Context for AppContext { - type EntityContext<'a, 'w, T: Send + Sync + 'static> = ModelContext<'a, T>; + type EntityContext<'a, 'w, T> = ModelContext<'a, T>; type Result = T; - fn entity( + fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, ) -> Handle { self.update(|cx| { let slot = cx.entities.reserve(); - let entity = build_entity(&mut ModelContext::mutable(cx, slot.entity_id)); + let entity = build_entity(&mut ModelContext::mutable(cx, slot.downgrade())); cx.entities.insert(slot, entity) }) } - fn update_entity( + fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, @@ -671,7 +670,7 @@ impl Context for AppContext { let mut entity = cx.entities.lease(handle); let result = update( &mut entity, - &mut ModelContext::mutable(cx, handle.entity_id), + &mut ModelContext::mutable(cx, handle.downgrade()), ); cx.entities.end_lease(entity); result @@ -737,11 +736,11 @@ impl MainThread { }) } - pub fn open_window( + pub fn open_window( &mut self, options: crate::WindowOptions, - build_root_view: impl FnOnce(&mut WindowContext) -> View + Send + 'static, - ) -> WindowHandle { + build_root_view: impl FnOnce(&mut WindowContext) -> View + Send + 'static, + ) -> WindowHandle { self.update(|cx| { let id = cx.windows.insert(None); let handle = WindowHandle::new(id); @@ -785,6 +784,34 @@ pub(crate) enum Effect { }, } +pub(crate) struct GlobalLease { + global: AnyBox, + global_type: PhantomData, +} + +impl GlobalLease { + fn new(global: AnyBox) -> Self { + GlobalLease { + global, + global_type: PhantomData, + } + } +} + +impl Deref for GlobalLease { + type Target = G; + + fn deref(&self) -> &Self::Target { + self.global.downcast_ref().unwrap() + } +} + +impl DerefMut for GlobalLease { + fn deref_mut(&mut self) -> &mut Self::Target { + self.global.downcast_mut().unwrap() + } +} + pub(crate) struct AnyDrag { pub drag_handle_view: AnyView, pub cursor_offset: Point, diff --git a/crates/gpui2/src/app/async_context.rs b/crates/gpui2/src/app/async_context.rs index 0fea00ed1f..42c9e96dd0 100644 --- a/crates/gpui2/src/app/async_context.rs +++ b/crates/gpui2/src/app/async_context.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::anyhow; use derive_more::{Deref, DerefMut}; use parking_lot::Mutex; -use std::{future::Future, sync::Weak}; +use std::{any::Any, future::Future, sync::Weak}; #[derive(Clone)] pub struct AsyncAppContext { @@ -14,13 +14,16 @@ pub struct AsyncAppContext { } impl Context for AsyncAppContext { - type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>; + type EntityContext<'a, 'w, T> = ModelContext<'a, T>; type Result = Result; - fn entity( + fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, - ) -> Self::Result> { + ) -> Self::Result> + where + T: Any + Send + Sync, + { let app = self .app .upgrade() @@ -29,7 +32,7 @@ impl Context for AsyncAppContext { Ok(lock.entity(build_entity)) } - fn update_entity( + fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, @@ -129,7 +132,7 @@ impl AsyncAppContext { Ok(app_context.run_on_main(f)) } - pub fn has_global(&self) -> Result { + pub fn has_global(&self) -> Result { let app = self .app .upgrade() @@ -138,10 +141,7 @@ impl AsyncAppContext { Ok(lock.has_global::()) } - pub fn read_global( - &self, - read: impl FnOnce(&G, &AppContext) -> R, - ) -> Result { + pub fn read_global(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result { let app = self .app .upgrade() @@ -150,7 +150,7 @@ impl AsyncAppContext { Ok(read(lock.global(), &lock)) } - pub fn try_read_global( + pub fn try_read_global( &self, read: impl FnOnce(&G, &AppContext) -> R, ) -> Option { @@ -159,7 +159,7 @@ impl AsyncAppContext { Some(read(lock.try_global()?, &lock)) } - pub fn update_global( + pub fn update_global( &mut self, update: impl FnOnce(&mut G, &mut AppContext) -> R, ) -> Result { @@ -195,7 +195,7 @@ impl AsyncWindowContext { .ok(); } - pub fn read_global( + pub fn read_global( &self, read: impl FnOnce(&G, &WindowContext) -> R, ) -> Result { @@ -203,28 +203,34 @@ impl AsyncWindowContext { .read_window(self.window, |cx| read(cx.global(), cx)) } - pub fn update_global( + pub fn update_global( &mut self, update: impl FnOnce(&mut G, &mut WindowContext) -> R, - ) -> Result { + ) -> Result + where + G: 'static, + { self.app .update_window(self.window, |cx| cx.update_global(update)) } } impl Context for AsyncWindowContext { - type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>; + type EntityContext<'a, 'w, T> = ViewContext<'a, 'w, T>; type Result = Result; - fn entity( + fn entity( &mut self, - build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R, - ) -> Result> { + build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, + ) -> Result> + where + T: Any + Send + Sync, + { self.app .update_window(self.window, |cx| cx.entity(build_entity)) } - fn update_entity( + fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, @@ -233,3 +239,14 @@ impl Context for AsyncWindowContext { .update_window(self.window, |cx| cx.update_entity(handle, update)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_async_app_context_send_sync() { + fn assert_send_sync() {} + assert_send_sync::(); + } +} diff --git a/crates/gpui2/src/app/entity_map.rs b/crates/gpui2/src/app/entity_map.rs index a8ef9bb87b..b593fd3745 100644 --- a/crates/gpui2/src/app/entity_map.rs +++ b/crates/gpui2/src/app/entity_map.rs @@ -1,4 +1,4 @@ -use crate::{AppContext, Context}; +use crate::{AnyBox, AppContext, Context}; use anyhow::{anyhow, Result}; use derive_more::{Deref, DerefMut}; use parking_lot::{RwLock, RwLockUpgradableReadGuard}; @@ -30,7 +30,7 @@ impl Display for EntityId { } pub(crate) struct EntityMap { - entities: SecondaryMap>, + entities: SecondaryMap, ref_counts: Arc>, } @@ -51,56 +51,46 @@ impl EntityMap { } /// Reserve a slot for an entity, which you can subsequently use with `insert`. - pub fn reserve(&self) -> Slot { + pub fn reserve(&self) -> Slot { let id = self.ref_counts.write().counts.insert(1.into()); Slot(Handle::new(id, Arc::downgrade(&self.ref_counts))) } /// Insert an entity into a slot obtained by calling `reserve`. - pub fn insert( - &mut self, - slot: Slot, - entity: T, - ) -> Handle { + pub fn insert(&mut self, slot: Slot, entity: T) -> Handle + where + T: Any + Send + Sync, + { let handle = slot.0; self.entities.insert(handle.entity_id, Box::new(entity)); handle } /// Move an entity to the stack. - pub fn lease<'a, T: 'static + Send + Sync>(&mut self, handle: &'a Handle) -> Lease<'a, T> { + pub fn lease<'a, T>(&mut self, handle: &'a Handle) -> Lease<'a, T> { let entity = Some( self.entities .remove(handle.entity_id) - .expect("Circular entity lease. Is the entity already being updated?") - .downcast::() - .unwrap(), + .expect("Circular entity lease. Is the entity already being updated?"), ); - Lease { handle, entity } - } - - /// Return an entity after moving it to the stack. - pub fn end_lease(&mut self, mut lease: Lease) { - self.entities - .insert(lease.handle.entity_id, lease.entity.take().unwrap()); - } - - pub fn read(&self, handle: &Handle) -> &T { - self.entities[handle.entity_id].downcast_ref().unwrap() - } - - pub fn weak_handle(&self, id: EntityId) -> WeakHandle { - WeakHandle { - any_handle: AnyWeakHandle { - entity_id: id, - entity_type: TypeId::of::(), - entity_ref_counts: Arc::downgrade(&self.ref_counts), - }, + Lease { + handle, + entity, entity_type: PhantomData, } } - pub fn take_dropped(&mut self) -> Vec<(EntityId, Box)> { + /// Return an entity after moving it to the stack. + pub fn end_lease(&mut self, mut lease: Lease) { + self.entities + .insert(lease.handle.entity_id, lease.entity.take().unwrap()); + } + + pub fn read(&self, handle: &Handle) -> &T { + (handle.downcast_entity)(&self.entities[handle.entity_id]) + } + + pub fn take_dropped(&mut self) -> Vec<(EntityId, AnyBox)> { let dropped_entity_ids = mem::take(&mut self.ref_counts.write().dropped_entity_ids); dropped_entity_ids .into_iter() @@ -109,35 +99,27 @@ impl EntityMap { } } -pub struct Lease<'a, T: Send + Sync> { - entity: Option>, +pub struct Lease<'a, T> { + entity: Option, pub handle: &'a Handle, + entity_type: PhantomData, } -impl<'a, T> core::ops::Deref for Lease<'a, T> -where - T: Send + Sync, -{ +impl<'a, T> core::ops::Deref for Lease<'a, T> { type Target = T; fn deref(&self) -> &Self::Target { - self.entity.as_ref().unwrap() + (self.handle.downcast_entity)(self.entity.as_ref().unwrap()) } } -impl<'a, T> core::ops::DerefMut for Lease<'a, T> -where - T: Send + Sync, -{ +impl<'a, T> core::ops::DerefMut for Lease<'a, T> { fn deref_mut(&mut self) -> &mut Self::Target { - self.entity.as_mut().unwrap() + (self.handle.downcast_entity_mut)(self.entity.as_mut().unwrap()) } } -impl<'a, T> Drop for Lease<'a, T> -where - T: Send + Sync, -{ +impl<'a, T> Drop for Lease<'a, T> { fn drop(&mut self) { if self.entity.is_some() { // We don't panic here, because other panics can cause us to drop the lease without ending it cleanly. @@ -147,7 +129,7 @@ where } #[derive(Deref, DerefMut)] -pub struct Slot(Handle); +pub struct Slot(Handle); pub struct AnyHandle { pub(crate) entity_id: EntityId, @@ -176,14 +158,13 @@ impl AnyHandle { } } - pub fn downcast(&self) -> Option> - where - T: 'static + Send + Sync, - { + pub fn downcast(&self) -> Option> { if TypeId::of::() == self.entity_type { Some(Handle { any_handle: self.clone(), entity_type: PhantomData, + downcast_entity: |any| any.downcast_ref().unwrap(), + downcast_entity_mut: |any| any.downcast_mut().unwrap(), }) } else { None @@ -231,10 +212,7 @@ impl Drop for AnyHandle { } } -impl From> for AnyHandle -where - T: 'static + Send + Sync, -{ +impl From> for AnyHandle { fn from(handle: Handle) -> Self { handle.any_handle } @@ -255,18 +233,28 @@ impl PartialEq for AnyHandle { impl Eq for AnyHandle {} #[derive(Deref, DerefMut)] -pub struct Handle { +pub struct Handle { #[deref] #[deref_mut] any_handle: AnyHandle, entity_type: PhantomData, + downcast_entity: fn(&dyn Any) -> &T, + downcast_entity_mut: fn(&mut dyn Any) -> &mut T, } -impl Handle { - fn new(id: EntityId, entity_map: Weak>) -> Self { +unsafe impl Send for Handle {} +unsafe impl Sync for Handle {} + +impl Handle { + fn new(id: EntityId, entity_map: Weak>) -> Self + where + T: 'static, + { Self { any_handle: AnyHandle::new(id, TypeId::of::(), entity_map), entity_type: PhantomData, + downcast_entity: |any| any.downcast_ref().unwrap(), + downcast_entity_mut: |any| any.downcast_mut().unwrap(), } } @@ -274,6 +262,8 @@ impl Handle { WeakHandle { any_handle: self.any_handle.downgrade(), entity_type: self.entity_type, + downcast_entity: self.downcast_entity, + downcast_entity_mut: self.downcast_entity_mut, } } @@ -286,25 +276,30 @@ impl Handle { /// The update function receives a context appropriate for its environment. /// When updating in an `AppContext`, it receives a `ModelContext`. /// When updating an a `WindowContext`, it receives a `ViewContext`. - pub fn update( + pub fn update( &self, cx: &mut C, update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R, - ) -> C::Result { + ) -> C::Result + where + C: Context, + { cx.update_entity(self, update) } } -impl Clone for Handle { +impl Clone for Handle { fn clone(&self) -> Self { Self { any_handle: self.any_handle.clone(), entity_type: self.entity_type, + downcast_entity: self.downcast_entity, + downcast_entity_mut: self.downcast_entity_mut, } } } -impl std::fmt::Debug for Handle { +impl std::fmt::Debug for Handle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, @@ -315,19 +310,19 @@ impl std::fmt::Debug for Handle { } } -impl Hash for Handle { +impl Hash for Handle { fn hash(&self, state: &mut H) { self.any_handle.hash(state); } } -impl PartialEq for Handle { +impl PartialEq for Handle { fn eq(&self, other: &Self) -> bool { self.any_handle == other.any_handle } } -impl Eq for Handle {} +impl Eq for Handle {} #[derive(Clone)] pub struct AnyWeakHandle { @@ -365,10 +360,7 @@ impl AnyWeakHandle { } } -impl From> for AnyWeakHandle -where - T: 'static + Send + Sync, -{ +impl From> for AnyWeakHandle { fn from(handle: WeakHandle) -> Self { handle.any_handle } @@ -394,22 +386,31 @@ pub struct WeakHandle { #[deref_mut] any_handle: AnyWeakHandle, entity_type: PhantomData, + downcast_entity: fn(&dyn Any) -> &T, + pub(crate) downcast_entity_mut: fn(&mut dyn Any) -> &mut T, } -impl Clone for WeakHandle { +unsafe impl Send for WeakHandle {} +unsafe impl Sync for WeakHandle {} + +impl Clone for WeakHandle { fn clone(&self) -> Self { Self { any_handle: self.any_handle.clone(), entity_type: self.entity_type, + downcast_entity: self.downcast_entity, + downcast_entity_mut: self.downcast_entity_mut, } } } -impl WeakHandle { +impl WeakHandle { pub fn upgrade(&self) -> Option> { Some(Handle { any_handle: self.any_handle.upgrade()?, entity_type: self.entity_type, + downcast_entity: self.downcast_entity, + downcast_entity_mut: self.downcast_entity_mut, }) } @@ -420,12 +421,13 @@ impl WeakHandle { /// The update function receives a context appropriate for its environment. /// When updating in an `AppContext`, it receives a `ModelContext`. /// When updating an a `WindowContext`, it receives a `ViewContext`. - pub fn update( + pub fn update( &self, cx: &mut C, update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R, ) -> Result where + C: Context, Result>: crate::Flatten, { crate::Flatten::flatten( @@ -436,16 +438,16 @@ impl WeakHandle { } } -impl Hash for WeakHandle { +impl Hash for WeakHandle { fn hash(&self, state: &mut H) { self.any_handle.hash(state); } } -impl PartialEq for WeakHandle { +impl PartialEq for WeakHandle { fn eq(&self, other: &Self) -> bool { self.any_handle == other.any_handle } } -impl Eq for WeakHandle {} +impl Eq for WeakHandle {} diff --git a/crates/gpui2/src/app/model_context.rs b/crates/gpui2/src/app/model_context.rs index 35237d91cf..faf766ea7f 100644 --- a/crates/gpui2/src/app/model_context.rs +++ b/crates/gpui2/src/app/model_context.rs @@ -5,10 +5,9 @@ use crate::{ use derive_more::{Deref, DerefMut}; use futures::FutureExt; use std::{ - any::TypeId, + any::{Any, TypeId}, borrow::{Borrow, BorrowMut}, future::Future, - marker::PhantomData, }; #[derive(Deref, DerefMut)] @@ -16,21 +15,19 @@ pub struct ModelContext<'a, T> { #[deref] #[deref_mut] app: Reference<'a, AppContext>, - entity_type: PhantomData, - entity_id: EntityId, + model_state: WeakHandle, } -impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { - pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self { +impl<'a, T: 'static> ModelContext<'a, T> { + pub(crate) fn mutable(app: &'a mut AppContext, model_state: WeakHandle) -> Self { Self { app: Reference::Mutable(app), - entity_type: PhantomData, - entity_id, + model_state, } } pub fn entity_id(&self) -> EntityId { - self.entity_id + self.model_state.entity_id } pub fn handle(&self) -> Handle { @@ -40,14 +37,17 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { } pub fn weak_handle(&self) -> WeakHandle { - self.app.entities.weak_handle(self.entity_id) + self.model_state.clone() } - pub fn observe( + pub fn observe( &mut self, - handle: &Handle, - on_notify: impl Fn(&mut T, Handle, &mut ModelContext<'_, T>) + Send + Sync + 'static, - ) -> Subscription { + handle: &Handle, + on_notify: impl Fn(&mut T, Handle, &mut ModelContext<'_, T>) + Send + Sync + 'static, + ) -> Subscription + where + T: Any + Send + Sync, + { let this = self.weak_handle(); let handle = handle.downgrade(); self.app.observers.insert( @@ -63,14 +63,17 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { ) } - pub fn subscribe( + pub fn subscribe( &mut self, handle: &Handle, on_event: impl Fn(&mut T, Handle, &E::Event, &mut ModelContext<'_, T>) + Send + Sync + 'static, - ) -> Subscription { + ) -> Subscription + where + T: Any + Send + Sync, + { let this = self.weak_handle(); let handle = handle.downgrade(); self.app.event_listeners.insert( @@ -90,9 +93,12 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { pub fn on_release( &mut self, on_release: impl Fn(&mut T, &mut AppContext) + Send + Sync + 'static, - ) -> Subscription { + ) -> Subscription + where + T: 'static, + { self.app.release_listeners.insert( - self.entity_id, + self.model_state.entity_id, Box::new(move |this, cx| { let this = this.downcast_mut().expect("invalid entity type"); on_release(this, cx); @@ -100,11 +106,14 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { ) } - pub fn observe_release( + pub fn observe_release( &mut self, handle: &Handle, on_release: impl Fn(&mut T, &mut E, &mut ModelContext<'_, T>) + Send + Sync + 'static, - ) -> Subscription { + ) -> Subscription + where + T: Any + Send + Sync, + { let this = self.weak_handle(); self.app.release_listeners.insert( handle.entity_id, @@ -120,7 +129,10 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { pub fn observe_global( &mut self, f: impl Fn(&mut T, &mut ModelContext<'_, T>) + Send + Sync + 'static, - ) -> Subscription { + ) -> Subscription + where + T: Any + Send + Sync, + { let handle = self.weak_handle(); self.global_observers.insert( TypeId::of::(), @@ -134,6 +146,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { ) -> Subscription where Fut: 'static + Future + Send, + T: Any + Send + Sync, { let handle = self.weak_handle(); self.app.quit_observers.insert( @@ -151,9 +164,13 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { } pub fn notify(&mut self) { - if self.app.pending_notifications.insert(self.entity_id) { + if self + .app + .pending_notifications + .insert(self.model_state.entity_id) + { self.app.pending_effects.push_back(Effect::Notify { - emitter: self.entity_id, + emitter: self.model_state.entity_id, }); } } @@ -163,8 +180,8 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { G: 'static + Send + Sync, { let mut global = self.app.lease_global::(); - let result = f(global.as_mut(), self); - self.app.restore_global(global); + let result = f(&mut global, self); + self.app.end_global_lease(global); result } @@ -173,6 +190,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { f: impl FnOnce(WeakHandle, AsyncAppContext) -> Fut + Send + 'static, ) -> Task where + T: 'static, Fut: Future + Send + 'static, R: Send + 'static, { @@ -193,27 +211,34 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> { } } -impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> { +impl<'a, T> ModelContext<'a, T> +where + T: EventEmitter, + T::Event: Send + Sync, +{ pub fn emit(&mut self, event: T::Event) { self.app.pending_effects.push_back(Effect::Emit { - emitter: self.entity_id, + emitter: self.model_state.entity_id, event: Box::new(event), }); } } -impl<'a, T: 'static> Context for ModelContext<'a, T> { - type EntityContext<'b, 'c, U: Send + Sync + 'static> = ModelContext<'b, U>; +impl<'a, T> Context for ModelContext<'a, T> { + type EntityContext<'b, 'c, U> = ModelContext<'b, U>; type Result = U; - fn entity( + fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U, - ) -> Handle { + ) -> Handle + where + U: 'static + Send + Sync, + { self.app.entity(build_entity) } - fn update_entity( + fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R, diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 1fd72554eb..a6efbe52eb 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,11 +1,11 @@ use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, ViewContext}; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; -use std::mem; +use std::{any::Any, mem}; -pub trait Element: 'static + Send + Sync + IntoAnyElement { - type ViewState: 'static + Send + Sync; - type ElementState: 'static + Send + Sync; +pub trait Element: IntoAnyElement { + type ViewState: 'static; + type ElementState: 'static; fn id(&self) -> Option; @@ -15,6 +15,8 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement { element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState; + // where + // Self::ViewState: Any + Send + Sync; fn layout( &mut self, @@ -22,6 +24,8 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement { element_state: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId; + // where + // Self::ViewState: Any + Send + Sync; fn paint( &mut self, @@ -30,6 +34,9 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement { element_state: &mut Self::ElementState, cx: &mut ViewContext, ); + + // where + // Self::ViewState: Any + Send + Sync; } #[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] @@ -59,7 +66,7 @@ pub trait ParentElement: Element { } } -trait ElementObject: 'static + Send + Sync { +trait ElementObject { fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext); fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext) -> LayoutId; fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext); @@ -99,6 +106,8 @@ impl RenderedElement { impl ElementObject for RenderedElement where E: Element, + // E::ViewState: Any + Send + Sync, + E::ElementState: Any + Send + Sync, { fn initialize(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext) { let frame_state = if let Some(id) = self.element.id() { @@ -171,10 +180,15 @@ where } } -pub struct AnyElement(Box>); +pub struct AnyElement(Box + Send + Sync>); -impl AnyElement { - pub fn new>(element: E) -> Self { +impl AnyElement { + pub fn new(element: E) -> Self + where + E: 'static + Send + Sync, + E: Element, + E::ElementState: Any + Send + Sync, + { AnyElement(Box::new(RenderedElement::new(element))) } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 2753d5f8fb..71196eadca 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -9,7 +9,7 @@ use refineable::Refineable; use smallvec::SmallVec; pub struct Div< - V: 'static + Send + Sync, + V: 'static, I: ElementInteraction = StatelessInteraction, F: ElementFocus = FocusDisabled, > { @@ -20,10 +20,7 @@ pub struct Div< base_style: StyleRefinement, } -pub fn div() -> Div, FocusDisabled> -where - V: 'static + Send + Sync, -{ +pub fn div() -> Div, FocusDisabled> { Div { interaction: StatelessInteraction::default(), focus: FocusDisabled, @@ -35,8 +32,8 @@ where impl Div, F> where + V: 'static, F: ElementFocus, - V: 'static + Send + Sync, { pub fn id(self, id: impl Into) -> Div, F> { Div { @@ -53,7 +50,6 @@ impl Div where I: ElementInteraction, F: ElementFocus, - V: 'static + Send + Sync, { pub fn group(mut self, group: impl Into) -> Self { self.group = Some(group.into()); @@ -108,10 +104,7 @@ where } } -impl Div, FocusDisabled> -where - V: 'static + Send + Sync, -{ +impl Div, FocusDisabled> { pub fn focusable(self) -> Div, FocusEnabled> { Div { interaction: self.interaction, @@ -152,10 +145,7 @@ where } } -impl Div, FocusDisabled> -where - V: 'static + Send + Sync, -{ +impl Div, FocusDisabled> { pub fn track_focus( self, handle: &FocusHandle, @@ -172,8 +162,8 @@ where impl Focusable for Div> where + V: 'static, I: ElementInteraction, - V: 'static + Send + Sync, { fn focus_listeners(&mut self) -> &mut FocusListeners { &mut self.focus.focus_listeners @@ -203,7 +193,6 @@ impl Element for Div where I: ElementInteraction, F: ElementFocus, - V: 'static + Send + Sync, { type ViewState = V; type ElementState = DivState; @@ -317,9 +306,9 @@ where impl IntoAnyElement for Div where + // V: Any + Send + Sync, I: ElementInteraction, F: ElementFocus, - V: 'static + Send + Sync, { fn into_any(self) -> AnyElement { AnyElement::new(self) @@ -330,7 +319,6 @@ impl ParentElement for Div where I: ElementInteraction, F: ElementFocus, - V: 'static + Send + Sync, { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { &mut self.children @@ -341,7 +329,6 @@ impl Styled for Div where I: ElementInteraction, F: ElementFocus, - V: 'static + Send + Sync, { fn style(&mut self) -> &mut StyleRefinement { &mut self.base_style @@ -352,7 +339,6 @@ impl StatelessInteractive for Div where I: ElementInteraction, F: ElementFocus, - V: 'static + Send + Sync, { fn stateless_interaction(&mut self) -> &mut StatelessInteraction { self.interaction.as_stateless_mut() @@ -362,7 +348,6 @@ where impl StatefulInteractive for Div, F> where F: ElementFocus, - V: 'static + Send + Sync, { fn stateful_interaction(&mut self) -> &mut StatefulInteraction { &mut self.interaction diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 713bc8b98d..adce6aea6b 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -8,7 +8,7 @@ use futures::FutureExt; use util::ResultExt; pub struct Img< - V: 'static + Send + Sync, + V: 'static, I: ElementInteraction = StatelessInteraction, F: ElementFocus = FocusDisabled, > { @@ -17,10 +17,7 @@ pub struct Img< grayscale: bool, } -pub fn img() -> Img, FocusDisabled> -where - V: 'static + Send + Sync, -{ +pub fn img() -> Img, FocusDisabled> { Img { base: div(), uri: None, @@ -30,7 +27,7 @@ where impl Img where - V: 'static + Send + Sync, + V: 'static, I: ElementInteraction, F: ElementFocus, { @@ -47,7 +44,6 @@ where impl Img, F> where - V: 'static + Send + Sync, F: ElementFocus, { pub fn id(self, id: impl Into) -> Img, F> { @@ -61,7 +57,6 @@ where impl IntoAnyElement for Img where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -72,7 +67,6 @@ where impl Element for Img where - V: Send + Sync + 'static, I: ElementInteraction, F: ElementFocus, { @@ -141,7 +135,6 @@ where impl Styled for Img where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -152,7 +145,6 @@ where impl StatelessInteractive for Img where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -163,7 +155,6 @@ where impl StatefulInteractive for Img, F> where - V: 'static + Send + Sync, F: ElementFocus, { fn stateful_interaction(&mut self) -> &mut StatefulInteraction { @@ -173,7 +164,7 @@ where impl Focusable for Img> where - V: 'static + Send + Sync, + V: 'static, I: ElementInteraction, { fn focus_listeners(&mut self) -> &mut FocusListeners { diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index 3785ce480e..7e9017264f 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -7,7 +7,7 @@ use crate::{ use util::ResultExt; pub struct Svg< - V: 'static + Send + Sync, + V: 'static, I: ElementInteraction = StatelessInteraction, F: ElementFocus = FocusDisabled, > { @@ -15,10 +15,7 @@ pub struct Svg< path: Option, } -pub fn svg() -> Svg, FocusDisabled> -where - V: 'static + Send + Sync, -{ +pub fn svg() -> Svg, FocusDisabled> { Svg { base: div(), path: None, @@ -27,7 +24,6 @@ where impl Svg where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -39,7 +35,6 @@ where impl Svg, F> where - V: 'static + Send + Sync, F: ElementFocus, { pub fn id(self, id: impl Into) -> Svg, F> { @@ -52,7 +47,6 @@ where impl IntoAnyElement for Svg where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -63,7 +57,6 @@ where impl Element for Svg where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -115,7 +108,6 @@ where impl Styled for Svg where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -126,7 +118,6 @@ where impl StatelessInteractive for Svg where - V: 'static + Send + Sync, I: ElementInteraction, F: ElementFocus, { @@ -137,7 +128,7 @@ where impl StatefulInteractive for Svg, F> where - V: 'static + Send + Sync, + V: 'static, F: ElementFocus, { fn stateful_interaction(&mut self) -> &mut StatefulInteraction { @@ -145,9 +136,8 @@ where } } -impl Focusable for Svg> +impl Focusable for Svg> where - V: 'static + Send + Sync, I: ElementInteraction, { fn focus_listeners(&mut self) -> &mut FocusListeners { diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index ff1a9e2335..7b0052826c 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -7,8 +7,8 @@ use smallvec::SmallVec; use std::{marker::PhantomData, sync::Arc}; use util::ResultExt; -impl IntoAnyElement for SharedString { - fn into_any(self) -> AnyElement { +impl IntoAnyElement for SharedString { + fn into_any(self) -> AnyElement { Text { text: self, state_type: PhantomData, @@ -17,7 +17,7 @@ impl IntoAnyElement for SharedString { } } -impl IntoAnyElement for &'static str { +impl IntoAnyElement for &'static str { fn into_any(self) -> AnyElement { Text { text: self.into(), @@ -29,8 +29,8 @@ impl IntoAnyElement for &'static str { // TODO: Figure out how to pass `String` to `child` without this. // This impl doesn't exist in the `gpui2` crate. -impl IntoAnyElement for String { - fn into_any(self) -> AnyElement { +impl IntoAnyElement for String { + fn into_any(self) -> AnyElement { Text { text: self.into(), state_type: PhantomData, @@ -44,13 +44,16 @@ pub struct Text { state_type: PhantomData, } -impl IntoAnyElement for Text { +unsafe impl Send for Text {} +unsafe impl Sync for Text {} + +impl IntoAnyElement for Text { fn into_any(self) -> AnyElement { AnyElement::new(self) } } -impl Element for Text { +impl Element for Text { type ViewState = V; type ElementState = Arc>>; diff --git a/crates/gpui2/src/focusable.rs b/crates/gpui2/src/focusable.rs index 2173d70416..3345b4c6c6 100644 --- a/crates/gpui2/src/focusable.rs +++ b/crates/gpui2/src/focusable.rs @@ -135,7 +135,7 @@ pub trait Focusable: Element { } } -pub trait ElementFocus: 'static + Send + Sync { +pub trait ElementFocus: 'static + Send + Sync { fn as_focusable(&self) -> Option<&FocusEnabled>; fn as_focusable_mut(&mut self) -> Option<&mut FocusEnabled>; @@ -200,7 +200,7 @@ pub trait ElementFocus: 'static + Send + Sync { } } -pub struct FocusEnabled { +pub struct FocusEnabled { pub focus_handle: Option, pub focus_listeners: FocusListeners, pub focus_style: StyleRefinement, @@ -208,10 +208,7 @@ pub struct FocusEnabled { pub in_focus_style: StyleRefinement, } -impl FocusEnabled -where - V: 'static + Send + Sync, -{ +impl FocusEnabled { pub fn new() -> Self { Self { focus_handle: None, @@ -233,10 +230,7 @@ where } } -impl ElementFocus for FocusEnabled -where - V: 'static + Send + Sync, -{ +impl ElementFocus for FocusEnabled { fn as_focusable(&self) -> Option<&FocusEnabled> { Some(self) } @@ -246,10 +240,7 @@ where } } -impl From for FocusEnabled -where - V: 'static + Send + Sync, -{ +impl From for FocusEnabled { fn from(value: FocusHandle) -> Self { Self { focus_handle: Some(value), @@ -263,10 +254,7 @@ where pub struct FocusDisabled; -impl ElementFocus for FocusDisabled -where - V: 'static + Send + Sync, -{ +impl ElementFocus for FocusDisabled { fn as_focusable(&self) -> Option<&FocusEnabled> { None } diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 95b96c1868..ef95fdfdf2 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -66,15 +66,17 @@ use taffy::TaffyLayoutEngine; type AnyBox = Box; pub trait Context { - type EntityContext<'a, 'w, T: 'static + Send + Sync>; + type EntityContext<'a, 'w, T>; type Result; - fn entity( + fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, - ) -> Self::Result>; + ) -> Self::Result> + where + T: 'static + Send + Sync; - fn update_entity( + fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, @@ -105,13 +107,16 @@ impl DerefMut for MainThread { } impl Context for MainThread { - type EntityContext<'a, 'w, T: 'static + Send + Sync> = MainThread>; + type EntityContext<'a, 'w, T> = MainThread>; type Result = C::Result; - fn entity( + fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, - ) -> Self::Result> { + ) -> Self::Result> + where + T: Any + Send + Sync, + { self.0.entity(|cx| { let cx = unsafe { mem::transmute::< @@ -123,7 +128,7 @@ impl Context for MainThread { }) } - fn update_entity( + fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, @@ -162,13 +167,13 @@ where result } - fn set_global(&mut self, global: T) { + fn set_global(&mut self, global: G) { self.borrow_mut().set_global(global) } } -pub trait EventEmitter { - type Event: Any + Send + Sync + 'static; +pub trait EventEmitter: 'static { + type Event: Any; } pub trait Flatten { diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 925763bd4e..652ff7af0c 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -361,8 +361,9 @@ pub trait StatefulInteractive: StatelessInteractive { ) -> Self where Self: Sized, - S: 'static + Send + Sync, - R: 'static + Fn(&mut Self::ViewState, &mut ViewContext) -> E + Send + Sync, + S: Any + Send + Sync, + R: Fn(&mut Self::ViewState, &mut ViewContext) -> E, + R: 'static + Send + Sync, E: Element, { debug_assert!( @@ -388,7 +389,7 @@ pub trait StatefulInteractive: StatelessInteractive { } } -pub trait ElementInteraction: 'static + Send + Sync { +pub trait ElementInteraction: 'static + Send + Sync { fn as_stateless(&self) -> &StatelessInteraction; fn as_stateless_mut(&mut self) -> &mut StatelessInteraction; fn as_stateful(&self) -> Option<&StatefulInteraction>; @@ -682,7 +683,7 @@ pub trait ElementInteraction: 'static + Send + Sync { } #[derive(Deref, DerefMut)] -pub struct StatefulInteraction { +pub struct StatefulInteraction { pub id: ElementId, #[deref] #[deref_mut] @@ -693,10 +694,7 @@ pub struct StatefulInteraction { drag_listener: Option>, } -impl ElementInteraction for StatefulInteraction -where - V: 'static + Send + Sync, -{ +impl ElementInteraction for StatefulInteraction { fn as_stateful(&self) -> Option<&StatefulInteraction> { Some(self) } @@ -714,10 +712,7 @@ where } } -impl From for StatefulInteraction -where - V: 'static + Send + Sync, -{ +impl From for StatefulInteraction { fn from(id: ElementId) -> Self { Self { id, @@ -730,7 +725,7 @@ where } } -type DropListener = dyn Fn(&mut V, AnyBox, &mut ViewContext) + Send + Sync; +type DropListener = dyn Fn(&mut V, AnyBox, &mut ViewContext) + 'static + Send + Sync; pub struct StatelessInteraction { pub dispatch_context: DispatchContext, @@ -746,10 +741,7 @@ pub struct StatelessInteraction { drop_listeners: SmallVec<[(TypeId, Arc>); 2]>, } -impl StatelessInteraction -where - V: 'static + Send + Sync, -{ +impl StatelessInteraction { pub fn into_stateful(self, id: impl Into) -> StatefulInteraction { StatefulInteraction { id: id.into(), @@ -841,10 +833,7 @@ impl Default for StatelessInteraction { } } -impl ElementInteraction for StatelessInteraction -where - V: 'static + Send + Sync, -{ +impl ElementInteraction for StatelessInteraction { fn as_stateful(&self) -> Option<&StatefulInteraction> { None } @@ -919,9 +908,7 @@ pub struct ClickEvent { pub struct Drag where - S: 'static + Send + Sync, R: Fn(&mut V, &mut ViewContext) -> E, - V: 'static + Send + Sync, E: Element, { pub state: S, @@ -931,9 +918,7 @@ where impl Drag where - S: 'static + Send + Sync, - R: Fn(&mut V, &mut ViewContext) -> E + Send + Sync, - V: 'static + Send + Sync, + R: Fn(&mut V, &mut ViewContext) -> E, E: Element, { pub fn new(state: S, render_drag_handle: R) -> Self { diff --git a/crates/gpui2/src/platform.rs b/crates/gpui2/src/platform.rs index d7ef60616a..fbae6c898b 100644 --- a/crates/gpui2/src/platform.rs +++ b/crates/gpui2/src/platform.rs @@ -102,7 +102,7 @@ pub(crate) trait Platform: 'static { fn delete_credentials(&self, url: &str) -> Result<()>; } -pub trait PlatformDisplay: Debug { +pub trait PlatformDisplay: Send + Sync + Debug { fn id(&self) -> DisplayId; fn as_any(&self) -> &dyn Any; fn bounds(&self) -> Bounds; diff --git a/crates/gpui2/src/subscription.rs b/crates/gpui2/src/subscription.rs index 214006b754..2b83ccc1ef 100644 --- a/crates/gpui2/src/subscription.rs +++ b/crates/gpui2/src/subscription.rs @@ -21,7 +21,7 @@ struct SubscriberSetState { impl SubscriberSet where - EmitterKey: 'static + Send + Sync + Ord + Clone + Debug, + EmitterKey: 'static + Ord + Clone + Debug, Callback: 'static + Send + Sync, { pub fn new() -> Self { @@ -96,7 +96,7 @@ where #[must_use] pub struct Subscription { - unsubscribe: Option>, + unsubscribe: Option>, } impl Subscription { diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index a8a4d650d6..ed633e8966 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -6,12 +6,12 @@ use crate::{ }; use std::{marker::PhantomData, sync::Arc}; -pub struct View { +pub struct View { state: Handle, render: Arc) -> AnyElement + Send + Sync + 'static>, } -impl View { +impl View { pub fn into_any(self) -> AnyView { AnyView { view: Arc::new(Mutex::new(self)), @@ -19,7 +19,7 @@ impl View { } } -impl Clone for View { +impl Clone for View { fn clone(&self) -> Self { Self { state: self.state.clone(), @@ -34,7 +34,6 @@ pub fn view( ) -> View where E: IntoAnyElement, - V: 'static + Send + Sync, { View { state, @@ -42,9 +41,7 @@ where } } -impl - IntoAnyElement for View -{ +impl IntoAnyElement for View { fn into_any(self) -> AnyElement { AnyElement::new(EraseViewState { view: self, @@ -53,7 +50,7 @@ impl } } -impl Element for View { +impl Element for View { type ViewState = (); type ElementState = AnyElement; @@ -94,26 +91,21 @@ impl Element for View { } } -struct EraseViewState { +struct EraseViewState { view: View, parent_view_state_type: PhantomData, } -impl IntoAnyElement for EraseViewState -where - V: 'static + Send + Sync, - ParentV: 'static + Send + Sync, -{ +unsafe impl Send for EraseViewState {} +unsafe impl Sync for EraseViewState {} + +impl IntoAnyElement for EraseViewState { fn into_any(self) -> AnyElement { AnyElement::new(self) } } -impl Element for EraseViewState -where - V: 'static + Send + Sync, - ParentV: 'static + Send + Sync, -{ +impl Element for EraseViewState { type ViewState = ParentV; type ElementState = AnyBox; @@ -150,14 +142,14 @@ where } } -trait ViewObject: 'static + Send + Sync { +trait ViewObject: Send + Sync { fn entity_id(&self) -> EntityId; fn initialize(&mut self, cx: &mut WindowContext) -> AnyBox; fn layout(&mut self, element: &mut AnyBox, cx: &mut WindowContext) -> LayoutId; fn paint(&mut self, bounds: Bounds, element: &mut AnyBox, cx: &mut WindowContext); } -impl ViewObject for View { +impl ViewObject for View { fn entity_id(&self) -> EntityId { self.state.entity_id } @@ -195,10 +187,7 @@ pub struct AnyView { view: Arc>, } -impl IntoAnyElement for AnyView -where - ParentV: 'static + Send + Sync, -{ +impl IntoAnyElement for AnyView { fn into_any(self) -> AnyElement { AnyElement::new(EraseAnyViewState { view: self, @@ -249,19 +238,16 @@ struct EraseAnyViewState { parent_view_state_type: PhantomData, } -impl IntoAnyElement for EraseAnyViewState -where - ParentV: 'static + Send + Sync, -{ +unsafe impl Send for EraseAnyViewState {} +unsafe impl Sync for EraseAnyViewState {} + +impl IntoAnyElement for EraseAnyViewState { fn into_any(self) -> AnyElement { AnyElement::new(self) } } -impl Element for EraseAnyViewState -where - ParentV: 'static + Send + Sync, -{ +impl Element for EraseAnyViewState { type ViewState = ParentV; type ElementState = AnyBox; diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index fcc49d2ef3..c6eff3590d 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -428,11 +428,11 @@ impl<'a, 'w> WindowContext<'a, 'w> { pub fn update_global(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R where - G: 'static + Send + Sync, + G: 'static, { let mut global = self.app.lease_global::(); - let result = f(global.as_mut(), self); - self.app.set_global(global); + let result = f(&mut global, self); + self.app.end_global_lease(global); result } @@ -1139,23 +1139,26 @@ impl<'a, 'w> WindowContext<'a, 'w> { } impl Context for WindowContext<'_, '_> { - type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>; + type EntityContext<'a, 'w, T> = ViewContext<'a, 'w, T>; type Result = T; - fn entity( + fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, - ) -> Handle { + ) -> Handle + where + T: Any + Send + Sync, + { let slot = self.app.entities.reserve(); let entity = build_entity(&mut ViewContext::mutable( &mut *self.app, &mut self.window, - slot.entity_id, + slot.downgrade(), )); self.entities.insert(slot, entity) } - fn update_entity( + fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, @@ -1163,7 +1166,7 @@ impl Context for WindowContext<'_, '_> { let mut entity = self.entities.lease(handle); let result = update( &mut *entity, - &mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.entity_id), + &mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.downgrade()), ); self.entities.end_lease(entity); result @@ -1271,11 +1274,14 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { .unwrap_or_default() } - fn with_element_state( + fn with_element_state( &mut self, id: ElementId, f: impl FnOnce(Option, &mut Self) -> (R, S), - ) -> R { + ) -> R + where + S: Any + Send + Sync, + { self.with_element_id(id, |global_id, cx| { if let Some(any) = cx .window_mut() @@ -1304,11 +1310,14 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { }) } - fn with_optional_element_state( + fn with_optional_element_state( &mut self, element_id: Option, f: impl FnOnce(Option, &mut Self) -> (R, S), - ) -> R { + ) -> R + where + S: Any + Send + Sync, + { if let Some(element_id) = element_id { self.with_element_state(element_id, f) } else { @@ -1350,8 +1359,7 @@ impl BorrowWindow for T where T: BorrowMut + BorrowMut {} pub struct ViewContext<'a, 'w, V> { window_cx: WindowContext<'a, 'w>, - entity_type: PhantomData, - entity_id: EntityId, + view_state: WeakHandle, } impl Borrow for ViewContext<'_, '_, V> { @@ -1378,17 +1386,16 @@ impl BorrowMut for ViewContext<'_, '_, V> { } } -impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { - fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self { +impl<'a, 'w, V: 'static> ViewContext<'a, 'w, V> { + fn mutable(app: &'a mut AppContext, window: &'w mut Window, view_state: WeakHandle) -> Self { Self { window_cx: WindowContext::mutable(app, window), - entity_id, - entity_type: PhantomData, + view_state, } } pub fn handle(&self) -> WeakHandle { - self.entities.weak_handle(self.entity_id) + self.view_state.clone() } pub fn stack(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R { @@ -1398,18 +1405,25 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { result } - pub fn on_next_frame(&mut self, f: impl FnOnce(&mut V, &mut ViewContext) + Send + 'static) { + pub fn on_next_frame(&mut self, f: impl FnOnce(&mut V, &mut ViewContext) + Send + 'static) + where + V: Any + Send + Sync, + { let entity = self.handle(); self.window_cx.on_next_frame(move |cx| { entity.update(cx, f).ok(); }); } - pub fn observe( + pub fn observe( &mut self, handle: &Handle, on_notify: impl Fn(&mut V, Handle, &mut ViewContext<'_, '_, V>) + Send + Sync + 'static, - ) -> Subscription { + ) -> Subscription + where + E: 'static, + V: Any + Send + Sync, + { let this = self.handle(); let handle = handle.downgrade(); let window_handle = self.window.handle; @@ -1429,7 +1443,7 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { ) } - pub fn subscribe( + pub fn subscribe( &mut self, handle: &Handle, on_event: impl Fn(&mut V, Handle, &E::Event, &mut ViewContext<'_, '_, V>) @@ -1463,7 +1477,7 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { ) -> Subscription { let window_handle = self.window.handle; self.app.release_listeners.insert( - self.entity_id, + self.view_state.entity_id, Box::new(move |this, cx| { let this = this.downcast_mut().expect("invalid entity type"); // todo!("are we okay with silently swallowing the error?") @@ -1472,11 +1486,14 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { ) } - pub fn observe_release( + pub fn observe_release( &mut self, - handle: &Handle, - on_release: impl Fn(&mut V, &mut E, &mut ViewContext<'_, '_, V>) + Send + Sync + 'static, - ) -> Subscription { + handle: &Handle, + on_release: impl Fn(&mut V, &mut T, &mut ViewContext<'_, '_, V>) + Send + Sync + 'static, + ) -> Subscription + where + V: Any + Send + Sync, + { let this = self.handle(); let window_handle = self.window.handle; self.app.release_listeners.insert( @@ -1494,7 +1511,7 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { pub fn notify(&mut self) { self.window_cx.notify(); self.window_cx.app.push_effect(Effect::Notify { - emitter: self.entity_id, + emitter: self.view_state.entity_id, }); } @@ -1633,8 +1650,8 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { G: 'static + Send + Sync, { let mut global = self.app.lease_global::(); - let result = f(global.as_mut(), self); - self.app.restore_global(global); + let result = f(&mut global, self); + self.app.end_global_lease(global); result } @@ -1668,9 +1685,13 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { } } -impl<'a, 'w, V: EventEmitter + Send + Sync + 'static> ViewContext<'a, 'w, V> { +impl<'a, 'w, V> ViewContext<'a, 'w, V> +where + V: EventEmitter, + V::Event: Any + Send + Sync, +{ pub fn emit(&mut self, event: V::Event) { - let emitter = self.entity_id; + let emitter = self.view_state.entity_id; self.app.push_effect(Effect::Emit { emitter, event: Box::new(event), @@ -1678,30 +1699,30 @@ impl<'a, 'w, V: EventEmitter + Send + Sync + 'static> ViewContext<'a, 'w, V> { } } -impl<'a, 'w, V> Context for ViewContext<'a, 'w, V> -where - V: 'static + Send + Sync, -{ - type EntityContext<'b, 'c, U: 'static + Send + Sync> = ViewContext<'b, 'c, U>; +impl<'a, 'w, V> Context for ViewContext<'a, 'w, V> { + type EntityContext<'b, 'c, U> = ViewContext<'b, 'c, U>; type Result = U; - fn entity( + fn entity( &mut self, - build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T2>) -> T2, - ) -> Handle { + build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, + ) -> Handle + where + T: 'static + Send + Sync, + { self.window_cx.entity(build_entity) } - fn update_entity( + fn update_entity( &mut self, - handle: &Handle, - update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R, + handle: &Handle, + update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, ) -> R { self.window_cx.update_entity(handle, update) } } -impl<'a, 'w, S: 'static> std::ops::Deref for ViewContext<'a, 'w, S> { +impl<'a, 'w, V> std::ops::Deref for ViewContext<'a, 'w, V> { type Target = WindowContext<'a, 'w>; fn deref(&self) -> &Self::Target { @@ -1709,7 +1730,7 @@ impl<'a, 'w, S: 'static> std::ops::Deref for ViewContext<'a, 'w, S> { } } -impl<'a, 'w, S: 'static> std::ops::DerefMut for ViewContext<'a, 'w, S> { +impl<'a, 'w, V> std::ops::DerefMut for ViewContext<'a, 'w, V> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.window_cx } @@ -1725,9 +1746,9 @@ impl WindowId { } #[derive(PartialEq, Eq)] -pub struct WindowHandle { +pub struct WindowHandle { id: WindowId, - state_type: PhantomData, + state_type: PhantomData, } impl Copy for WindowHandle {}