diff --git a/src/hugr/serialize.rs b/src/hugr/serialize.rs index abc985616..67e209ac1 100644 --- a/src/hugr/serialize.rs +++ b/src/hugr/serialize.rs @@ -10,7 +10,6 @@ use pyo3::{create_exception, exceptions::PyException, PyErr}; use crate::core::NodeIndex; use crate::extension::ExtensionSet; use crate::hugr::{Hugr, NodeType}; -use crate::ops::OpTrait; use crate::ops::OpType; use crate::{Node, PortIndex}; use portgraph::hierarchy::AttachError; @@ -167,7 +166,7 @@ impl TryFrom<&Hugr> for SerHugrV0 { .expect("Could not reach one of the nodes"); let find_offset = |node: Node, offset: usize, dir: Direction, hugr: &Hugr| { - let sig = hugr.get_optype(node).signature(); + let sig = hugr.signature(node); let offset = match offset < sig.port_count(dir) { true => Some(offset as u16), false => None, diff --git a/src/hugr/views.rs b/src/hugr/views.rs index 114c41859..2078abf29 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -25,6 +25,8 @@ use portgraph::{multiportgraph, LinkView, MultiPortGraph, PortView}; use super::{Hugr, HugrError, NodeMetadata, NodeMetadataMap, NodeType, DEFAULT_NODETYPE}; use crate::ops::handle::NodeHandle; use crate::ops::{FuncDecl, FuncDefn, OpName, OpTag, OpTrait, OpType, DFG}; +#[rustversion::since(1.75)] // uses impl in return position +use crate::types::Type; use crate::types::{EdgeKind, FunctionType}; use crate::{Direction, IncomingPort, Node, OutgoingPort, Port}; @@ -355,6 +357,37 @@ pub trait HugrView: sealed::HugrInternals { .next() .map(|(n, _)| n) } + + /// Get the "signature" (incoming and outgoing types) of a node, non-Value + /// kind edges will be missing. + fn signature(&self, node: Node) -> FunctionType { + self.get_optype(node).signature() + } + + #[rustversion::since(1.75)] // uses impl in return position + /// Iterator over all ports in a given direction that have Value type, along + /// with corresponding types. + fn value_types(&self, node: Node, dir: Direction) -> impl Iterator { + let sig = self.signature(node); + self.node_ports(node, dir) + .flat_map(move |port| sig.port_type(port).map(|typ| (port, typ.clone()))) + } + + #[rustversion::since(1.75)] // uses impl in return position + /// Iterator over all incoming ports that have Value type, along + /// with corresponding types. + fn in_value_types(&self, node: Node) -> impl Iterator { + self.value_types(node, Direction::Incoming) + .map(|(p, t)| (p.as_incoming().unwrap(), t)) + } + + #[rustversion::since(1.75)] // uses impl in return position + /// Iterator over all incoming ports that have Value type, along + /// with corresponding types. + fn out_value_types(&self, node: Node) -> impl Iterator { + self.value_types(node, Direction::Outgoing) + .map(|(p, t)| (p.as_outgoing().unwrap(), t)) + } } /// Wraps an iterator over [Port]s that are known to be [OutgoingPort]s diff --git a/src/hugr/views/sibling_subgraph.rs b/src/hugr/views/sibling_subgraph.rs index deb518405..91a7dcb66 100644 --- a/src/hugr/views/sibling_subgraph.rs +++ b/src/hugr/views/sibling_subgraph.rs @@ -298,7 +298,7 @@ impl SiblingSubgraph { .iter() .map(|part| { let &(n, p) = part.iter().next().expect("is non-empty"); - let sig = hugr.get_optype(n).signature(); + let sig = hugr.signature(n); sig.port_type(p).cloned().expect("must be dataflow edge") }) .collect_vec(); @@ -306,7 +306,7 @@ impl SiblingSubgraph { .outputs .iter() .map(|&(n, p)| { - let sig = hugr.get_optype(n).signature(); + let sig = hugr.signature(n); sig.port_type(p).cloned().expect("must be dataflow edge") }) .collect_vec(); @@ -356,10 +356,10 @@ impl SiblingSubgraph { // See https://github.com/CQCL-DEV/hugr/discussions/432 let rep_inputs = replacement.node_outputs(rep_input).map(|p| (rep_input, p)); let rep_outputs = replacement.node_inputs(rep_output).map(|p| (rep_output, p)); - let (rep_inputs, in_order_ports): (Vec<_>, Vec<_>) = rep_inputs - .partition(|&(n, p)| replacement.get_optype(n).signature().port_type(p).is_some()); - let (rep_outputs, out_order_ports): (Vec<_>, Vec<_>) = rep_outputs - .partition(|&(n, p)| replacement.get_optype(n).signature().port_type(p).is_some()); + let (rep_inputs, in_order_ports): (Vec<_>, Vec<_>) = + rep_inputs.partition(|&(n, p)| replacement.signature(n).port_type(p).is_some()); + let (rep_outputs, out_order_ports): (Vec<_>, Vec<_>) = + rep_outputs.partition(|&(n, p)| replacement.signature(n).port_type(p).is_some()); if combine_in_out(&vec![out_order_ports], &in_order_ports) .any(|(n, p)| is_order_edge(&replacement, n, p)) @@ -467,10 +467,10 @@ impl<'g, Base: HugrView> ConvexChecker<'g, Base> { /// If the array is empty or a port does not exist, returns `None`. fn get_edge_type + Copy>(hugr: &H, ports: &[(Node, P)]) -> Option { let &(n, p) = ports.first()?; - let edge_t = hugr.get_optype(n).signature().port_type(p)?.clone(); + let edge_t = hugr.signature(n).port_type(p)?.clone(); ports .iter() - .all(|&(n, p)| hugr.get_optype(n).signature().port_type(p) == Some(&edge_t)) + .all(|&(n, p)| hugr.signature(n).port_type(p) == Some(&edge_t)) .then_some(edge_t) } diff --git a/src/hugr/views/tests.rs b/src/hugr/views/tests.rs index 816a0c41b..9b1833213 100644 --- a/src/hugr/views/tests.rs +++ b/src/hugr/views/tests.rs @@ -117,3 +117,34 @@ fn all_ports(sample_hugr: (Hugr, BuildHandle, BuildHandle