Fold attribute names through monitors and skip coercing name inputs

This commit is contained in:
Dennis Kobert
2026-09-13 17:58:53 +02:00
parent 53608ae7bf
commit f27d90d152
5 changed files with 140 additions and 21 deletions

View File

@@ -136,6 +136,17 @@ impl Preprocessor {
if valid_call_args.len() > 1 {
input_type = &const { generic!(D) };
}
// An attribute name folds to a constant when the graph compiles, so its input keeps the
// document's value in place rather than riding a coercion the fold could not see through.
let name_inputs: HashSet<usize> = implementations
.iter()
.filter_map(|entry| entry.layout_meta.as_ref())
.flat_map(|meta| {
let writes = meta.named_writes.iter().map(|named| named.name_input as usize);
let reads = meta.named_reads.iter().map(|named| named.name_input as usize);
writes.chain(reads)
})
.collect();
let mut inputs: Vec<_> = node_inputs(fields, first_node_io);
let wrapper_input_count = inputs.len() - if *async_source_fields { 2 } else { 0 };
@@ -156,7 +167,7 @@ impl Preprocessor {
(
NodeId(i as u64),
match inputs.len() {
1 => {
1 if !name_inputs.contains(&i) => {
let input = inputs.iter().next().unwrap();
let input_ty = input.nested_type();
let mut inputs = vec![NodeInput::import(input.clone(), i)];
@@ -311,3 +322,30 @@ impl std::fmt::Display for PreprocessorError {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use graph_craft::document::DocumentNodeImplementation;
/// An attribute name folds when the graph compiles, so the preprocessor
/// must leave the name input as the document's constant rather than coerce it.
#[test]
fn an_attribute_name_input_is_not_coerced() {
let preprocessor = Preprocessor::new();
let Some(substitution) = preprocessor.substitutions.get(&graphene_std::graphic::write_attribute::IDENTIFIER) else {
// Nothing to coerce on any input means no wrapper at all, which is also correct
return;
};
let DocumentNodeImplementation::Network(wrapper) = &substitution.implementation else {
panic!("a substitution wraps the node in a network");
};
let name_slot = &wrapper.nodes[&NodeId(1)];
assert_eq!(
name_slot.implementation,
DocumentNodeImplementation::ProtoNode(ops::passthrough::IDENTIFIER),
"the name input passes through untouched, got {:?}",
name_slot.implementation
);
}
}