gpui: Introduce stacker to address stack overflows with deep layout trees (#35813)
Co-authored-by: Anthony Eid <hello@anthonyeid.me> Co-authored-by: Lukas Wirth <lukas@zed.dev> Co-authored-by: Ben Kunkle <ben@zed.dev> Release Notes: - N/A Co-authored-by: Anthony Eid <hello@anthonyeid.me> Co-authored-by: Lukas Wirth <lukas@zed.dev> Co-authored-by: Ben Kunkle <ben@zed.dev>
This commit is contained in:
parent
1fbb318714
commit
ed14ab8c02
5 changed files with 56 additions and 5 deletions
35
Cargo.lock
generated
35
Cargo.lock
generated
|
@ -7482,6 +7482,7 @@ dependencies = [
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"smol",
|
"smol",
|
||||||
|
"stacksafe",
|
||||||
"strum 0.27.1",
|
"strum 0.27.1",
|
||||||
"sum_tree",
|
"sum_tree",
|
||||||
"taffy",
|
"taffy",
|
||||||
|
@ -15541,6 +15542,40 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stacker"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"psm",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stacksafe"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d9c1172965d317e87ddb6d364a040d958b40a1db82b6ef97da26253a8b3d090"
|
||||||
|
dependencies = [
|
||||||
|
"stacker",
|
||||||
|
"stacksafe-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stacksafe-macro"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "172175341049678163e979d9107ca3508046d4d2a7c6682bee46ac541b17db69"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.101",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
|
@ -590,6 +590,7 @@ simplelog = "0.12.2"
|
||||||
smallvec = { version = "1.6", features = ["union"] }
|
smallvec = { version = "1.6", features = ["union"] }
|
||||||
smol = "2.0"
|
smol = "2.0"
|
||||||
sqlformat = "0.2"
|
sqlformat = "0.2"
|
||||||
|
stacksafe = "0.1"
|
||||||
streaming-iterator = "0.1"
|
streaming-iterator = "0.1"
|
||||||
strsim = "0.11"
|
strsim = "0.11"
|
||||||
strum = { version = "0.27.0", features = ["derive"] }
|
strum = { version = "0.27.0", features = ["derive"] }
|
||||||
|
|
|
@ -119,6 +119,7 @@ serde_json.workspace = true
|
||||||
slotmap = "1.0.6"
|
slotmap = "1.0.6"
|
||||||
smallvec.workspace = true
|
smallvec.workspace = true
|
||||||
smol.workspace = true
|
smol.workspace = true
|
||||||
|
stacksafe.workspace = true
|
||||||
strum.workspace = true
|
strum.workspace = true
|
||||||
sum_tree.workspace = true
|
sum_tree.workspace = true
|
||||||
taffy = "=0.9.0"
|
taffy = "=0.9.0"
|
||||||
|
|
|
@ -27,6 +27,7 @@ use crate::{
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use refineable::Refineable;
|
use refineable::Refineable;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use stacksafe::{StackSafe, stacksafe};
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
@ -1195,7 +1196,7 @@ pub fn div() -> Div {
|
||||||
/// A [`Div`] element, the all-in-one element for building complex UIs in GPUI
|
/// A [`Div`] element, the all-in-one element for building complex UIs in GPUI
|
||||||
pub struct Div {
|
pub struct Div {
|
||||||
interactivity: Interactivity,
|
interactivity: Interactivity,
|
||||||
children: SmallVec<[AnyElement; 2]>,
|
children: SmallVec<[StackSafe<AnyElement>; 2]>,
|
||||||
prepaint_listener: Option<Box<dyn Fn(Vec<Bounds<Pixels>>, &mut Window, &mut App) + 'static>>,
|
prepaint_listener: Option<Box<dyn Fn(Vec<Bounds<Pixels>>, &mut Window, &mut App) + 'static>>,
|
||||||
image_cache: Option<Box<dyn ImageCacheProvider>>,
|
image_cache: Option<Box<dyn ImageCacheProvider>>,
|
||||||
}
|
}
|
||||||
|
@ -1256,7 +1257,8 @@ impl InteractiveElement for Div {
|
||||||
|
|
||||||
impl ParentElement for Div {
|
impl ParentElement for Div {
|
||||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
||||||
self.children.extend(elements)
|
self.children
|
||||||
|
.extend(elements.into_iter().map(StackSafe::new))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1272,6 +1274,7 @@ impl Element for Div {
|
||||||
self.interactivity.source_location()
|
self.interactivity.source_location()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stacksafe]
|
||||||
fn request_layout(
|
fn request_layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
global_id: Option<&GlobalElementId>,
|
global_id: Option<&GlobalElementId>,
|
||||||
|
@ -1307,6 +1310,7 @@ impl Element for Div {
|
||||||
(layout_id, DivFrameState { child_layout_ids })
|
(layout_id, DivFrameState { child_layout_ids })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stacksafe]
|
||||||
fn prepaint(
|
fn prepaint(
|
||||||
&mut self,
|
&mut self,
|
||||||
global_id: Option<&GlobalElementId>,
|
global_id: Option<&GlobalElementId>,
|
||||||
|
@ -1376,6 +1380,7 @@ impl Element for Div {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stacksafe]
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
&mut self,
|
||||||
global_id: Option<&GlobalElementId>,
|
global_id: Option<&GlobalElementId>,
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use collections::{FxHashMap, FxHashSet};
|
use collections::{FxHashMap, FxHashSet};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use stacksafe::{StackSafe, stacksafe};
|
||||||
use std::{fmt::Debug, ops::Range};
|
use std::{fmt::Debug, ops::Range};
|
||||||
use taffy::{
|
use taffy::{
|
||||||
TaffyTree, TraversePartialTree as _,
|
TaffyTree, TraversePartialTree as _,
|
||||||
|
@ -11,8 +12,15 @@ use taffy::{
|
||||||
tree::NodeId,
|
tree::NodeId,
|
||||||
};
|
};
|
||||||
|
|
||||||
type NodeMeasureFn = Box<
|
type NodeMeasureFn = StackSafe<
|
||||||
dyn FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>,
|
Box<
|
||||||
|
dyn FnMut(
|
||||||
|
Size<Option<Pixels>>,
|
||||||
|
Size<AvailableSpace>,
|
||||||
|
&mut Window,
|
||||||
|
&mut App,
|
||||||
|
) -> Size<Pixels>,
|
||||||
|
>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
struct NodeContext {
|
struct NodeContext {
|
||||||
|
@ -88,7 +96,7 @@ impl TaffyLayoutEngine {
|
||||||
.new_leaf_with_context(
|
.new_leaf_with_context(
|
||||||
taffy_style,
|
taffy_style,
|
||||||
NodeContext {
|
NodeContext {
|
||||||
measure: Box::new(measure),
|
measure: StackSafe::new(Box::new(measure)),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect(EXPECT_MESSAGE)
|
.expect(EXPECT_MESSAGE)
|
||||||
|
@ -143,6 +151,7 @@ impl TaffyLayoutEngine {
|
||||||
Ok(edges)
|
Ok(edges)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stacksafe]
|
||||||
pub fn compute_layout(
|
pub fn compute_layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: LayoutId,
|
id: LayoutId,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue