Skip to content

Commit 568831b

Browse files
authored
Fix regression breaking Into/Convert node type coercion (#3681)
1 parent ede34b1 commit 568831b

5 files changed

Lines changed: 55 additions & 58 deletions

File tree

editor/src/messages/portfolio/document/utility_types/network_interface.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ impl NodeNetworkInterface {
648648

649649
let export_name = if !export_name.is_empty() {
650650
export_name
651-
} else if let Some(export_type_name) = input_type.compiled_nested_type().map(|nested| nested.to_string()) {
651+
} else if let Some(export_type_name) = input_type.compiled_nested_type().map(ToString::to_string) {
652652
export_type_name
653653
} else {
654654
format!("Export #{}", export_index)
@@ -658,12 +658,19 @@ impl NodeNetworkInterface {
658658
}
659659
};
660660

661+
let valid_types = self.potential_valid_input_types(input_connector, network_path).iter().map(ToString::to_string).collect::<Vec<_>>();
662+
let valid_types = {
663+
// Dedupe while preserving order
664+
let mut found = HashSet::new();
665+
valid_types.into_iter().filter(|s| found.insert(s.clone())).collect::<Vec<_>>()
666+
};
667+
661668
Some(FrontendGraphInput {
662669
data_type,
663670
resolved_type,
664671
name,
665672
description,
666-
valid_types: self.potential_valid_input_types(input_connector, network_path).iter().map(|ty| ty.to_string()).collect(),
673+
valid_types,
667674
connected_to,
668675
})
669676
}
@@ -698,7 +705,7 @@ impl NodeNetworkInterface {
698705

699706
let import_name = if !import_name.is_empty() {
700707
import_name
701-
} else if let Some(import_type_name) = output_type.compiled_nested_type().map(|nested| nested.to_string()) {
708+
} else if let Some(import_type_name) = output_type.compiled_nested_type().map(ToString::to_string) {
702709
import_type_name
703710
} else {
704711
format!("Import #{}", import_index)

editor/src/messages/portfolio/document/utility_types/network_interface/resolved_types.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ impl TypeSource {
9191
/// The type to display in the tooltip label.
9292
pub fn resolved_type_tooltip_string(&self) -> String {
9393
match self {
94-
TypeSource::Compiled(compiled_type) => format!("Data Type: {:?}", compiled_type.nested_type().to_string()),
95-
TypeSource::TaggedValue(value_type) => format!("Data Type: {:?}", value_type.nested_type().to_string()),
94+
TypeSource::Compiled(compiled_type) => format!("Data Type: {}", compiled_type.nested_type()),
95+
TypeSource::TaggedValue(value_type) => format!("Data Type: {}", value_type.nested_type()),
9696
TypeSource::Unknown => "Unknown Data Type".to_string(),
9797
TypeSource::Invalid => "Invalid Type Combination".to_string(),
9898
TypeSource::Error(_) => "Error Getting Data Type".to_string(),
@@ -180,7 +180,7 @@ impl NodeNetworkInterface {
180180
self.input_type_not_invalid(input_connector, network_path)
181181
}
182182

183-
// Gets the default tagged value for an input. If its not compiled, then it tries to get a valid type. If there are no valid types, then it picks a random implementation
183+
/// Gets the default tagged value for an input. If its not compiled, then it tries to get a valid type. If there are no valid types, then it picks a random implementation.
184184
pub fn tagged_value_from_input(&mut self, input_connector: &InputConnector, network_path: &[NodeId]) -> TaggedValue {
185185
let guaranteed_type = match self.input_type(input_connector, network_path) {
186186
TypeSource::Compiled(compiled) => compiled,
@@ -190,12 +190,12 @@ impl NodeNetworkInterface {
190190
// TODO: Add a NodeInput::Indeterminate which can be resolved at compile time to be any type that prevents an error. This may require bidirectional typing.
191191
self.complete_valid_input_types(input_connector, network_path)
192192
.into_iter()
193-
.min_by_key(|ty| ty.nested_type().to_string())
193+
.min_by_key(|ty| ty.nested_type().identifier_name())
194194
// Pick a random type from the potential valid types
195195
.or_else(|| {
196196
self.potential_valid_input_types(input_connector, network_path)
197197
.into_iter()
198-
.min_by_key(|ty| ty.nested_type().to_string())
198+
.min_by_key(|ty| ty.nested_type().identifier_name())
199199
}).unwrap_or(concrete!(()))
200200
}
201201
TypeSource::Error(e) => {

node-graph/graph-craft/src/proto.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,14 @@ impl TypingContext {
794794
.into_iter()
795795
.chain(&inputs)
796796
.enumerate()
797-
.filter_map(|(i, t)| if i == 0 { None } else { Some(format!("• Input {}: {t}", i + convert_node_index_offset)) })
797+
.filter_map(|(i, t)| {
798+
if i == 0 {
799+
None
800+
} else {
801+
let number = i + convert_node_index_offset;
802+
Some(format!("• Input {number}: {t}"))
803+
}
804+
})
798805
.collect::<Vec<_>>()
799806
.join("\n");
800807
Err(vec![GraphError::new(node, GraphErrorType::InvalidImplementations { inputs, error_inputs })])
@@ -821,13 +828,13 @@ impl TypingContext {
821828
return Ok(node_io.clone());
822829
}
823830
}
824-
let inputs = [call_argument].into_iter().chain(&inputs).map(|t| t.to_string()).collect::<Vec<_>>().join(", ");
831+
let inputs = [call_argument].into_iter().chain(&inputs).map(ToString::to_string).collect::<Vec<_>>().join(", ");
825832
let valid = valid_output_types.into_iter().cloned().collect();
826833
Err(vec![GraphError::new(node, GraphErrorType::MultipleImplementations { inputs, valid })])
827834
}
828835

829836
_ => {
830-
let inputs = [call_argument].into_iter().chain(&inputs).map(|t| t.to_string()).collect::<Vec<_>>().join(", ");
837+
let inputs = [call_argument].into_iter().chain(&inputs).map(ToString::to_string).collect::<Vec<_>>().join(", ");
831838
let valid = valid_output_types.into_iter().cloned().collect();
832839
Err(vec![GraphError::new(node, GraphErrorType::MultipleImplementations { inputs, valid })])
833840
}
@@ -871,9 +878,7 @@ fn check_generic(types: &NodeIOTypes, input: &Type, parameters: &[Type], generic
871878
/// Returns a list of all generic types used in the node
872879
fn replace_generics(types: &mut NodeIOTypes, lookup: &HashMap<String, Type>) {
873880
let replace = |ty: &Type| {
874-
let Type::Generic(ident) = ty else {
875-
return None;
876-
};
881+
let Type::Generic(ident) = ty else { return None };
877882
lookup.get(ident.as_ref()).cloned()
878883
};
879884
types.call_argument.replace_nested(replace);

node-graph/libraries/core-types/src/types.rs

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,10 @@ impl NodeIOTypes {
118118

119119
impl std::fmt::Debug for NodeIOTypes {
120120
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121-
f.write_fmt(format_args!(
122-
"node({}) → {}",
123-
[&self.call_argument].into_iter().chain(&self.inputs).map(|input| input.to_string()).collect::<Vec<_>>().join(", "),
124-
self.return_value
125-
))
121+
let inputs = self.inputs.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ");
122+
let return_value = &self.return_value;
123+
let call_argument = &self.call_argument;
124+
f.write_fmt(format_args!("({inputs}) → {return_value} called with {call_argument}"))
126125
}
127126
}
128127

@@ -202,7 +201,7 @@ impl std::hash::Hash for TypeDescriptor {
202201

203202
impl std::fmt::Display for TypeDescriptor {
204203
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205-
let text = make_type_user_readable(&format_type(&self.name));
204+
let text = make_type_user_readable(&simplify_identifier_name(&self.name));
206205
write!(f, "{text}")
207206
}
208207
}
@@ -337,15 +336,17 @@ impl Type {
337336
}
338337
}
339338

340-
pub fn to_cow_string(&self) -> Cow<'static, str> {
339+
pub fn identifier_name(&self) -> String {
341340
match self {
342-
Type::Generic(name) => name.clone(),
343-
_ => Cow::Owned(self.to_string()),
341+
Type::Generic(name) => name.to_string(),
342+
Type::Concrete(ty) => simplify_identifier_name(&ty.name),
343+
Type::Fn(call_arg, return_value) => format!("{} called with {}", return_value.identifier_name(), call_arg.identifier_name()),
344+
Type::Future(ty) => ty.identifier_name(),
344345
}
345346
}
346347
}
347348

348-
pub fn format_type(ty: &str) -> String {
349+
pub fn simplify_identifier_name(ty: &str) -> String {
349350
ty.split('<')
350351
.map(|path| path.split(',').map(|path| path.split("::").last().unwrap_or(path)).collect::<Vec<_>>().join(","))
351352
.collect::<Vec<_>>()
@@ -361,42 +362,26 @@ pub fn make_type_user_readable(ty: &str) -> String {
361362

362363
impl std::fmt::Debug for Type {
363364
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
364-
let text = match self {
365-
Self::Generic(name) => name.to_string(),
366-
#[cfg(feature = "type_id_logging")]
367-
Self::Concrete(ty) => format!("Concrete<{}, {:?}>", ty.name, ty.id),
368-
#[cfg(not(feature = "type_id_logging"))]
369-
Self::Concrete(ty) => format_type(&ty.name),
370-
Self::Fn(call_arg, return_value) => format!("{return_value:?} called with {call_arg:?}"),
371-
Self::Future(ty) => format!("{ty:?}"),
372-
};
373-
let text = make_type_user_readable(&text);
374-
write!(f, "{text}")
365+
write!(f, "{self}")
375366
}
376367
}
377368

369+
// Display
378370
impl std::fmt::Display for Type {
379371
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
380-
if self == &concrete!(glam::DVec2) {
381-
return write!(f, "vec2");
382-
}
383-
if self == &concrete!(glam::DAffine2) {
384-
return write!(f, "transform");
385-
}
386-
if self == &concrete!(Footprint) {
387-
return write!(f, "footprint");
388-
}
389-
if self == &concrete!(&str) || self == &concrete!(String) {
390-
return write!(f, "string");
391-
}
372+
use glam::*;
392373

393-
let text = match self {
394-
Type::Generic(name) => name.to_string(),
395-
Type::Concrete(ty) => format_type(&ty.name),
396-
Type::Fn(call_arg, return_value) => format!("{return_value} called with {call_arg}"),
397-
Type::Future(ty) => ty.to_string(),
398-
};
399-
let text = make_type_user_readable(&text);
400-
write!(f, "{text}")
374+
match self {
375+
Type::Generic(name) => write!(f, "{}", make_type_user_readable(name)),
376+
Type::Concrete(ty) => match () {
377+
() if self == &concrete!(DVec2) || self == &concrete!(Vec2) || self == &concrete!(IVec2) || self == &concrete!(UVec2) => write!(f, "Vec2"),
378+
() if self == &concrete!(glam::DAffine2) => write!(f, "Transform"),
379+
() if self == &concrete!(Footprint) => write!(f, "Footprint"),
380+
() if self == &concrete!(&str) || self == &concrete!(String) => write!(f, "String"),
381+
_ => write!(f, "{}", make_type_user_readable(&simplify_identifier_name(&ty.name))),
382+
},
383+
Type::Fn(call_arg, return_value) => write!(f, "{return_value} called with {call_arg}"),
384+
Type::Future(ty) => write!(f, "{ty}"),
385+
}
401386
}
402387
}

node-graph/preprocessor/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn generate_node_substitutions() -> HashMap<ProtoNodeIdentifier, DocumentNod
3636
let id = id.clone();
3737

3838
let NodeMetadata { fields, .. } = metadata;
39-
let Some(implementations) = &node_registry.get(&id) else { continue };
39+
let Some(implementations) = node_registry.get(&id) else { continue };
4040
let valid_call_args: HashSet<_> = implementations.iter().map(|(_, node_io)| node_io.call_argument.clone()).collect();
4141
let first_node_io = implementations.first().map(|(_, node_io)| node_io).unwrap_or(const { &NodeIOTypes::empty() });
4242
let mut node_io_types = vec![HashSet::new(); fields.len()];
@@ -69,8 +69,8 @@ pub fn generate_node_substitutions() -> HashMap<ProtoNodeIdentifier, DocumentNod
6969
let input_ty = input.nested_type();
7070
let mut inputs = vec![NodeInput::import(input.clone(), i)];
7171

72-
let into_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::IntoNode<{}>", input_ty.clone()));
73-
let convert_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::ConvertNode<{}>", input_ty.clone()));
72+
let into_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::IntoNode<{}>", input_ty.identifier_name()));
73+
let convert_node_identifier = ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::ConvertNode<{}>", input_ty.identifier_name()));
7474

7575
let proto_node = if into_node_registry.keys().any(|ident: &ProtoNodeIdentifier| ident.as_str() == into_node_identifier.as_str()) {
7676
generated_nodes += 1;

0 commit comments

Comments
 (0)