From e28c60a73eab33366b704e0ed0e538aa19345975 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 12 Sep 2023 15:33:49 +0100 Subject: [PATCH 01/10] Move valid_node/valid_non_root into HugrView (no uses yet) --- src/hugr/hugrmut.rs | 24 ------------------------ src/hugr/views.rs | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/hugr/hugrmut.rs b/src/hugr/hugrmut.rs index 5cd338f35..671031ac2 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -312,30 +312,6 @@ pub(crate) mod sealed { /// Returns the Hugr at the base of a chain of views. fn hugr_mut(&mut self) -> &mut Hugr; - /// Validates that a node is valid in the graph. - /// - /// Returns a [`HugrError::InvalidNode`] otherwise. - #[inline] - fn valid_node(&self, node: Node) -> Result<(), HugrError> { - match self.contains_node(node) { - true => Ok(()), - false => Err(HugrError::InvalidNode(node)), - } - } - - /// Validates that a node is a valid root descendant in the graph. - /// - /// To include the root node use [`HugrMutInternals::valid_node`] instead. - /// - /// Returns a [`HugrError::InvalidNode`] otherwise. - #[inline] - fn valid_non_root(&self, node: Node) -> Result<(), HugrError> { - match self.root() == node { - true => Err(HugrError::InvalidNode(node)), - false => self.valid_node(node), - } - } - /// Add a node to the graph, with the default conversion from OpType to NodeType fn add_op(&mut self, op: impl Into) -> Node { self.hugr_mut().add_op(op) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index cb66167e5..1cd671e69 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -18,7 +18,7 @@ use itertools::{Itertools, MapInto}; use portgraph::dot::{DotFormat, EdgeStyle, NodeStyle, PortStyle}; use portgraph::{multiportgraph, LinkView, MultiPortGraph, PortView}; -use super::{Hugr, NodeMetadata, NodeType}; +use super::{Hugr, HugrError, NodeMetadata, NodeType}; use crate::ops::handle::NodeHandle; use crate::ops::{FuncDecl, FuncDefn, OpName, OpTag, OpType, DFG}; use crate::types::{EdgeKind, FunctionType}; @@ -80,6 +80,30 @@ pub trait HugrView: sealed::HugrInternals { /// Returns whether the node exists. fn contains_node(&self, node: Node) -> bool; + /// Validates that a node is valid in the graph. + /// + /// Returns a [`HugrError::InvalidNode`] otherwise. + #[inline] + fn valid_node(&self, node: Node) -> Result<(), HugrError> { + match self.contains_node(node) { + true => Ok(()), + false => Err(HugrError::InvalidNode(node)), + } + } + + /// Validates that a node is a valid root descendant in the graph. + /// + /// To include the root node use [`HugrView::valid_node`] instead. + /// + /// Returns a [`HugrError::InvalidNode`] otherwise. + #[inline] + fn valid_non_root(&self, node: Node) -> Result<(), HugrError> { + match self.root() == node { + true => Err(HugrError::InvalidNode(node)), + false => self.valid_node(node), + } + } + /// Returns the parent of a node. fn get_parent(&self, node: Node) -> Option; From f2b64e15274d453ac5269b3e2ae003c0e1434b74 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 12 Sep 2023 12:56:15 +0100 Subject: [PATCH 02/10] Implement HugrView::get_{parent,{node,op}type,metadata} once only, with valid_node checks ==> SiblingGraph::new's "get_optype" will implicitly check the root is in the base view. This does mean some unnecessary index checking for &Hugr's. We could continue to reimplement those methods for AsRef if we want to avoid this inefficiency. Alternatively we could make UnmanagedDenseMap return Options rather than unwrapping. Some other ugly alternative/hacks for returning default values - DEFAULT_{NODE,OP}TYPE --- src/hugr.rs | 8 ++++- src/hugr/views.rs | 56 +++++++++++++++++++---------------- src/hugr/views/descendants.rs | 27 ++--------------- src/hugr/views/sibling.rs | 24 ++------------- src/ops.rs | 5 +++- 5 files changed, 46 insertions(+), 74 deletions(-) diff --git a/src/hugr.rs b/src/hugr.rs index f697c63b7..a3ab61542 100644 --- a/src/hugr.rs +++ b/src/hugr.rs @@ -29,7 +29,7 @@ pub use self::views::HugrView; use crate::extension::{ infer_extensions, ExtensionRegistry, ExtensionSet, ExtensionSolution, InferExtensionError, }; -use crate::ops::{OpTag, OpTrait, OpType}; +use crate::ops::{OpTag, OpTrait, OpType, DEFAULT_OPTYPE}; use crate::types::{FunctionType, Signature}; use delegate::delegate; @@ -64,6 +64,12 @@ pub struct NodeType { input_extensions: Option, } +/// The default NodeType, with open extensions +pub const DEFAULT_NODETYPE: NodeType = NodeType { + op: DEFAULT_OPTYPE, + input_extensions: None, // Default for any Option +}; + impl NodeType { /// Create a new optype with some ExtensionSet pub fn new(op: impl Into, input_extensions: impl Into>) -> Self { diff --git a/src/hugr/views.rs b/src/hugr/views.rs index 1cd671e69..1b19f760c 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -18,7 +18,7 @@ use itertools::{Itertools, MapInto}; use portgraph::dot::{DotFormat, EdgeStyle, NodeStyle, PortStyle}; use portgraph::{multiportgraph, LinkView, MultiPortGraph, PortView}; -use super::{Hugr, HugrError, NodeMetadata, NodeType}; +use super::{Hugr, HugrError, NodeMetadata, NodeType, DEFAULT_NODETYPE}; use crate::ops::handle::NodeHandle; use crate::ops::{FuncDecl, FuncDefn, OpName, OpTag, OpType, DFG}; use crate::types::{EdgeKind, FunctionType}; @@ -105,16 +105,42 @@ pub trait HugrView: sealed::HugrInternals { } /// Returns the parent of a node. - fn get_parent(&self, node: Node) -> Option; + #[inline] + fn get_parent(&self, node: Node) -> Option { + self.valid_non_root(node).ok()?; + self.base_hugr() + .hierarchy + .parent(node.index) + .map(Into::into) + } /// Returns the operation type of a node. - fn get_optype(&self, node: Node) -> &OpType; + #[inline] + fn get_optype(&self, node: Node) -> &OpType { + &self.get_nodetype(node).op + } /// Returns the type of a node. - fn get_nodetype(&self, node: Node) -> &NodeType; + #[inline] + fn get_nodetype(&self, node: Node) -> &NodeType { + match self.contains_node(node) { + true => self.base_hugr().op_types.get(node.index), + false => &DEFAULT_NODETYPE, + } + } /// Returns the metadata associated with a node. - fn get_metadata(&self, node: Node) -> &NodeMetadata; + #[inline] + fn get_metadata(&self, node: Node) -> &NodeMetadata { + // The other way to do it - exploit the UnmanagedDenseMap's get() returning &default + let md = &self.base_hugr().metadata; + + let idx = match self.contains_node(node) { + true => node.index, + false => portgraph::NodeIndex::new(md.capacity() + 1), + }; + md.get(idx) + } /// Returns the number of nodes in the hugr. fn node_count(&self) -> usize; @@ -311,21 +337,6 @@ where self.as_ref().graph.contains_node(node.index) } - #[inline] - fn get_parent(&self, node: Node) -> Option { - self.as_ref().hierarchy.parent(node.index).map(Into::into) - } - - #[inline] - fn get_optype(&self, node: Node) -> &OpType { - &self.as_ref().op_types.get(node.index).op - } - - #[inline] - fn get_nodetype(&self, node: Node) -> &NodeType { - self.as_ref().op_types.get(node.index) - } - #[inline] fn node_count(&self) -> usize { self.as_ref().graph.node_count() @@ -410,11 +421,6 @@ where None } } - - #[inline] - fn get_metadata(&self, node: Node) -> &NodeMetadata { - self.as_ref().metadata.get(node.index) - } } pub(crate) mod sealed { diff --git a/src/hugr/views/descendants.rs b/src/hugr/views/descendants.rs index 73f7791a9..4355ddb53 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -7,9 +7,9 @@ use portgraph::{LinkView, MultiPortGraph, PortIndex, PortView}; use crate::ops::handle::NodeHandle; use crate::ops::OpTrait; -use crate::{hugr::NodeType, hugr::OpType, Direction, Hugr, Node, Port}; +use crate::{Direction, Hugr, Node, Port}; -use super::{sealed::HugrInternals, HierarchyView, HugrView, NodeMetadata}; +use super::{sealed::HugrInternals, HierarchyView, HugrView}; type RegionGraph<'g> = portgraph::view::Region<'g, &'g MultiPortGraph>; @@ -94,29 +94,6 @@ where self.graph.contains_node(node.index) } - #[inline] - fn get_parent(&self, node: Node) -> Option { - self.hugr - .get_parent(node) - .filter(|&parent| self.graph.contains_node(parent.index)) - .map(Into::into) - } - - #[inline] - fn get_optype(&self, node: Node) -> &OpType { - self.hugr.get_optype(node) - } - - #[inline] - fn get_nodetype(&self, node: Node) -> &NodeType { - self.hugr.get_nodetype(node) - } - - #[inline] - fn get_metadata(&self, node: Node) -> &NodeMetadata { - self.hugr.get_metadata(node) - } - #[inline] fn node_count(&self) -> usize { self.graph.node_count() diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index d2caf509d..16640e367 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -8,9 +8,9 @@ use portgraph::{LinkView, MultiPortGraph, PortIndex, PortView}; use crate::ops::handle::NodeHandle; use crate::ops::OpTrait; -use crate::{hugr::NodeType, hugr::OpType, Direction, Hugr, Node, Port}; +use crate::{Direction, Hugr, Node, Port}; -use super::{sealed::HugrInternals, HierarchyView, HugrView, NodeMetadata}; +use super::{sealed::HugrInternals, HierarchyView, HugrView}; type FlatRegionGraph<'g> = portgraph::view::FlatRegion<'g, &'g MultiPortGraph>; @@ -94,26 +94,6 @@ where self.graph.contains_node(node.index) } - #[inline] - fn get_parent(&self, node: Node) -> Option { - self.hugr.get_parent(node).filter(|&n| n == self.root) - } - - #[inline] - fn get_optype(&self, node: Node) -> &OpType { - self.hugr.get_optype(node) - } - - #[inline] - fn get_nodetype(&self, node: Node) -> &NodeType { - self.hugr.get_nodetype(node) - } - - #[inline] - fn get_metadata(&self, node: Node) -> &NodeMetadata { - self.hugr.get_metadata(node) - } - #[inline] fn node_count(&self) -> usize { self.base_hugr().hierarchy.child_count(self.root.index) + 1 diff --git a/src/ops.rs b/src/ops.rs index cbd928fe7..0334becd3 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -52,9 +52,12 @@ pub enum OpType { Case, } +/// The default OpType (as returned by [Default::default]) +pub const DEFAULT_OPTYPE: OpType = OpType::Module(Module); + impl Default for OpType { fn default() -> Self { - Module.into() + DEFAULT_OPTYPE } } From 17c3a3023970d114100aada54a9208480e89d42a Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 12 Sep 2023 13:12:34 +0100 Subject: [PATCH 03/10] Remove Base type-parameter to SiblingGraph/DescendantsGraph, call base_hugr in c'tor --- src/hugr/views.rs | 5 +---- src/hugr/views/descendants.rs | 32 ++++++++++---------------------- src/hugr/views/sibling.rs | 34 +++++++++++----------------------- 3 files changed, 22 insertions(+), 49 deletions(-) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index 1b19f760c..bce46a46d 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -300,11 +300,8 @@ pub trait HugrView: sealed::HugrInternals { /// A common trait for views of a HUGR hierarchical subgraph. pub trait HierarchyView<'a>: HugrView { - /// The base from which the subgraph is derived. - type Base; - /// Create a hierarchical view of a HUGR given a root node. - fn new(hugr: &'a Self::Base, root: Node) -> Self; + fn new(hugr: &'a impl HugrView, root: Node) -> Self; } impl HugrView for T diff --git a/src/hugr/views/descendants.rs b/src/hugr/views/descendants.rs index 4355ddb53..748a74826 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -25,10 +25,7 @@ type RegionGraph<'g> = portgraph::view::Region<'g, &'g MultiPortGraph>; /// used interchangeably with [`SiblingGraph`]. /// /// [`SiblingGraph`]: super::SiblingGraph -pub struct DescendantsGraph<'g, Root = Node, Base = Hugr> -where - Base: HugrInternals, -{ +pub struct DescendantsGraph<'g, Root = Node> { /// The chosen root node. root: Node, @@ -36,26 +33,24 @@ where graph: RegionGraph<'g>, /// The node hierarchy. - hugr: &'g Base, + hugr: &'g Hugr, /// The operation handle of the root node. _phantom: std::marker::PhantomData, } -impl<'g, Root, Base: Clone> Clone for DescendantsGraph<'g, Root, Base> +impl<'g, Root> Clone for DescendantsGraph<'g, Root> where Root: NodeHandle, - Base: HugrInternals + HugrView, { fn clone(&self) -> Self { DescendantsGraph::new(self.hugr, self.root) } } -impl<'g, Root, Base> HugrView for DescendantsGraph<'g, Root, Base> +impl<'g, Root> HugrView for DescendantsGraph<'g, Root> where Root: NodeHandle, - Base: HugrInternals + HugrView, { type RootHandle = Root; @@ -173,36 +168,29 @@ where } } -impl<'a, Root, Base> HierarchyView<'a> for DescendantsGraph<'a, Root, Base> +impl<'a, Root> HierarchyView<'a> for DescendantsGraph<'a, Root> where Root: NodeHandle, - Base: HugrView, { - type Base = Base; - - fn new(hugr: &'a Base, root: Node) -> Self { + fn new(hugr: &'a impl HugrView, root: Node) -> Self { let root_tag = hugr.get_optype(root).tag(); if !Root::TAG.is_superset(root_tag) { // TODO: Return an error panic!("Root node must have the correct operation type tag.") } + let hugr = hugr.base_hugr(); Self { root, - graph: RegionGraph::new_region( - &hugr.base_hugr().graph, - &hugr.base_hugr().hierarchy, - root.index, - ), + graph: RegionGraph::new_region(&hugr.graph, &hugr.hierarchy, root.index), hugr, _phantom: std::marker::PhantomData, } } } -impl<'g, Root, Base> super::sealed::HugrInternals for DescendantsGraph<'g, Root, Base> +impl<'g, Root> super::sealed::HugrInternals for DescendantsGraph<'g, Root> where Root: NodeHandle, - Base: HugrInternals, { type Portgraph<'p> = &'p RegionGraph<'g> where Self: 'p; @@ -213,7 +201,7 @@ where #[inline] fn base_hugr(&self) -> &Hugr { - self.hugr.base_hugr() + self.hugr } #[inline] diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index 16640e367..da5b03574 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -25,37 +25,32 @@ type FlatRegionGraph<'g> = portgraph::view::FlatRegion<'g, &'g MultiPortGraph>; /// used interchangeably with [`DescendantsGraph`]. /// /// [`DescendantsGraph`]: super::DescendantsGraph -pub struct SiblingGraph<'g, Root = Node, Base = Hugr> -where - Base: HugrInternals, -{ +pub struct SiblingGraph<'g, Root = Node> { /// The chosen root node. root: Node, /// The filtered portgraph encoding the adjacency structure of the HUGR. graph: FlatRegionGraph<'g>, - /// The rest of the HUGR. - hugr: &'g Base, + /// View onto the underlying Hugr which this graph filters + hugr: &'g Hugr, /// The operation type of the root node. _phantom: std::marker::PhantomData, } -impl<'g, Root, Base> Clone for SiblingGraph<'g, Root, Base> +impl<'g, Root> Clone for SiblingGraph<'g, Root> where Root: NodeHandle, - Base: HugrInternals + HugrView, { fn clone(&self) -> Self { SiblingGraph::new(self.hugr, self.root) } } -impl<'g, Root, Base> HugrView for SiblingGraph<'g, Root, Base> +impl<'g, Root> HugrView for SiblingGraph<'g, Root> where Root: NodeHandle, - Base: HugrInternals + HugrView, { type RootHandle = Root; @@ -186,36 +181,29 @@ where } } -impl<'a, Root, Base> HierarchyView<'a> for SiblingGraph<'a, Root, Base> +impl<'a, Root> HierarchyView<'a> for SiblingGraph<'a, Root> where Root: NodeHandle, - Base: HugrView, { - type Base = Base; - - fn new(hugr: &'a Base, root: Node) -> Self { + fn new(hugr: &'a impl HugrView, root: Node) -> Self { let root_tag = hugr.get_optype(root).tag(); if !Root::TAG.is_superset(root_tag) { // TODO: Return an error panic!("Root node must have the correct operation type tag.") } + let hugr = hugr.base_hugr(); Self { root, - graph: FlatRegionGraph::new_flat_region( - &hugr.base_hugr().graph, - &hugr.base_hugr().hierarchy, - root.index, - ), + graph: FlatRegionGraph::new_flat_region(&hugr.graph, &hugr.hierarchy, root.index), hugr, _phantom: std::marker::PhantomData, } } } -impl<'g, Root, Base> HugrInternals for SiblingGraph<'g, Root, Base> +impl<'g, Root> HugrInternals for SiblingGraph<'g, Root> where Root: NodeHandle, - Base: HugrInternals, { type Portgraph<'p> = &'p FlatRegionGraph<'g> where Self: 'p; @@ -226,7 +214,7 @@ where #[inline] fn base_hugr(&self) -> &Hugr { - self.hugr.base_hugr() + self.hugr } #[inline] From 8475d12edcd81b49bec4fee796b1379532849f43 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 12 Sep 2023 15:49:42 +0100 Subject: [PATCH 04/10] Derive Clone for SiblingGraph + DescendantsGraph --- src/hugr/views/descendants.rs | 10 +--------- src/hugr/views/sibling.rs | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/hugr/views/descendants.rs b/src/hugr/views/descendants.rs index 748a74826..185291049 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -25,6 +25,7 @@ type RegionGraph<'g> = portgraph::view::Region<'g, &'g MultiPortGraph>; /// used interchangeably with [`SiblingGraph`]. /// /// [`SiblingGraph`]: super::SiblingGraph +#[derive(Clone)] pub struct DescendantsGraph<'g, Root = Node> { /// The chosen root node. root: Node, @@ -39,15 +40,6 @@ pub struct DescendantsGraph<'g, Root = Node> { _phantom: std::marker::PhantomData, } -impl<'g, Root> Clone for DescendantsGraph<'g, Root> -where - Root: NodeHandle, -{ - fn clone(&self) -> Self { - DescendantsGraph::new(self.hugr, self.root) - } -} - impl<'g, Root> HugrView for DescendantsGraph<'g, Root> where Root: NodeHandle, diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index da5b03574..df7139100 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -25,6 +25,7 @@ type FlatRegionGraph<'g> = portgraph::view::FlatRegion<'g, &'g MultiPortGraph>; /// used interchangeably with [`DescendantsGraph`]. /// /// [`DescendantsGraph`]: super::DescendantsGraph +#[derive(Clone)] pub struct SiblingGraph<'g, Root = Node> { /// The chosen root node. root: Node, @@ -39,15 +40,6 @@ pub struct SiblingGraph<'g, Root = Node> { _phantom: std::marker::PhantomData, } -impl<'g, Root> Clone for SiblingGraph<'g, Root> -where - Root: NodeHandle, -{ - fn clone(&self) -> Self { - SiblingGraph::new(self.hugr, self.root) - } -} - impl<'g, Root> HugrView for SiblingGraph<'g, Root> where Root: NodeHandle, From aa88f7579e8177f39c9f774fc3974559cccfb2ed Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 12 Sep 2023 15:55:13 +0100 Subject: [PATCH 05/10] HierarchyView::new returns Result/HugrError --- src/algorithm/nest_cfgs.rs | 2 +- src/hugr/validate.rs | 4 ++-- src/hugr/views.rs | 7 +++++-- src/hugr/views/descendants.rs | 15 ++++++++------- src/hugr/views/sibling.rs | 16 ++++++++-------- src/hugr/views/sibling_subgraph.rs | 21 +++++++++++---------- 6 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/algorithm/nest_cfgs.rs b/src/algorithm/nest_cfgs.rs index 9a5d48559..9de39e158 100644 --- a/src/algorithm/nest_cfgs.rs +++ b/src/algorithm/nest_cfgs.rs @@ -449,7 +449,7 @@ pub(crate) mod test { let (split, merge, head, tail) = (split.node(), merge.node(), head.node(), tail.node()); // There's no need to use a FlatRegionView here but we do so just to check // that we *can* (as we'll need to for "real" module Hugr's). - let v: SiblingGraph = SiblingGraph::new(&h, h.root()); + let v: SiblingGraph = SiblingGraph::new(&h, h.root()).unwrap(); let edge_classes = EdgeClassifier::get_edge_classes(&SimpleCfgView::new(&v)); let [&left, &right] = edge_classes .keys() diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index 9db0a4f7b..74912dcba 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -100,7 +100,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { /// The results of this computation should be cached in `self.dominators`. /// We don't do it here to avoid mutable borrows. fn compute_dominator(&self, parent: Node) -> Dominators { - let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); + let region: SiblingGraph = SiblingGraph::new(self.hugr, parent).unwrap(); let entry_node = self.hugr.children(parent).next().unwrap(); dominators::simple_fast(®ion.as_petgraph(), entry_node) } @@ -374,7 +374,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { return Ok(()); }; - let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); + let region: SiblingGraph = SiblingGraph::new(self.hugr, parent).unwrap(); let postorder = Topo::new(®ion.as_petgraph()); let nodes_visited = postorder .iter(®ion.as_petgraph()) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index bce46a46d..392fa8a2c 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -299,9 +299,12 @@ pub trait HugrView: sealed::HugrInternals { } /// A common trait for views of a HUGR hierarchical subgraph. -pub trait HierarchyView<'a>: HugrView { +pub trait HierarchyView<'a>: HugrView + Sized { /// Create a hierarchical view of a HUGR given a root node. - fn new(hugr: &'a impl HugrView, root: Node) -> Self; + /// + /// # Errors + /// Returns [`HugrError::InvalidNode`] if the root isn't a node of the required [OpTag] + fn new(hugr: &'a impl HugrView, root: Node) -> Result; } impl HugrView for T diff --git a/src/hugr/views/descendants.rs b/src/hugr/views/descendants.rs index 185291049..13ec68dce 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -5,6 +5,7 @@ use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; use itertools::{Itertools, MapInto}; use portgraph::{LinkView, MultiPortGraph, PortIndex, PortView}; +use crate::hugr::HugrError; use crate::ops::handle::NodeHandle; use crate::ops::OpTrait; use crate::{Direction, Hugr, Node, Port}; @@ -164,19 +165,19 @@ impl<'a, Root> HierarchyView<'a> for DescendantsGraph<'a, Root> where Root: NodeHandle, { - fn new(hugr: &'a impl HugrView, root: Node) -> Self { + fn new(hugr: &'a impl HugrView, root: Node) -> Result { + hugr.valid_node(root)?; let root_tag = hugr.get_optype(root).tag(); if !Root::TAG.is_superset(root_tag) { - // TODO: Return an error - panic!("Root node must have the correct operation type tag.") + return Err(HugrError::InvalidNode(root)); } let hugr = hugr.base_hugr(); - Self { + Ok(Self { root, graph: RegionGraph::new_region(&hugr.graph, &hugr.hierarchy, root.index), hugr, _phantom: std::marker::PhantomData, - } + }) } } @@ -256,7 +257,7 @@ pub(super) mod test { fn full_region() -> Result<(), Box> { let (hugr, def, inner) = make_module_hgr()?; - let region: DescendantsGraph = DescendantsGraph::new(&hugr, def); + let region: DescendantsGraph = DescendantsGraph::new(&hugr, def)?; assert_eq!(region.node_count(), 7); assert!(region.nodes().all(|n| n == def @@ -268,7 +269,7 @@ pub(super) mod test { region.get_function_type(), Some(&FunctionType::new(type_row![NAT, QB], type_row![NAT, QB])) ); - let inner_region: DescendantsGraph = DescendantsGraph::new(&hugr, inner); + let inner_region: DescendantsGraph = DescendantsGraph::new(&hugr, inner)?; assert_eq!( inner_region.get_function_type(), Some(&FunctionType::new(type_row![NAT], type_row![NAT])) diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index df7139100..7d100d1ab 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -6,6 +6,7 @@ use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; use itertools::{Itertools, MapInto}; use portgraph::{LinkView, MultiPortGraph, PortIndex, PortView}; +use crate::hugr::HugrError; use crate::ops::handle::NodeHandle; use crate::ops::OpTrait; use crate::{Direction, Hugr, Node, Port}; @@ -177,19 +178,18 @@ impl<'a, Root> HierarchyView<'a> for SiblingGraph<'a, Root> where Root: NodeHandle, { - fn new(hugr: &'a impl HugrView, root: Node) -> Self { - let root_tag = hugr.get_optype(root).tag(); - if !Root::TAG.is_superset(root_tag) { - // TODO: Return an error - panic!("Root node must have the correct operation type tag.") + fn new(hugr: &'a impl HugrView, root: Node) -> Result { + hugr.valid_node(root)?; + if !Root::TAG.is_superset(hugr.get_optype(root).tag()) { + return Err(HugrError::InvalidNode(root)); } let hugr = hugr.base_hugr(); - Self { + Ok(Self { root, graph: FlatRegionGraph::new_flat_region(&hugr.graph, &hugr.hierarchy, root.index), hugr, _phantom: std::marker::PhantomData, - } + }) } } @@ -224,7 +224,7 @@ mod test { fn flat_region() -> Result<(), Box> { let (hugr, def, inner) = make_module_hgr()?; - let region: SiblingGraph = SiblingGraph::new(&hugr, def); + let region: SiblingGraph = SiblingGraph::new(&hugr, def)?; assert_eq!(region.node_count(), 5); assert!(region diff --git a/src/hugr/views/sibling_subgraph.rs b/src/hugr/views/sibling_subgraph.rs index 7edf1beea..e7e47a5fc 100644 --- a/src/hugr/views/sibling_subgraph.rs +++ b/src/hugr/views/sibling_subgraph.rs @@ -579,9 +579,9 @@ mod tests { #[test] fn construct_subgraph() -> Result<(), InvalidSubgraph> { let (hugr, func_root) = build_hugr().unwrap(); - let sibling_graph: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root); + let sibling_graph: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); let from_root = SiblingSubgraph::from_sibling_graph(&sibling_graph)?; - let region: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root); + let region: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); let from_region = SiblingSubgraph::from_sibling_graph(®ion)?; assert_eq!( from_root.get_parent(&sibling_graph), @@ -597,7 +597,7 @@ mod tests { #[test] fn construct_simple_replacement() -> Result<(), InvalidSubgraph> { let (mut hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, func_root); + let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, func_root).unwrap(); let sub = SiblingSubgraph::try_new_dataflow_subgraph(&func)?; let empty_dfg = { @@ -620,7 +620,7 @@ mod tests { #[test] fn test_signature() -> Result<(), InvalidSubgraph> { let (hugr, dfg) = build_hugr().unwrap(); - let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, dfg); + let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, dfg).unwrap(); let sub = SiblingSubgraph::try_new_dataflow_subgraph(&func)?; assert_eq!( sub.signature(&func), @@ -632,7 +632,7 @@ mod tests { #[test] fn construct_simple_replacement_invalid_signature() -> Result<(), InvalidSubgraph> { let (hugr, dfg) = build_hugr().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, dfg); + let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, dfg).unwrap(); let sub = SiblingSubgraph::from_sibling_graph(&func)?; let empty_dfg = { @@ -651,7 +651,7 @@ mod tests { #[test] fn convex_subgraph() { let (hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, func_root); + let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, func_root).unwrap(); assert_eq!( SiblingSubgraph::try_new_dataflow_subgraph(&func) .unwrap() @@ -665,7 +665,7 @@ mod tests { fn convex_subgraph_2() { let (hugr, func_root) = build_hugr().unwrap(); let (inp, out) = hugr.children(func_root).take(2).collect_tuple().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root); + let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); // All graph except input/output nodes SiblingSubgraph::try_new( hugr.node_outputs(inp) @@ -683,7 +683,7 @@ mod tests { #[test] fn degen_boundary() { let (hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root); + let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); let (inp, _) = hugr.children(func_root).take(2).collect_tuple().unwrap(); let first_cx_edge = hugr.node_outputs(inp).next().unwrap(); // All graph but one edge @@ -700,7 +700,7 @@ mod tests { #[test] fn non_convex_subgraph() { let (hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root); + let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); let (inp, out) = hugr.children(func_root).take(2).collect_tuple().unwrap(); let first_cx_edge = hugr.node_outputs(inp).next().unwrap(); let snd_cx_edge = hugr.node_inputs(out).next().unwrap(); @@ -718,7 +718,8 @@ mod tests { #[test] fn preserve_signature() { let (hugr, func_root) = build_hugr_classical().unwrap(); - let func_graph: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, func_root); + let func_graph: SiblingGraph<'_, FuncID> = + SiblingGraph::new(&hugr, func_root).unwrap(); let func = SiblingSubgraph::try_new_dataflow_subgraph(&func_graph).unwrap(); let OpType::FuncDefn(func_defn) = hugr.get_optype(func_root) else { panic!() From 487c795b5e60a55a7311ca12691614614f6de017 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 12 Sep 2023 16:45:31 +0100 Subject: [PATCH 06/10] test --- src/hugr/views/sibling.rs | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index 7d100d1ab..bfa6146a2 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -179,8 +179,13 @@ where Root: NodeHandle, { fn new(hugr: &'a impl HugrView, root: Node) -> Result { + println!("ALAN checking node {:?} against {}", root, Root::TAG); hugr.valid_node(root)?; if !Root::TAG.is_superset(hugr.get_optype(root).tag()) { + println!( + "ALAN check failed, optype was {}", + hugr.get_optype(root).tag() + ); return Err(HugrError::InvalidNode(root)); } let hugr = hugr.base_hugr(); @@ -217,6 +222,13 @@ where #[cfg(test)] mod test { + use crate::builder::{Container, Dataflow, DataflowSubContainer, HugrBuilder, ModuleBuilder}; + use crate::extension::PRELUDE_REGISTRY; + use crate::ops::handle::{DfgID, FuncID, ModuleRootID}; + use crate::ops::{dataflow::IOTrait, Input, Output}; + use crate::type_row; + use crate::types::{FunctionType, Type}; + use super::super::descendants::test::make_module_hgr; use super::*; @@ -234,4 +246,45 @@ mod test { Ok(()) } + + const NAT: Type = crate::extension::prelude::USIZE_T; + #[test] + fn nested_flat() -> Result<(), Box> { + let mut module_builder = ModuleBuilder::new(); + let fty = FunctionType::new(type_row![NAT], type_row![NAT]); + let mut fbuild = module_builder.define_function("main", fty.clone().pure())?; + let dfg = fbuild.dfg_builder(fty, None, fbuild.input_wires())?; + let ins = dfg.input_wires(); + let sub_dfg = dfg.finish_with_outputs(ins)?; + let fun = fbuild.finish_with_outputs(sub_dfg.outputs())?; + let h = module_builder.finish_hugr(&PRELUDE_REGISTRY)?; + let sub_dfg = sub_dfg.node(); + // Can create a view from a child or grandchild of a hugr: + let dfg_view: SiblingGraph<'_, DfgID> = SiblingGraph::new(&h, sub_dfg)?; + let fun_view: SiblingGraph<'_, FuncID> = SiblingGraph::new(&h, fun.node())?; + assert_eq!(fun_view.children(sub_dfg).len(), 0); + // And can create a view from a child of another SiblingGraph + let nested_dfg_view: SiblingGraph<'_, DfgID> = SiblingGraph::new(&fun_view, sub_dfg)?; + + // Both ways work: + let just_io = vec![ + Input::new(type_row![NAT]).into(), + Output::new(type_row![NAT]).into(), + ]; + for d in [dfg_view, nested_dfg_view] { + assert_eq!( + d.children(sub_dfg).map(|n| d.get_optype(n)).collect_vec(), + just_io.iter().collect_vec() + ); + } + + // But cannot create a view directly as a grandchild of another SiblingGraph + let root_view: SiblingGraph<'_, ModuleRootID> = SiblingGraph::new(&h, h.root()).unwrap(); + assert_eq!( + SiblingGraph::<'_, DfgID>::new(&root_view, sub_dfg.node()).err(), + Some(HugrError::InvalidNode(sub_dfg.node())) + ); + + Ok(()) + } } From 430e4e6b10035edfa9c0e0495031f1308cea2120 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 12 Sep 2023 18:30:51 +0100 Subject: [PATCH 07/10] Remove debug println --- src/hugr/views/sibling.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index bfa6146a2..a9a32acb7 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -179,13 +179,8 @@ where Root: NodeHandle, { fn new(hugr: &'a impl HugrView, root: Node) -> Result { - println!("ALAN checking node {:?} against {}", root, Root::TAG); hugr.valid_node(root)?; if !Root::TAG.is_superset(hugr.get_optype(root).tag()) { - println!( - "ALAN check failed, optype was {}", - hugr.get_optype(root).tag() - ); return Err(HugrError::InvalidNode(root)); } let hugr = hugr.base_hugr(); From c7899696273e7c854aff6ebf9d48d47f14db47e2 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 13 Sep 2023 10:22:54 +0100 Subject: [PATCH 08/10] use NodeMetadata::Null --- src/hugr/views.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index 392fa8a2c..afc808e53 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -132,14 +132,10 @@ pub trait HugrView: sealed::HugrInternals { /// Returns the metadata associated with a node. #[inline] fn get_metadata(&self, node: Node) -> &NodeMetadata { - // The other way to do it - exploit the UnmanagedDenseMap's get() returning &default - let md = &self.base_hugr().metadata; - - let idx = match self.contains_node(node) { - true => node.index, - false => portgraph::NodeIndex::new(md.capacity() + 1), - }; - md.get(idx) + match self.contains_node(node) { + true => self.base_hugr().metadata.get(node.index), + false => &NodeMetadata::Null, + } } /// Returns the number of nodes in the hugr. From 6507bbc8cd95b9ea1c579e60df002e8ffb960797 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 13 Sep 2023 10:23:54 +0100 Subject: [PATCH 09/10] correct comment re. view/filter --- src/hugr/views/sibling.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index a9a32acb7..0ba04e981 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -34,7 +34,7 @@ pub struct SiblingGraph<'g, Root = Node> { /// The filtered portgraph encoding the adjacency structure of the HUGR. graph: FlatRegionGraph<'g>, - /// View onto the underlying Hugr which this graph filters + /// The underlying Hugr onto which this view is a filter hugr: &'g Hugr, /// The operation type of the root node. From 929ecf4761d043e427f347ae33746d76f85e0cc3 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 13 Sep 2023 10:27:53 +0100 Subject: [PATCH 10/10] new -> try_new --- src/algorithm/nest_cfgs.rs | 2 +- src/hugr/validate.rs | 4 ++-- src/hugr/views.rs | 2 +- src/hugr/views/descendants.rs | 6 +++--- src/hugr/views/sibling.rs | 15 ++++++++------- src/hugr/views/sibling_subgraph.rs | 20 ++++++++++---------- 6 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/algorithm/nest_cfgs.rs b/src/algorithm/nest_cfgs.rs index 9de39e158..50f2a4c9c 100644 --- a/src/algorithm/nest_cfgs.rs +++ b/src/algorithm/nest_cfgs.rs @@ -449,7 +449,7 @@ pub(crate) mod test { let (split, merge, head, tail) = (split.node(), merge.node(), head.node(), tail.node()); // There's no need to use a FlatRegionView here but we do so just to check // that we *can* (as we'll need to for "real" module Hugr's). - let v: SiblingGraph = SiblingGraph::new(&h, h.root()).unwrap(); + let v: SiblingGraph = SiblingGraph::try_new(&h, h.root()).unwrap(); let edge_classes = EdgeClassifier::get_edge_classes(&SimpleCfgView::new(&v)); let [&left, &right] = edge_classes .keys() diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index 74912dcba..bba2b2f3d 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -100,7 +100,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { /// The results of this computation should be cached in `self.dominators`. /// We don't do it here to avoid mutable borrows. fn compute_dominator(&self, parent: Node) -> Dominators { - let region: SiblingGraph = SiblingGraph::new(self.hugr, parent).unwrap(); + let region: SiblingGraph = SiblingGraph::try_new(self.hugr, parent).unwrap(); let entry_node = self.hugr.children(parent).next().unwrap(); dominators::simple_fast(®ion.as_petgraph(), entry_node) } @@ -374,7 +374,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { return Ok(()); }; - let region: SiblingGraph = SiblingGraph::new(self.hugr, parent).unwrap(); + let region: SiblingGraph = SiblingGraph::try_new(self.hugr, parent).unwrap(); let postorder = Topo::new(®ion.as_petgraph()); let nodes_visited = postorder .iter(®ion.as_petgraph()) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index afc808e53..66bf6a7a8 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -300,7 +300,7 @@ pub trait HierarchyView<'a>: HugrView + Sized { /// /// # Errors /// Returns [`HugrError::InvalidNode`] if the root isn't a node of the required [OpTag] - fn new(hugr: &'a impl HugrView, root: Node) -> Result; + fn try_new(hugr: &'a impl HugrView, root: Node) -> Result; } impl HugrView for T diff --git a/src/hugr/views/descendants.rs b/src/hugr/views/descendants.rs index 13ec68dce..be1382286 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -165,7 +165,7 @@ impl<'a, Root> HierarchyView<'a> for DescendantsGraph<'a, Root> where Root: NodeHandle, { - fn new(hugr: &'a impl HugrView, root: Node) -> Result { + fn try_new(hugr: &'a impl HugrView, root: Node) -> Result { hugr.valid_node(root)?; let root_tag = hugr.get_optype(root).tag(); if !Root::TAG.is_superset(root_tag) { @@ -257,7 +257,7 @@ pub(super) mod test { fn full_region() -> Result<(), Box> { let (hugr, def, inner) = make_module_hgr()?; - let region: DescendantsGraph = DescendantsGraph::new(&hugr, def)?; + let region: DescendantsGraph = DescendantsGraph::try_new(&hugr, def)?; assert_eq!(region.node_count(), 7); assert!(region.nodes().all(|n| n == def @@ -269,7 +269,7 @@ pub(super) mod test { region.get_function_type(), Some(&FunctionType::new(type_row![NAT, QB], type_row![NAT, QB])) ); - let inner_region: DescendantsGraph = DescendantsGraph::new(&hugr, inner)?; + let inner_region: DescendantsGraph = DescendantsGraph::try_new(&hugr, inner)?; assert_eq!( inner_region.get_function_type(), Some(&FunctionType::new(type_row![NAT], type_row![NAT])) diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index 0ba04e981..5287ec8d4 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -178,7 +178,7 @@ impl<'a, Root> HierarchyView<'a> for SiblingGraph<'a, Root> where Root: NodeHandle, { - fn new(hugr: &'a impl HugrView, root: Node) -> Result { + fn try_new(hugr: &'a impl HugrView, root: Node) -> Result { hugr.valid_node(root)?; if !Root::TAG.is_superset(hugr.get_optype(root).tag()) { return Err(HugrError::InvalidNode(root)); @@ -231,7 +231,7 @@ mod test { fn flat_region() -> Result<(), Box> { let (hugr, def, inner) = make_module_hgr()?; - let region: SiblingGraph = SiblingGraph::new(&hugr, def)?; + let region: SiblingGraph = SiblingGraph::try_new(&hugr, def)?; assert_eq!(region.node_count(), 5); assert!(region @@ -255,11 +255,11 @@ mod test { let h = module_builder.finish_hugr(&PRELUDE_REGISTRY)?; let sub_dfg = sub_dfg.node(); // Can create a view from a child or grandchild of a hugr: - let dfg_view: SiblingGraph<'_, DfgID> = SiblingGraph::new(&h, sub_dfg)?; - let fun_view: SiblingGraph<'_, FuncID> = SiblingGraph::new(&h, fun.node())?; + let dfg_view: SiblingGraph<'_, DfgID> = SiblingGraph::try_new(&h, sub_dfg)?; + let fun_view: SiblingGraph<'_, FuncID> = SiblingGraph::try_new(&h, fun.node())?; assert_eq!(fun_view.children(sub_dfg).len(), 0); // And can create a view from a child of another SiblingGraph - let nested_dfg_view: SiblingGraph<'_, DfgID> = SiblingGraph::new(&fun_view, sub_dfg)?; + let nested_dfg_view: SiblingGraph<'_, DfgID> = SiblingGraph::try_new(&fun_view, sub_dfg)?; // Both ways work: let just_io = vec![ @@ -274,9 +274,10 @@ mod test { } // But cannot create a view directly as a grandchild of another SiblingGraph - let root_view: SiblingGraph<'_, ModuleRootID> = SiblingGraph::new(&h, h.root()).unwrap(); + let root_view: SiblingGraph<'_, ModuleRootID> = + SiblingGraph::try_new(&h, h.root()).unwrap(); assert_eq!( - SiblingGraph::<'_, DfgID>::new(&root_view, sub_dfg.node()).err(), + SiblingGraph::<'_, DfgID>::try_new(&root_view, sub_dfg.node()).err(), Some(HugrError::InvalidNode(sub_dfg.node())) ); diff --git a/src/hugr/views/sibling_subgraph.rs b/src/hugr/views/sibling_subgraph.rs index 69991150f..2390264be 100644 --- a/src/hugr/views/sibling_subgraph.rs +++ b/src/hugr/views/sibling_subgraph.rs @@ -639,9 +639,9 @@ mod tests { #[test] fn construct_subgraph() -> Result<(), InvalidSubgraph> { let (hugr, func_root) = build_hugr().unwrap(); - let sibling_graph: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); + let sibling_graph: SiblingGraph<'_> = SiblingGraph::try_new(&hugr, func_root).unwrap(); let from_root = SiblingSubgraph::from_sibling_graph(&sibling_graph)?; - let region: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); + let region: SiblingGraph<'_> = SiblingGraph::try_new(&hugr, func_root).unwrap(); let from_region = SiblingSubgraph::from_sibling_graph(®ion)?; assert_eq!( from_root.get_parent(&sibling_graph), @@ -657,7 +657,7 @@ mod tests { #[test] fn construct_simple_replacement() -> Result<(), InvalidSubgraph> { let (mut hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, func_root).unwrap(); + let func: SiblingGraph<'_, FuncID> = SiblingGraph::try_new(&hugr, func_root).unwrap(); let sub = SiblingSubgraph::try_new_dataflow_subgraph(&func)?; let empty_dfg = { @@ -680,7 +680,7 @@ mod tests { #[test] fn test_signature() -> Result<(), InvalidSubgraph> { let (hugr, dfg) = build_hugr().unwrap(); - let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, dfg).unwrap(); + let func: SiblingGraph<'_, FuncID> = SiblingGraph::try_new(&hugr, dfg).unwrap(); let sub = SiblingSubgraph::try_new_dataflow_subgraph(&func)?; assert_eq!( sub.signature(&func), @@ -692,7 +692,7 @@ mod tests { #[test] fn construct_simple_replacement_invalid_signature() -> Result<(), InvalidSubgraph> { let (hugr, dfg) = build_hugr().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, dfg).unwrap(); + let func: SiblingGraph<'_> = SiblingGraph::try_new(&hugr, dfg).unwrap(); let sub = SiblingSubgraph::from_sibling_graph(&func)?; let empty_dfg = { @@ -711,7 +711,7 @@ mod tests { #[test] fn convex_subgraph() { let (hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_, FuncID> = SiblingGraph::new(&hugr, func_root).unwrap(); + let func: SiblingGraph<'_, FuncID> = SiblingGraph::try_new(&hugr, func_root).unwrap(); assert_eq!( SiblingSubgraph::try_new_dataflow_subgraph(&func) .unwrap() @@ -725,7 +725,7 @@ mod tests { fn convex_subgraph_2() { let (hugr, func_root) = build_hugr().unwrap(); let (inp, out) = hugr.children(func_root).take(2).collect_tuple().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); + let func: SiblingGraph<'_> = SiblingGraph::try_new(&hugr, func_root).unwrap(); // All graph except input/output nodes SiblingSubgraph::try_new( hugr.node_outputs(inp) @@ -743,7 +743,7 @@ mod tests { #[test] fn degen_boundary() { let (hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); + let func: SiblingGraph<'_> = SiblingGraph::try_new(&hugr, func_root).unwrap(); let (inp, _) = hugr.children(func_root).take(2).collect_tuple().unwrap(); let first_cx_edge = hugr.node_outputs(inp).next().unwrap(); // All graph but one edge @@ -760,7 +760,7 @@ mod tests { #[test] fn non_convex_subgraph() { let (hugr, func_root) = build_hugr().unwrap(); - let func: SiblingGraph<'_> = SiblingGraph::new(&hugr, func_root).unwrap(); + let func: SiblingGraph<'_> = SiblingGraph::try_new(&hugr, func_root).unwrap(); let (inp, out) = hugr.children(func_root).take(2).collect_tuple().unwrap(); let first_cx_edge = hugr.node_outputs(inp).next().unwrap(); let snd_cx_edge = hugr.node_inputs(out).next().unwrap(); @@ -779,7 +779,7 @@ mod tests { fn preserve_signature() { let (hugr, func_root) = build_hugr_classical().unwrap(); let func_graph: SiblingGraph<'_, FuncID> = - SiblingGraph::new(&hugr, func_root).unwrap(); + SiblingGraph::try_new(&hugr, func_root).unwrap(); let func = SiblingSubgraph::try_new_dataflow_subgraph(&func_graph).unwrap(); let OpType::FuncDefn(func_defn) = hugr.get_optype(func_root) else { panic!()