diff --git a/src/algorithm/nest_cfgs.rs b/src/algorithm/nest_cfgs.rs index 9a5d48559..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()); + 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.rs b/src/hugr.rs index 648383562..ee5ba33a9 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/hugrmut.rs b/src/hugr/hugrmut.rs index ca3e95084..663f51988 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -322,30 +322,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), - } - } - /// Set the number of ports on a node. This may invalidate the node's `PortIndex`. fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) { self.valid_node(node).unwrap_or_else(|e| panic!("{}", e)); diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index 9db0a4f7b..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); + 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); + 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 cb66167e5..66bf6a7a8 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, DEFAULT_NODETYPE}; use crate::ops::handle::NodeHandle; use crate::ops::{FuncDecl, FuncDefn, OpName, OpTag, OpType, DFG}; use crate::types::{EdgeKind, FunctionType}; @@ -80,17 +80,63 @@ 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; + #[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 { + match self.contains_node(node) { + true => self.base_hugr().metadata.get(node.index), + false => &NodeMetadata::Null, + } + } /// Returns the number of nodes in the hugr. fn node_count(&self) -> usize; @@ -249,12 +295,12 @@ 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; - +pub trait HierarchyView<'a>: HugrView + Sized { /// Create a hierarchical view of a HUGR given a root node. - fn new(hugr: &'a Self::Base, root: Node) -> Self; + /// + /// # Errors + /// Returns [`HugrError::InvalidNode`] if the root isn't a node of the required [OpTag] + fn try_new(hugr: &'a impl HugrView, root: Node) -> Result; } impl HugrView for T @@ -287,21 +333,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() @@ -386,11 +417,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..be1382286 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -5,11 +5,12 @@ 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::{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>; @@ -25,10 +26,8 @@ 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, -{ +#[derive(Clone)] +pub struct DescendantsGraph<'g, Root = Node> { /// The chosen root node. root: Node, @@ -36,26 +35,15 @@ 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> -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; @@ -94,29 +82,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() @@ -196,36 +161,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 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) { - // TODO: Return an error - panic!("Root node must have the correct operation type tag.") + return Err(HugrError::InvalidNode(root)); } - Self { + let hugr = hugr.base_hugr(); + Ok(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; @@ -236,7 +194,7 @@ where #[inline] fn base_hugr(&self) -> &Hugr { - self.hugr.base_hugr() + self.hugr } #[inline] @@ -299,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 @@ -311,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 d2caf509d..5287ec8d4 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -6,11 +6,12 @@ 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::{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>; @@ -25,37 +26,24 @@ 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, -{ +#[derive(Clone)] +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, + /// The underlying Hugr onto which this view is a filter + hugr: &'g Hugr, /// The operation type of the root node. _phantom: std::marker::PhantomData, } -impl<'g, Root, Base> Clone for SiblingGraph<'g, Root, Base> -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; @@ -94,26 +82,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 @@ -206,36 +174,28 @@ 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 { - 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 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)); } - Self { + let hugr = hugr.base_hugr(); + Ok(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; @@ -246,7 +206,7 @@ where #[inline] fn base_hugr(&self) -> &Hugr { - self.hugr.base_hugr() + self.hugr } #[inline] @@ -257,6 +217,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::*; @@ -264,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 @@ -274,4 +241,46 @@ 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::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::try_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::try_new(&h, h.root()).unwrap(); + assert_eq!( + SiblingGraph::<'_, DfgID>::try_new(&root_view, sub_dfg.node()).err(), + Some(HugrError::InvalidNode(sub_dfg.node())) + ); + + Ok(()) + } } diff --git a/src/hugr/views/sibling_subgraph.rs b/src/hugr/views/sibling_subgraph.rs index a48ca2978..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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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(); @@ -778,7 +778,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::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!() 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 } }