Make Node::layout non-optional, defaulting to a shared empty layout

This commit is contained in:
Dennis Kobert
2026-08-11 09:04:08 +00:00
parent 5b02edfd9a
commit 5db7e1816a
7 changed files with 49 additions and 37 deletions

View File

@@ -208,7 +208,7 @@ mod tests {
fn lifted_value<T: Clone + Send + Sync + 'static>(value: T) -> (core_types::record::RecordLift<T, ValueNode<T>>, Layout) {
let lift = core_types::record::RecordLift::<T, _>::new(ValueNode(value));
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
(lift, layout)
}
@@ -234,7 +234,7 @@ mod tests {
reserve_for(&[&source_layout, &modified, &stacked]);
let chain = MultiplyOpacityNode::new(MultiplyOpacityNode::new(bare_source(&source_layout, 2.), ValueNode(0.5), &source_layout), ValueNode(0.5), &modified);
assert_eq!(chain.layout(), Some(&stacked));
assert_eq!(chain.layout(), &stacked);
let GPoll::Final(value) = chain.eval(&ctx) else {
panic!("expected a final record");
};
@@ -361,7 +361,7 @@ mod tests {
reserve_for(&[&layout]);
let node = SourceOpacityNode::new(ValueNode(3.), ValueNode(0.25));
assert_eq!(Node::<ContextImpl>::layout(&node), Some(&layout));
assert_eq!(Node::<ContextImpl>::layout(&node), &layout);
let GPoll::Final(value) = node.eval(&ctx) else {
panic!("expected a final record");
};
@@ -490,7 +490,7 @@ mod tests {
let source_layout = f64_layout(&["opacity"]);
let factor = core_types::record::RecordLift::<f64, _>::new(ValueNode(3.));
let factor_layout = Node::<ContextImpl>::layout(&factor).unwrap().clone();
let factor_layout = Node::<ContextImpl>::layout(&factor).clone();
reserve_for(&[&source_layout]);
let node = BoostNode::new(
@@ -499,7 +499,7 @@ mod tests {
&source_layout,
&factor_layout,
);
let out_layout = Node::<ContextImpl>::layout(&node).unwrap().clone();
let out_layout = Node::<ContextImpl>::layout(&node).clone();
let opacity_offset = out_layout.offset_of(Opacity::NAME, 0).expect("the primary input's fields pass through to the output");
let GPoll::Final(value) = node.eval(&ctx) else {
panic!("expected a final record");
@@ -526,7 +526,7 @@ mod tests {
&source_layout,
&factor_layout,
);
let out_layout = Node::<ContextImpl>::layout(&node).unwrap().clone();
let out_layout = Node::<ContextImpl>::layout(&node).clone();
let opacity_offset = out_layout.offset_of(Opacity::NAME, 0).expect("the primary input's fields pass through the poll kernel");
let GPoll::Final(value) = node.eval(&ctx) else {
panic!("expected a final record");
@@ -554,7 +554,7 @@ mod tests {
&carrier_layout,
&by_layout,
);
let out_layout = Node::<ContextImpl>::layout(&node).unwrap().clone();
let out_layout = Node::<ContextImpl>::layout(&node).clone();
let GPoll::Final(value) = node.eval(&ctx) else {
panic!("expected a final record");
};
@@ -593,7 +593,7 @@ mod tests {
&runtime_layout,
&source_id_layout,
);
let out_layout = Node::<ContextImpl>::layout(&node).unwrap().clone();
let out_layout = Node::<ContextImpl>::layout(&node).clone();
let opacity_offset = out_layout.offset_of(Opacity::NAME, 0).expect("the carrier's fields pass through the async source");
let GPoll::Final(value) = node.eval(&ctx) else {
@@ -619,14 +619,14 @@ mod tests {
let ctx = ContextImpl::root(&scope);
let unit = core_types::record::RecordLift::<(), _>::new(ValueNode(()));
let unit_layout = Node::<ContextImpl>::layout(&unit).unwrap().clone();
let unit_layout = Node::<ContextImpl>::layout(&unit).clone();
let content_layout = f64_layout(&["opacity"]);
reserve_for(&[&content_layout]);
let run = |opacity: Option<f64>| {
let evals = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
let alternate = core_types::record::RecordLift::<f64, _>::new(CountingValue(evals.clone()));
let alternate_layout = Node::<ContextImpl>::layout(&alternate).unwrap().clone();
let alternate_layout = Node::<ContextImpl>::layout(&alternate).clone();
let (content_layout, fields) = match opacity {
Some(value) => (content_layout.clone(), vec![(content_layout.offset_of("opacity", 0).unwrap(), value)]),
None => (f64_layout(&[]), vec![]),
@@ -642,7 +642,7 @@ mod tests {
let GPoll::Final(value) = node.eval(&ctx) else {
panic!("expected a final record");
};
let element = unsafe { Node::<ContextImpl>::layout(&node).unwrap().rec(&value).element::<f64>() };
let element = unsafe { Node::<ContextImpl>::layout(&node).rec(&value).element::<f64>() };
(element, evals.load(std::sync::atomic::Ordering::Relaxed))
};
@@ -892,7 +892,7 @@ mod tests {
let probed = |features: ContextFeatures| {
let (modification, modification_layout) = lifted_value(ContextModification::from_sources(features, &[]));
let node = crate::context_modification::ContextModificationNode::new(RealTimeProbe { layout: layout.clone() }, modification, &layout, &modification_layout);
assert_eq!(Node::<ContextImpl>::layout(&node), Some(&layout));
assert_eq!(Node::<ContextImpl>::layout(&node), &layout);
let GPoll::Final(value) = node.eval(&ctx) else {
panic!("expected a final record");
};
@@ -944,7 +944,7 @@ mod tests {
let ctx = ContextImpl::root(&scope);
let lift = core_types::record::RecordLift::<String, _>::new(ValueNode(String::from("parked")));
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
let chain = core_types::record::RecordExtract::<String, _>::new(lift, &layout);
let GPoll::Final(text) = chain.eval(&ctx) else {
@@ -1029,7 +1029,7 @@ mod tests {
let evals = std::sync::Arc::new(std::sync::atomic::AtomicU32::new(0));
let lift = core_types::record::RecordLift::<f64, _>::new(CountingValue(evals.clone()));
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
let memo = crate::memo::MemoizeNode::new(lift, &layout);
let GPoll::Final(value) = memo.eval(&ctx) else {

View File

@@ -269,7 +269,7 @@ mod test {
let x_translations = |values: [f64; 3]| values.map(|x| DVec2::new(x, 0.)).to_vec();
let lift = RecordLift::<List<Vector>, _>::new(IndexProbe);
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
let forward = super::repeat(&ctx, ElementLazyInput::new(&lift, &cell, 0, &layout), 3, false).unwrap();
assert_eq!(row_translations(&forward, ATTR_TRANSFORM), x_translations([0., 1., 2.]));
@@ -285,7 +285,7 @@ mod test {
let count = 3;
let lift = RecordLift::<List<Vector>, _>::new(ValueNode(single_default_vector()));
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
let repeated = super::repeat_array(&ctx, ElementLazyInput::new(&lift, &cell, 0, &layout), direction, 0., count).unwrap();
assert_eq!(repeated.len(), count as usize);
@@ -300,7 +300,7 @@ mod test {
test_ctx!(ctx, cell);
let lift = RecordLift::<List<Vector>, _>::new(ValueNode(single_default_vector()));
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
let repeated = super::repeat_array(&ctx, ElementLazyInput::<List<Vector>, _>::new(&lift, &cell, 0, &layout), DVec2::new(12., 10.), 45., 1).unwrap();
assert_eq!(repeated.len(), 1);
@@ -314,7 +314,7 @@ mod test {
let (radius, count) = (5., 4);
let lift = RecordLift::<List<Vector>, _>::new(ValueNode(single_default_vector()));
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
let repeated = super::repeat_radial(&ctx, ElementLazyInput::<List<Vector>, _>::new(&lift, &cell, 0, &layout), 0., radius, count).unwrap();
assert_eq!(repeated.len(), count as usize);
@@ -332,7 +332,7 @@ mod test {
let points = List::new_from_element(Vector::from_subpath(Subpath::from_anchors(positions, false)));
let lift = RecordLift::<List<Vector>, _>::new(PositionProbe);
let layout = Node::<ContextImpl>::layout(&lift).unwrap().clone();
let layout = Node::<ContextImpl>::layout(&lift).clone();
let generated = super::repeat_on_points(&ctx, points.clone(), ElementLazyInput::new(&lift, &cell, 0, &layout), false).unwrap();
assert_eq!(row_translations(&generated, ATTR_TRANSFORM), positions.to_vec());