Wire record-io plain values as record edges in the registry, extracted at construction

This commit is contained in:
Dennis Kobert
2026-08-16 17:47:25 +00:00
parent e423dd96de
commit 3df028cb18
2 changed files with 16 additions and 5 deletions

View File

@@ -1345,9 +1345,10 @@ where
}
}
/// Law-test scaffolding: a plain probe over a record wire, cloning the
/// element out of the parked reference when it carries drop glue. No
/// production path constructs one.
/// A plain probe over a record wire, cloning the element out of the parked
/// reference when it carries drop glue. Registry constructors wrap a record
/// edge in one to feed a node's plain value input, keeping the wire kind
/// uniform.
pub struct RecordExtract<El, N> {
edge: N,
layout: Layout,

View File

@@ -186,6 +186,8 @@ enum SlotKind {
BaseConcrete(Type),
/// A concrete record edge read for its layout only.
Value(Type),
/// A record edge whose element extracts to the node's plain value input.
Extracted(Type),
/// A plain value edge.
Plain(Type),
/// A lazy node edge.
@@ -226,6 +228,9 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
ParsedFieldType::Node(NodeParsedField { output_type, .. }) => SlotKind::Lazy(output_type.clone()),
ParsedFieldType::Regular(RegularParsedField { ty, .. }) => match ir::value_binding(&node, index) {
ir::ValueBinding::ReadingSecondary | ir::ValueBinding::RecordElement => SlotKind::Value(ty.clone()),
// One wire kind: a record node's plain value still rides a
// record edge, extracted to its element at construction.
_ if matches!(ir::node_kind(&node), ir::NodeKind::RecordIo) => SlotKind::Extracted(ty.clone()),
_ => SlotKind::Plain(ty.clone()),
},
}
@@ -235,7 +240,7 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
// Every non-base value/plain/lazy input must be concrete.
let values_concrete = regular_fields.iter().zip(&slots).all(|(field, slot)| match slot {
SlotKind::BaseGeneric(_) | SlotKind::BaseConcrete(_) => true,
SlotKind::Value(ty) | SlotKind::Plain(ty) | SlotKind::Lazy(ty) => !contains_open_generic(parsed, ty) && (lend(field) || !type_disqualifies(ty)),
SlotKind::Value(ty) | SlotKind::Extracted(ty) | SlotKind::Plain(ty) | SlotKind::Lazy(ty) => !contains_open_generic(parsed, ty) && (lend(field) || !type_disqualifies(ty)),
});
if !values_concrete {
return quote!();
@@ -247,7 +252,7 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
let input_types = slots.iter().map(|slot| match slot {
SlotKind::BaseGeneric(name) => quote!(gcore::registry::generic_record_edge_type(#name)),
SlotKind::BaseConcrete(ty) | SlotKind::Value(ty) => quote!(gcore::registry::record_edge_type::<#ty>()),
SlotKind::BaseConcrete(ty) | SlotKind::Value(ty) | SlotKind::Extracted(ty) => quote!(gcore::registry::record_edge_type::<#ty>()),
SlotKind::Plain(ty) | SlotKind::Lazy(ty) => quote!(gcore::registry::edge_type::<#ty>()),
});
@@ -267,6 +272,11 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
let #layout = #handle.layout().clone();
let #name = #handle.downcast_record::<#value_ty>()?;
},
SlotKind::Extracted(value_ty) => quote! {
let #handle = inputs.next().unwrap();
let #layout = #handle.layout().clone();
let #name = gcore::record::RecordExtract::<#value_ty, _>::new(#handle.downcast_record::<#value_ty>()?, &#layout);
},
SlotKind::Plain(value_ty) | SlotKind::Lazy(value_ty) => quote!(let #name = inputs.next().unwrap().downcast::<#value_ty>()?;),
}
});