From 2157ce700c6dd55ada8fcd7d8056e0226d256aec Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Mon, 14 Sep 2026 13:45:06 +0200 Subject: [PATCH] Measure a node's level delta from its deepest layout source --- node-graph/node-macro/src/codegen/ir.rs | 49 ++++++++++++++++++++----- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/node-graph/node-macro/src/codegen/ir.rs b/node-graph/node-macro/src/codegen/ir.rs index eaa58f8627..342f2392d5 100644 --- a/node-graph/node-macro/src/codegen/ir.rs +++ b/node-graph/node-macro/src/codegen/ir.rs @@ -326,6 +326,14 @@ pub(crate) fn gathered_subject(node: &Node) -> Option { if !node.output.gathers { return None; } + materialized_subject(node) +} + +/// The subject a gather copies frames from or a fold consumes, if any. At most one +/// exists: materializing takes an eager subject of non-zero depth, and [`subject`] +/// admits an eager one only at index 0 or as a routing source, whose bare-ident +/// match rules out any `IList` nesting. +pub(crate) fn materialized_subject(node: &Node) -> Option { node.inputs .iter() .enumerate() @@ -357,11 +365,7 @@ pub(crate) fn folded_subject(node: &Node) -> Option<(u8, u8)> { if node.output.gathers { return None; } - node.inputs - .iter() - .enumerate() - .find(|(index, input)| input.subject && materialized_levels(node, *index) > 0) - .map(|(index, _)| (index as u8, materialized_levels(node, index))) + materialized_subject(node).map(|index| (index as u8, materialized_levels(node, index))) } fn field_writes(attrs: &[LevelAttr], core_types: &TokenStream2) -> Vec { @@ -474,8 +478,9 @@ pub(crate) fn name_input(node: &Node, placeholder: &Type) -> Option { fn level_delta(node: &Node) -> i8 { // A folded subject contributes no base layout, so the delta is relative to - // the fresh (empty) base. - let base_depth = layout_sources(node).first().map_or(0, |&index| node.inputs[index].shape.depth as i8); + // the fresh (empty) base. Several sources union into that base, and the union + // lifts the shallower ones, so the deepest is what the delta measures from. + let base_depth = layout_sources(node).iter().map(|&index| node.inputs[index].shape.depth as i8).max().unwrap_or(0); node.output.shape.depth as i8 - base_depth } @@ -718,13 +723,12 @@ mod tests { Element::Generic(_) => node.monomorphizations.is_empty(), Element::Concrete(_) => false, }; - let subject_depth = node.inputs.iter().find(|input| input.subject).map_or(0, |input| input.shape.depth as i8); Facts { sources: layout_sources(node), carried, writes: markers(node.output.shape.attrs.iter().map(|attr| &attr.marker)), removes: markers(node.output.removes.iter().map(|attr| &attr.marker)), - delta: node.output.shape.depth as i8 - subject_depth, + delta: level_delta(node), } } @@ -1358,6 +1362,33 @@ mod tests { assert_eq!(node.output.shape.depth as i8 - subject.shape.depth as i8, -1, "the reducer collapses one level"); } + #[test] + fn the_deepest_layout_source_is_the_delta_base() { + let mut parsed = parse_node_fn( + quote!(category("")), + quote!( + fn pick(ctx: impl Ctx + Copy, condition: bool, scalar: impl Node, Output = T>, listed: impl Node, Output = IList>) -> Result, Interrupt> { + if condition { listed.eval(ctx) } else { emit(scalar.eval(ctx)?) } + } + ), + ) + .unwrap(); + parsed.replace_impl_trait_in_input(); + let node = build(&parsed); + + // Both branches are lazy, so neither materializes and both source the + // output's layout, at depths 0 and 1. + let sources = layout_sources(&node); + let depths: Vec = sources.iter().map(|&index| node.inputs[index].shape.depth).collect(); + assert_eq!(depths, vec![0, 1], "the two branches source the layout at differing depths"); + + // The union lifts the scalar side to the listed side's depth, so the + // output sits at the base rather than one level above it. Measuring from + // the first source instead would read a spurious +1 push. + assert_eq!(node.output.shape.depth, 1); + assert_eq!(level_delta(&node), 0, "the delta measures from the deepest source, not the first"); + } + #[test] fn monomorphizations_key_by_generic() { let node = assert_bridge(