gpui: Make entities no longer implement Element (they go through AnyElement now) (#48217)

This reduces e.g. agent_ui's LLVM lines from 1.95m to 1.7m ( -> 56009 ->
50899).
git_ui: 1.02 -> 0.917m (30700 functions -> 27496)


Overall, anything that implements `Render` should benefit. OTOH `editor`
does not, because it has a custom `Element` impl.
Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2026-02-03 12:00:22 +01:00 committed by GitHub
parent 92ad7c3000
commit f565fb8750
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 40 additions and 74 deletions

View file

@ -30563,7 +30563,7 @@ fn test_editor_rendering_when_positioned_above_viewport(cx: &mut TestAppContext)
cx.draw(
gpui::point(px(0.), px(-10000.)),
gpui::size(px(500.), px(3000.)),
|_, _| editor.clone(),
|_, _| editor.clone().into_any_element(),
);
// If we get here without hanging, the test passes

View file

@ -19,7 +19,7 @@ use gpui::{
use multi_buffer::{MultiBufferOffset, ToPoint};
use pretty_assertions::assert_eq;
use project::{Project, project_settings::DiagnosticSeverity};
use ui::{App, BorrowAppContext, px};
use ui::{App, BorrowAppContext, IntoElement, px};
use util::test::{generate_marked_text, marked_text_offsets, marked_text_ranges};
#[cfg(test)]
@ -193,7 +193,9 @@ pub fn editor_content_with_blocks_and_size(
cx: &mut VisualTestContext,
) -> String {
cx.simulate_resize(draw_size);
cx.draw(gpui::Point::default(), draw_size, |_, _| editor.clone());
cx.draw(gpui::Point::default(), draw_size, |_, _| {
editor.clone().into_any_element()
});
let (snapshot, mut lines, blocks) = editor.update_in(cx, |editor, window, cx| {
let snapshot = editor.snapshot(window, cx);
let text = editor.display_text(cx);

View file

@ -33,8 +33,8 @@
use crate::{
App, ArenaBox, AvailableSpace, Bounds, Context, DispatchNodeId, ElementId, FocusHandle,
InspectorElementId, LayoutId, Pixels, Point, Size, Style, Window, util::FluentBuilder,
window::with_element_arena,
InspectorElementId, LayoutId, Pixels, Point, SharedString, Size, Style, Window,
util::FluentBuilder, window::with_element_arena,
};
use derive_more::{Deref, DerefMut};
use std::{
@ -197,8 +197,27 @@ impl<C: RenderOnce> Component<C> {
}
}
fn prepaint_component(
(element, name): &mut (AnyElement, &'static str),
window: &mut Window,
cx: &mut App,
) {
window.with_id(ElementId::Name(SharedString::new_static(name)), |window| {
element.prepaint(window, cx);
})
}
fn paint_component(
(element, name): &mut (AnyElement, &'static str),
window: &mut Window,
cx: &mut App,
) {
window.with_id(ElementId::Name(SharedString::new_static(name)), |window| {
element.paint(window, cx);
})
}
impl<C: RenderOnce> Element for Component<C> {
type RequestLayoutState = AnyElement;
type RequestLayoutState = (AnyElement, &'static str);
type PrepaintState = ();
fn id(&self) -> Option<ElementId> {
@ -229,7 +248,7 @@ impl<C: RenderOnce> Element for Component<C> {
.into_any_element();
let layout_id = element.request_layout(window, cx);
(layout_id, element)
(layout_id, (element, type_name::<C>()))
})
}
@ -238,13 +257,11 @@ impl<C: RenderOnce> Element for Component<C> {
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_: Bounds<Pixels>,
element: &mut AnyElement,
state: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App,
) {
window.with_id(ElementId::Name(type_name::<C>().into()), |window| {
element.prepaint(window, cx);
})
prepaint_component(state, window, cx);
}
fn paint(
@ -252,14 +269,12 @@ impl<C: RenderOnce> Element for Component<C> {
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_: Bounds<Pixels>,
element: &mut Self::RequestLayoutState,
state: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App,
) {
window.with_id(ElementId::Name(type_name::<C>().into()), |window| {
element.paint(window, cx);
})
paint_component(state, window, cx);
}
}

View file

@ -1285,7 +1285,7 @@ mod test {
// Paint
cx.draw(point(px(0.), px(0.)), size(px(100.), px(20.)), |_, cx| {
cx.new(|_| TestView(state.clone()))
cx.new(|_| TestView(state.clone())).into_any_element()
});
// Reset
@ -1322,7 +1322,7 @@ mod test {
// Paint
cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, cx| {
cx.new(|_| TestView(state.clone()))
cx.new(|_| TestView(state.clone())).into_any_element()
});
// Test positive distance: start at item 1, move down 30px
@ -1391,7 +1391,7 @@ mod test {
});
cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| {
view.clone()
view.clone().into_any_element()
});
let offset = state.logical_scroll_top();
@ -1405,7 +1405,9 @@ mod test {
item_height.set(50);
state.remeasure();
cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| view);
cx.draw(point(px(0.), px(0.)), size(px(100.), px(200.)), |_, _| {
view.into_any_element()
});
let offset = state.logical_scroll_top();
assert_eq!(offset.item_ix, 2);

View file

@ -25,59 +25,6 @@ struct ViewCacheKey {
text_style: TextStyle,
}
impl<V: Render> Element for Entity<V> {
type RequestLayoutState = AnyElement;
type PrepaintState = ();
fn id(&self) -> Option<ElementId> {
Some(ElementId::View(self.entity_id()))
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
fn request_layout(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
window: &mut Window,
cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut element = self.update(cx, |view, cx| view.render(window, cx).into_any_element());
let layout_id = window.with_rendered_view(self.entity_id(), |window| {
element.request_layout(window, cx)
});
(layout_id, element)
}
fn prepaint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_: Bounds<Pixels>,
element: &mut Self::RequestLayoutState,
window: &mut Window,
cx: &mut App,
) {
window.set_view_id(self.entity_id());
window.with_rendered_view(self.entity_id(), |window| element.prepaint(window, cx));
}
fn paint(
&mut self,
_id: Option<&GlobalElementId>,
_inspector_id: Option<&InspectorElementId>,
_: Bounds<Pixels>,
element: &mut Self::RequestLayoutState,
_: &mut Self::PrepaintState,
window: &mut Window,
cx: &mut App,
) {
window.with_rendered_view(self.entity_id(), |window| element.paint(window, cx));
}
}
/// A dynamically-typed handle to a view, which can be downcast to a [Entity] for a specific type.
#[derive(Clone, Debug)]
pub struct AnyView {
@ -294,10 +241,10 @@ impl Element for AnyView {
}
impl<V: 'static + Render> IntoElement for Entity<V> {
type Element = Entity<V>;
type Element = AnyView;
fn into_element(self) -> Self::Element {
self
self.into()
}
}