WIP: Try to store an Rc<RefCell> inside entity handles

This commit is contained in:
Nathan Sobo 2025-07-08 21:27:09 -06:00
parent df57754baf
commit 6256e80933
10 changed files with 123 additions and 130 deletions

View file

@ -402,7 +402,7 @@ impl AppContext for ExampleContext {
self.app.new(build_entity)
}
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<gpui::Reservation<T>> {
fn reserve_entity(&mut self) -> Self::Result<gpui::Reservation<T>> {
self.app.reserve_entity()
}

View file

@ -38,9 +38,9 @@ use crate::{
EventEmitter, FocusHandle, FocusMap, ForegroundExecutor, Global, KeyBinding, KeyContext,
Keymap, Keystroke, LayoutId, Menu, MenuItem, OwnedMenu, PathPromptOptions, Pixels, Platform,
PlatformDisplay, PlatformKeyboardLayout, Point, PromptBuilder, PromptButton, PromptHandle,
PromptLevel, Render, RenderImage, RenderablePromptHandle, Reservation, ScreenCaptureSource,
SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, Window, WindowAppearance,
WindowHandle, WindowId, WindowInvalidator,
PromptLevel, Render, RenderImage, RenderablePromptHandle, ScreenCaptureSource, SubscriberSet,
Subscription, SvgRenderer, Task, TextSystem, Window, WindowAppearance, WindowHandle, WindowId,
WindowInvalidator,
colors::{Colors, GlobalColors},
current_platform, hash, init_app_menus,
};
@ -930,11 +930,11 @@ impl App {
break;
}
for (entity_id, mut entity) in dropped {
for (entity_id, entity) in dropped {
self.observers.remove(&entity_id);
self.event_listeners.remove(&entity_id);
for release_callback in self.release_listeners.remove(&entity_id) {
release_callback(entity.as_mut(), self);
release_callback(entity.borrow_mut().deref_mut(), self);
}
}
}
@ -1746,9 +1746,9 @@ impl AppContext for App {
/// [`Entity`] handle will be returned, which can be used to access the entity in a context.
fn new<T: 'static>(&mut self, build_entity: impl FnOnce(&mut Context<T>) -> T) -> Entity<T> {
self.update(|cx| {
let slot = cx.entities.reserve();
let handle = slot.clone();
let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
let entity_id = cx.entities.reserve();
let entity = build_entity(&mut Context::new_context(cx, entity_id, None));
let handle = cx.entities.insert(entity_id, entity);
cx.push_effect(Effect::EntityCreated {
entity: handle.clone().into_any(),
@ -1756,24 +1756,22 @@ impl AppContext for App {
window: cx.window_update_stack.last().cloned(),
});
cx.entities.insert(slot, entity);
handle
})
}
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<Reservation<T>> {
Reservation(self.entities.reserve())
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
self.entities.reserve()
}
fn insert_entity<T: 'static>(
&mut self,
reservation: Reservation<T>,
entity_id: EntityId,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Self::Result<Entity<T>> {
self.update(|cx| {
let slot = reservation.0;
let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
cx.entities.insert(slot, entity)
let entity = build_entity(&mut Context::new_context(cx, entity_id, None));
cx.entities.insert(entity_id, entity)
})
}
@ -1785,13 +1783,11 @@ impl AppContext for App {
update: impl FnOnce(&mut T, &mut Context<T>) -> R,
) -> R {
self.update(|cx| {
let mut entity = cx.entities.lease(handle);
let result = update(
&mut entity,
&mut Context::new_context(cx, handle.downgrade()),
);
cx.entities.end_lease(entity);
result
let mut entity = cx.entities.get(handle.entity_id());
update(
entity.borrow_mut().downcast_mut().unwrap(),
&mut Context::new_context(cx, handle.entity_id(), Some(handle.downgrade())),
)
})
}

View file

@ -1,7 +1,8 @@
use crate::{
AnyView, AnyWindowHandle, App, AppCell, AppContext, BackgroundExecutor, BorrowAppContext,
Entity, EventEmitter, Focusable, ForegroundExecutor, Global, PromptButton, PromptLevel, Render,
Reservation, Result, Subscription, Task, VisualContext, Window, WindowHandle,
Entity, EntityId, EventEmitter, Focusable, ForegroundExecutor, Global, PromptButton,
PromptLevel, Render, Result, Subscription, Task, VisualContext, Window, WindowHandle,
app::NewEntityListener,
};
use anyhow::Context as _;
use derive_more::{Deref, DerefMut};
@ -32,7 +33,7 @@ impl AppContext for AsyncApp {
Ok(app.new(build_entity))
}
fn reserve_entity<T: 'static>(&mut self) -> Result<Reservation<T>> {
fn reserve_entity(&mut self) -> Result<EntityId> {
let app = self.app.upgrade().context("app was released")?;
let mut app = app.borrow_mut();
Ok(app.reserve_entity())
@ -40,12 +41,12 @@ impl AppContext for AsyncApp {
fn insert_entity<T: 'static>(
&mut self,
reservation: Reservation<T>,
entity_id: EntityId,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Result<Entity<T>> {
let app = self.app.upgrade().context("app was released")?;
let mut app = app.borrow_mut();
Ok(app.insert_entity(reservation, build_entity))
Ok(app.insert_entity(entity_id, build_entity))
}
fn update_entity<T: 'static, R>(
@ -342,17 +343,17 @@ impl AppContext for AsyncWindowContext {
self.window.update(self, |_, _, cx| cx.new(build_entity))
}
fn reserve_entity<T: 'static>(&mut self) -> Result<Reservation<T>> {
fn reserve_entity(&mut self) -> Result<EntityId> {
self.window.update(self, |_, _, cx| cx.reserve_entity())
}
fn insert_entity<T: 'static>(
&mut self,
reservation: Reservation<T>,
entity_id: EntityId,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Self::Result<Entity<T>> {
self.window
.update(self, |_, _, cx| cx.insert_entity(reservation, build_entity))
.update(self, |_, _, cx| cx.insert_entity(entity_id, build_entity))
}
fn update_entity<T: 'static, R>(

View file

@ -1,7 +1,7 @@
use crate::{
AnyView, AnyWindowHandle, AppContext, AsyncApp, DispatchPhase, Effect, EntityId, EventEmitter,
FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Reservation, SubscriberSet,
Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, SubscriberSet, Subscription,
Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
};
use anyhow::Result;
use derive_more::{Deref, DerefMut};
@ -22,17 +22,26 @@ pub struct Context<'a, T> {
#[deref]
#[deref_mut]
app: &'a mut App,
entity_state: WeakEntity<T>,
entity_id: EntityId,
entity_state: Option<WeakEntity<T>>,
}
impl<'a, T: 'static> Context<'a, T> {
pub(crate) fn new_context(app: &'a mut App, entity_state: WeakEntity<T>) -> Self {
Self { app, entity_state }
pub(crate) fn new_context(
app: &'a mut App,
entity_id: EntityId,
entity_state: Option<WeakEntity<T>>,
) -> Self {
Self {
app,
entity_id,
entity_state,
}
}
/// The entity id of the entity backing this context.
pub fn entity_id(&self) -> EntityId {
self.entity_state.entity_id
self.entity_id
}
/// Returns a handle to the entity belonging to this context.
@ -44,7 +53,7 @@ impl<'a, T: 'static> Context<'a, T> {
/// Returns a weak handle to the entity belonging to this context.
pub fn weak_entity(&self) -> WeakEntity<T> {
self.entity_state.clone()
self.entity_state.as_ref().unwrap().clone()
}
/// Arranges for the given function to be called whenever [`Context::notify`] is
@ -112,7 +121,7 @@ impl<'a, T: 'static> Context<'a, T> {
T: 'static,
{
let (subscription, activate) = self.app.release_listeners.insert(
self.entity_state.entity_id,
self.entity_id,
Box::new(move |this, cx| {
let this = this.downcast_mut().expect("invalid entity type");
on_release(this, cx);
@ -193,7 +202,7 @@ impl<'a, T: 'static> Context<'a, T> {
/// Tell GPUI that this entity has changed and observers of it should be notified.
pub fn notify(&mut self) {
self.app.notify(self.entity_state.entity_id);
self.app.notify(self.entity_id);
}
/// Spawn the future returned by the given function.
@ -692,7 +701,7 @@ impl<T> Context<'_, T> {
Evt: 'static,
{
self.app.pending_effects.push_back(Effect::Emit {
emitter: self.entity_state.entity_id,
emitter: self.entity_id,
event_type: TypeId::of::<Evt>(),
event: Box::new(event),
});
@ -706,16 +715,16 @@ impl<T> AppContext for Context<'_, T> {
self.app.new(build_entity)
}
fn reserve_entity<U: 'static>(&mut self) -> Reservation<U> {
fn reserve_entity(&mut self) -> EntityId {
self.app.reserve_entity()
}
fn insert_entity<U: 'static>(
&mut self,
reservation: Reservation<U>,
entity_id: EntityId,
build_entity: impl FnOnce(&mut Context<U>) -> U,
) -> Self::Result<Entity<U>> {
self.app.insert_entity(reservation, build_entity)
self.app.insert_entity(entity_id, build_entity)
}
fn update_entity<U: 'static, R>(

View file

@ -13,6 +13,7 @@ use std::{
marker::PhantomData,
mem,
num::NonZeroU64,
rc::{self, Rc},
sync::{
Arc, Weak,
atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst},
@ -55,9 +56,9 @@ impl Display for EntityId {
}
pub(crate) struct EntityMap {
entities: SecondaryMap<EntityId, Box<dyn Any>>,
entities: SecondaryMap<EntityId, Rc<RefCell<dyn Any>>>,
pub accessed_entities: RefCell<FxHashSet<EntityId>>,
ref_counts: Arc<RwLock<EntityRefCounts>>,
pub(crate) ref_counts: Arc<RwLock<EntityRefCounts>>,
}
struct EntityRefCounts {
@ -85,47 +86,28 @@ impl EntityMap {
}
/// Reserve a slot for an entity, which you can subsequently use with `insert`.
pub fn reserve<T: 'static>(&self) -> Slot<T> {
let id = self.ref_counts.write().counts.insert(1.into());
Slot(Entity::new(id, Arc::downgrade(&self.ref_counts)))
pub fn reserve(&self) -> EntityId {
self.ref_counts.write().counts.insert(1.into())
}
/// Insert an entity into a slot obtained by calling `reserve`.
pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Entity<T>
pub fn insert<T>(&mut self, entity_id: EntityId, entity: T) -> Entity<T>
where
T: 'static,
{
let mut accessed_entities = self.accessed_entities.borrow_mut();
accessed_entities.insert(slot.entity_id);
accessed_entities.insert(entity_id);
let handle = slot.0;
self.entities.insert(handle.entity_id, Box::new(entity));
handle
let entity_data = Rc::new(RefCell::new(entity));
self.entities.insert(entity_id, entity_data.clone());
Entity::new(entity_id, entity_data, Arc::downgrade(&self.ref_counts))
}
/// Move an entity to the stack.
#[track_caller]
pub fn lease<'a, T>(&mut self, pointer: &'a Entity<T>) -> Lease<'a, T> {
self.assert_valid_context(pointer);
pub fn get(&self, entity_id: EntityId) -> Rc<RefCell<dyn Any>> {
let mut accessed_entities = self.accessed_entities.borrow_mut();
accessed_entities.insert(pointer.entity_id);
let entity = Some(
self.entities
.remove(pointer.entity_id)
.unwrap_or_else(|| double_lease_panic::<T>("update")),
);
Lease {
entity,
pointer,
entity_type: PhantomData,
}
}
/// Returns an entity after moving it to the stack.
pub fn end_lease<T>(&mut self, mut lease: Lease<T>) {
self.entities
.insert(lease.pointer.entity_id, lease.entity.take().unwrap());
accessed_entities.insert(entity_id);
self.entities.get(entity_id).unwrap().clone()
}
pub fn read<T: 'static>(&self, entity: &Entity<T>) -> &T {
@ -133,15 +115,16 @@ impl EntityMap {
let mut accessed_entities = self.accessed_entities.borrow_mut();
accessed_entities.insert(entity.entity_id);
self.entities
.get(entity.entity_id)
.and_then(|entity| entity.downcast_ref())
.unwrap_or_else(|| double_lease_panic::<T>("read"))
// self.entities
// .get(entity.entity_id)
// .and_then(|entity| entity.borrow().downcast_ref())
// .unwrap_or_else(|| double_lease_panic::<T>("read"))
todo!("interface will need to change here")
}
fn assert_valid_context(&self, entity: &AnyEntity) {
debug_assert!(
Weak::ptr_eq(&entity.entity_map, &Arc::downgrade(&self.ref_counts)),
Weak::ptr_eq(&entity.ref_counts, &Arc::downgrade(&self.ref_counts)),
"used a entity with the wrong context"
);
}
@ -156,7 +139,7 @@ impl EntityMap {
self.accessed_entities.borrow_mut().clear();
}
pub fn take_dropped(&mut self) -> Vec<(EntityId, Box<dyn Any>)> {
pub fn take_dropped(&mut self) -> Vec<(EntityId, Rc<RefCell<dyn Any>>)> {
let mut ref_counts = self.ref_counts.write();
let dropped_entity_ids = mem::take(&mut ref_counts.dropped_entity_ids);
let mut accessed_entities = self.accessed_entities.borrow_mut();
@ -222,19 +205,26 @@ pub(crate) struct Slot<T>(Entity<T>);
pub struct AnyEntity {
pub(crate) entity_id: EntityId,
pub(crate) entity_type: TypeId,
entity_map: Weak<RwLock<EntityRefCounts>>,
entity_data: Rc<RefCell<dyn Any>>,
ref_counts: Weak<RwLock<EntityRefCounts>>,
#[cfg(any(test, feature = "leak-detection"))]
handle_id: HandleId,
}
impl AnyEntity {
fn new(id: EntityId, entity_type: TypeId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self {
fn new(
id: EntityId,
entity_type: TypeId,
entity_data: Rc<RefCell<dyn Any>>,
ref_counts: Weak<RwLock<EntityRefCounts>>,
) -> Self {
Self {
entity_id: id,
entity_type,
entity_map: entity_map.clone(),
entity_data,
ref_counts: ref_counts.clone(),
#[cfg(any(test, feature = "leak-detection"))]
handle_id: entity_map
handle_id: ref_counts
.upgrade()
.unwrap()
.write()
@ -258,7 +248,8 @@ impl AnyEntity {
AnyWeakEntity {
entity_id: self.entity_id,
entity_type: self.entity_type,
entity_ref_counts: self.entity_map.clone(),
entity_data: Rc::downgrade(&self.entity_data),
entity_ref_counts: self.ref_counts.clone(),
}
}
@ -278,7 +269,7 @@ impl AnyEntity {
impl Clone for AnyEntity {
fn clone(&self) -> Self {
if let Some(entity_map) = self.entity_map.upgrade() {
if let Some(entity_map) = self.ref_counts.upgrade() {
let entity_map = entity_map.read();
let count = entity_map
.counts
@ -291,10 +282,11 @@ impl Clone for AnyEntity {
Self {
entity_id: self.entity_id,
entity_type: self.entity_type,
entity_map: self.entity_map.clone(),
entity_data: self.entity_data.clone(),
ref_counts: self.ref_counts.clone(),
#[cfg(any(test, feature = "leak-detection"))]
handle_id: self
.entity_map
.ref_counts
.upgrade()
.unwrap()
.write()
@ -306,7 +298,7 @@ impl Clone for AnyEntity {
impl Drop for AnyEntity {
fn drop(&mut self) {
if let Some(entity_map) = self.entity_map.upgrade() {
if let Some(entity_map) = self.ref_counts.upgrade() {
let entity_map = entity_map.upgradable_read();
let count = entity_map
.counts
@ -322,7 +314,7 @@ impl Drop for AnyEntity {
}
#[cfg(any(test, feature = "leak-detection"))]
if let Some(entity_map) = self.entity_map.upgrade() {
if let Some(entity_map) = self.ref_counts.upgrade() {
entity_map
.write()
.leak_detector
@ -386,12 +378,16 @@ unsafe impl<T> Sync for Entity<T> {}
impl<T> Sealed for Entity<T> {}
impl<T: 'static> Entity<T> {
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
fn new(
id: EntityId,
entity_data: Rc<RefCell<T>>,
ref_counts: Weak<RwLock<EntityRefCounts>>,
) -> Self
where
T: 'static,
{
Self {
any_entity: AnyEntity::new(id, TypeId::of::<T>(), entity_map),
any_entity: AnyEntity::new(id, TypeId::of::<T>(), entity_data, ref_counts),
entity_type: PhantomData,
}
}
@ -504,6 +500,7 @@ impl<T: 'static> PartialOrd for Entity<T> {
pub struct AnyWeakEntity {
pub(crate) entity_id: EntityId,
entity_type: TypeId,
entity_data: rc::Weak<RefCell<dyn Any>>,
entity_ref_counts: Weak<RwLock<EntityRefCounts>>,
}
@ -538,7 +535,8 @@ impl AnyWeakEntity {
Some(AnyEntity {
entity_id: self.entity_id,
entity_type: self.entity_type,
entity_map: self.entity_ref_counts.clone(),
entity_data: self.entity_data.upgrade()?,
ref_counts: self.entity_ref_counts.clone(),
#[cfg(any(test, feature = "leak-detection"))]
handle_id: self
.entity_ref_counts
@ -592,6 +590,7 @@ impl AnyWeakEntity {
// read in the first place, so we're good!
entity_id: entity_id.into(),
entity_type: TypeId::of::<()>(),
entity_data: Rc::downgrade(&(Rc::new(RefCell::new(())) as Rc<RefCell<dyn Any>>)),
entity_ref_counts: Weak::new(),
}
}
@ -836,10 +835,10 @@ mod test {
// Tests that slots are not re-used before take_dropped.
let mut entity_map = EntityMap::new();
let slot = entity_map.reserve::<TestEntity>();
let slot = entity_map.reserve();
entity_map.insert(slot, TestEntity { i: 1 });
let slot = entity_map.reserve::<TestEntity>();
let slot = entity_map.reserve();
entity_map.insert(slot, TestEntity { i: 2 });
let dropped = entity_map.take_dropped();
@ -848,7 +847,7 @@ mod test {
assert_eq!(
dropped
.into_iter()
.map(|(_, entity)| entity.downcast::<TestEntity>().unwrap().i)
.map(|(_, entity)| entity.borrow().downcast_ref::<TestEntity>().unwrap().i)
.collect::<Vec<i32>>(),
vec![1, 2],
);
@ -859,7 +858,7 @@ mod test {
// Tests that weak handles are not upgraded before take_dropped
let mut entity_map = EntityMap::new();
let slot = entity_map.reserve::<TestEntity>();
let slot = entity_map.reserve();
let handle = entity_map.insert(slot, TestEntity { i: 1 });
let weak = handle.downgrade();
drop(handle);
@ -873,7 +872,7 @@ mod test {
assert_eq!(
dropped
.into_iter()
.map(|(_, entity)| entity.downcast::<TestEntity>().unwrap().i)
.map(|(_, entity)| entity.borrow().downcast_ref::<TestEntity>().unwrap().i)
.collect::<Vec<i32>>(),
vec![1],
);

View file

@ -1,9 +1,9 @@
use crate::{
Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncApp, AvailableSpace,
BackgroundExecutor, BorrowAppContext, Bounds, Capslock, ClipboardItem, DrawPhase, Drawable,
Element, Empty, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Modifiers,
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
Element, Empty, EntityId, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke,
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
Pixels, Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds,
WindowHandle, WindowOptions,
};
@ -40,14 +40,14 @@ impl AppContext for TestAppContext {
app.new(build_entity)
}
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
let mut app = self.app.borrow_mut();
app.reserve_entity()
}
fn insert_entity<T: 'static>(
&mut self,
reservation: crate::Reservation<T>,
reservation: EntityId,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Self::Result<Entity<T>> {
let mut app = self.app.borrow_mut();
@ -891,13 +891,13 @@ impl AppContext for VisualTestContext {
self.cx.new(build_entity)
}
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
self.cx.reserve_entity()
}
fn insert_entity<T: 'static>(
&mut self,
reservation: crate::Reservation<T>,
reservation: EntityId,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Self::Result<Entity<T>> {
self.cx.insert_entity(reservation, build_entity)

View file

@ -175,16 +175,15 @@ pub trait AppContext {
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Self::Result<Entity<T>>;
/// Reserve a slot for a entity to be inserted later.
/// The returned [Reservation] allows you to obtain the [EntityId] for the future entity.
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<Reservation<T>>;
/// Reserve an EntityId for a entity to be inserted later.
fn reserve_entity(&mut self) -> Self::Result<EntityId>;
/// Insert a new entity in the app context based on a [Reservation] previously obtained from [`reserve_entity`].
/// Insert a new entity in the app context based on a [EntityId] previously obtained from [`reserve_entity`].
///
/// [`reserve_entity`]: Self::reserve_entity
fn insert_entity<T: 'static>(
&mut self,
reservation: Reservation<T>,
reservation: EntityId,
build_entity: impl FnOnce(&mut Context<T>) -> T,
) -> Self::Result<Entity<T>>;
@ -231,17 +230,6 @@ pub trait AppContext {
G: Global;
}
/// Returned by [Context::reserve_entity] to later be passed to [Context::insert_entity].
/// Allows you to obtain the [EntityId] for a entity before it is created.
pub struct Reservation<T>(pub(crate) Slot<T>);
impl<T: 'static> Reservation<T> {
/// Returns the [EntityId] that will be associated with the entity once it is inserted.
pub fn entity_id(&self) -> EntityId {
self.0.entity_id()
}
}
/// This trait is used for the different visual contexts in GPUI that
/// require a window to be present.
pub trait VisualContext: AppContext {

View file

@ -30,16 +30,16 @@ pub fn derive_app_context(input: TokenStream) -> TokenStream {
self.#app_variable.new(build_entity)
}
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<gpui::Reservation<T>> {
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
self.#app_variable.reserve_entity()
}
fn insert_entity<T: 'static>(
&mut self,
reservation: gpui::Reservation<T>,
entity_id: EntityId,
build_entity: impl FnOnce(&mut gpui::Context<'_, T>) -> T,
) -> Self::Result<gpui::Entity<T>> {
self.#app_variable.insert_entity(reservation, build_entity)
self.#app_variable.insert_entity(entity_id, build_entity)
}
fn update_entity<T, R>(

View file

@ -1,6 +1,6 @@
#[test]
fn test_derive_context() {
use gpui::{App, Window};
use gpui::{App, EntityId, Window};
use gpui_macros::{AppContext, VisualContext};
#[derive(AppContext, VisualContext)]

View file

@ -967,7 +967,7 @@ impl Buffer {
language_registry: Option<Arc<LanguageRegistry>>,
cx: &mut App,
) -> impl Future<Output = BufferSnapshot> + use<> {
let entity_id = cx.reserve_entity::<Self>().entity_id();
let entity_id = cx.reserve_entity();
let buffer_id = entity_id.as_non_zero_u64().into();
async move {
let text =
@ -992,7 +992,7 @@ impl Buffer {
}
pub fn build_empty_snapshot(cx: &mut App) -> BufferSnapshot {
let entity_id = cx.reserve_entity::<Self>().entity_id();
let entity_id = cx.reserve_entity();
let buffer_id = entity_id.as_non_zero_u64().into();
let text =
TextBuffer::new_normalized(0, buffer_id, Default::default(), Rope::new()).snapshot();
@ -1015,7 +1015,7 @@ impl Buffer {
language_registry: Option<Arc<LanguageRegistry>>,
cx: &mut App,
) -> BufferSnapshot {
let entity_id = cx.reserve_entity::<Self>().entity_id();
let entity_id = cx.reserve_entity();
let buffer_id = entity_id.as_non_zero_u64().into();
let text = TextBuffer::new_normalized(0, buffer_id, Default::default(), text).snapshot();
let mut syntax = SyntaxMap::new(&text).snapshot();