Query per-copy extents with the same chain shape the value path builds

This commit is contained in:
Dennis Kobert
2026-08-25 16:36:49 +00:00
parent db761cf8ed
commit 5176bfd331
4 changed files with 48 additions and 18 deletions

View File

@@ -561,7 +561,7 @@ impl ProtoNetwork {
let branch = self.find_context_dependencies(node);
let mut lifted = branch.0.clone();
lifted.index_levels = lifted.index_levels.popped(pushed_levels.get(input).copied().unwrap_or(0));
lifted.index_levels = lifted.index_levels.lifted(0, pushed_levels.get(input).copied().unwrap_or(0));
combined_deps |= &lifted;
branch_dependencies.push(branch);
}

View File

@@ -244,19 +244,24 @@ impl IndexLevels {
self.0 == u32::MAX
}
/// The same requirement seen from outside `levels` pushed levels. An
/// all-levels mask stays saturated, since its reader's level is not known at
/// compile time.
///
/// TODO: a fold overwrites the level it consumes rather than pushing one, so
/// this shift misnumbers levels above 0 across fold edges; latent until a
/// numeric level above 0 is declared. Preferred fix: folds push a level,
/// once the pass cancels the level a fold supplies.
pub const fn popped(self, levels: u8) -> Self {
/// The same requirement seen from outside an edge whose innermost `supplied`
/// levels the reading node drives itself, and whose chain sits `delta`
/// deeper than that node's. A supplied level leaves no requirement behind;
/// the rest renumber by the depth difference. An all-levels mask stays
/// saturated, since its reader's level is not known at compile time.
pub const fn lifted(self, supplied: u8, delta: u8) -> Self {
match self.0 {
u32::MAX => self,
_ if levels as u32 >= u32::BITS => Self(0),
mask => Self(mask >> levels),
mask => {
let kept = match supplied as u32 >= u32::BITS {
true => 0,
false => mask & !((1 << supplied) - 1),
};
match delta as u32 >= u32::BITS {
true => Self(0),
false => Self(kept >> delta),
}
}
}
}
@@ -1518,6 +1523,29 @@ mod context_impl_tests {
core::iter::successors(Some(head), |link| link.outer).map(|link| link.index).collect()
}
#[test]
fn lifting_a_fold_edge_clears_the_driven_level_in_place() {
let reads = IndexLevels::innermost().with_level(2);
assert_eq!(reads.lifted(1, 0), IndexLevels::empty().with_level(2));
}
#[test]
fn lifting_a_pushed_edge_renumbers_outwards() {
let reads = IndexLevels::innermost().with_level(2);
assert_eq!(reads.lifted(1, 1), IndexLevels::empty().with_level(1));
}
#[test]
fn lifting_a_decomposed_edge_drops_both_driven_levels() {
let reads = IndexLevels::innermost().with_level(1).with_level(3);
assert_eq!(reads.lifted(2, 1), IndexLevels::empty().with_level(2));
}
#[test]
fn lifting_leaves_a_saturated_mask_alone() {
assert_eq!(IndexLevels::all().lifted(2, 1), IndexLevels::all());
}
#[test]
fn nullify_drops_trailing_zeroed_levels() {
let arena = Arena::new(256).unwrap();

View File

@@ -901,8 +901,8 @@ where
B: crate::context::DeriveCtx,
N: for<'d> DerivedRecordEdge<'d, crate::context::Derived<'d, B>>,
{
let head = ctx.index_head();
let derived = ctx.promoted(&head, copy);
let mut frame = crate::context::IndexLink { index: 0, outer: None };
let derived = ctx.push_level(&mut frame, copy, 0);
let mut inner: u64 = 1;
for level in 0..levels {
match node.extent_at_derived(&derived, level) {

View File

@@ -1461,8 +1461,9 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
ParsedFieldType::Node(_) => match ir::lazy_binding(&node, index) {
ir::LazyBinding::DeriveRouting | ir::LazyBinding::DeriveCarrier => quote! {
let #query = |__copy: u64, __lvl: u8| {
let __head = #core_types::context::DeriveCtx::index_head(__input);
#core_types::record::DerivedRecordEdge::extent_at_derived(&self.#name, &#core_types::context::DeriveCtx::promoted(__input, &__head, __copy), __lvl)
let mut __frame = #core_types::context::IndexLink { index: 0, outer: None };
let __derived = #core_types::context::DeriveCtx::push_level(__input, &mut __frame, __copy, 0);
#core_types::record::DerivedRecordEdge::extent_at_derived(&self.#name, &__derived, __lvl)
};
let #arg = #core_types::extent::ExtentIn::new(&#query);
},
@@ -1541,9 +1542,10 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let query = match &field.ty {
ParsedFieldType::Node(_) => match ir::lazy_binding(&node, subject_index) {
ir::LazyBinding::DeriveRouting | ir::LazyBinding::DeriveCarrier => quote! {
let __query = |__copy: u64, __lvl: u8| {
let __query = |_: u64, __lvl: u8| {
let __head = #core_types::context::DeriveCtx::index_head(__input);
#core_types::record::DerivedRecordEdge::extent_at_derived(&self.#name, &#core_types::context::DeriveCtx::promoted(__input, &__head, __copy), __lvl)
let __derived = #core_types::context::DeriveCtx::replaced(__input, __head.index);
#core_types::record::DerivedRecordEdge::extent_at_derived(&self.#name, &__derived, __lvl)
};
},
_ => quote! {