From 4bc534cda924c5f5b7111b882b959580391dfe03 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 24 Jul 2023 14:55:06 +0100 Subject: [PATCH 01/18] [trivial][refactor]Combine identical impl blocks for BlockBuilder --- src/builder/cfg.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 5d7188d57..38edc730f 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -256,8 +256,7 @@ impl + AsRef> BlockBuilder { let db = DFGBuilder::create_with_io(base, block_n, signature)?; Ok(BlockBuilder::from_dfg_builder(db)) } -} -impl + AsRef> BlockBuilder { + /// [Set outputs](BlockBuilder::set_outputs) and [finish](`BlockBuilder::finish_sub_container`). pub fn finish_with_outputs( mut self, From 5dcb6c777fcd147f37bd9b380d4e554638e9aef7 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 24 Jul 2023 14:56:05 +0100 Subject: [PATCH 02/18] [trivial][refactor]Combine identical impl blocks for TailLoopBuilder --- src/builder/tail_loop.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index c109b158e..81c036287 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -52,9 +52,7 @@ impl + AsRef> TailLoopBuilder { pub fn internal_output_row(&self) -> Result { self.loop_signature().map(ops::TailLoop::body_output_row) } -} -impl + AsRef> TailLoopBuilder { /// Set outputs and finish, see [`TailLoopBuilder::set_outputs`] pub fn finish_with_outputs( mut self, From 1dd1f1f690d8bfb95a35732d296dc5944dc79fac Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 18 Jul 2023 16:04:24 +0100 Subject: [PATCH 03/18] Add Container::Base{Mut,View}, define as &'a (mut) Hugr - build_traits broken --- src/builder/build_traits.rs | 6 ++++-- src/builder/cfg.rs | 2 ++ src/builder/conditional.rs | 3 +++ src/builder/dataflow.rs | 4 ++++ src/builder/module.rs | 2 ++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index 437e52d2e..d3a0d5b52 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -34,12 +34,14 @@ use crate::hugr::HugrMut; /// Implementations of this trait allow the child sibling graph to be added to /// the HUGR. pub trait Container { + type BaseMut<'a>: HugrMut where Self: 'a; + type BaseView<'a>: HugrView where Self: 'a; /// The container node. fn container_node(&self) -> Node; /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> &mut Hugr; + fn hugr_mut(&mut self) -> Self::BaseMut<'_>; /// Immutable reference to HUGR being built - fn hugr(&self) -> &Hugr; + fn hugr(&self) -> Self::BaseView<'_>; /// Add an [`OpType`] as the final child of the container. fn add_child_op(&mut self, op: impl Into) -> Result { let parent = self.container_node(); diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 38edc730f..b849b07f3 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -28,6 +28,8 @@ pub struct CFGBuilder { } impl + AsRef> Container for CFGBuilder { + type BaseMut<'a> = &'a mut Hugr where B: 'a; + type BaseView<'a> = &'a Hugr where B: 'a; #[inline] fn container_node(&self) -> Node { self.cfg_node diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index 38c7d7b16..cff7f3538 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -49,6 +49,9 @@ pub struct ConditionalBuilder { } impl + AsRef> Container for ConditionalBuilder { + type BaseMut<'a> = &'a mut Hugr where T: 'a; + type BaseView<'a> = &'a Hugr where T: 'a; + #[inline] fn container_node(&self) -> Node { self.conditional_node diff --git a/src/builder/dataflow.rs b/src/builder/dataflow.rs index 690932c2b..dd0980454 100644 --- a/src/builder/dataflow.rs +++ b/src/builder/dataflow.rs @@ -83,6 +83,8 @@ impl HugrBuilder for DFGBuilder { } impl + AsRef> Container for DFGBuilder { + type BaseMut<'a> = &'a mut Hugr where T: 'a; + type BaseView<'a> = &'a Hugr where T: 'a; #[inline] fn container_node(&self) -> Node { self.dfg_node @@ -148,6 +150,8 @@ impl FunctionBuilder { } impl + AsRef, T> Container for DFGWrapper { + type BaseMut<'a> = &'a mut Hugr where B: 'a, T: 'a; + type BaseView<'a> = &'a Hugr where B: 'a, T: 'a; #[inline] fn container_node(&self) -> Node { self.0.container_node() diff --git a/src/builder/module.rs b/src/builder/module.rs index 8c7acb28f..133467a0a 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -25,6 +25,8 @@ use crate::{hugr::HugrMut, Hugr}; pub struct ModuleBuilder(pub(super) T); impl + AsRef> Container for ModuleBuilder { + type BaseMut<'a> = &'a mut Hugr where T: 'a; + type BaseView<'a> = &'a Hugr where T: 'a; #[inline] fn container_node(&self) -> Node { self.0.as_ref().root() From 51701ccc615dc51b84bd00d8d288dfacba04af81 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 18 Jul 2023 18:09:05 +0100 Subject: [PATCH 04/18] WIP (changing region.rs - but needs impl of HugrView that view.rs doesn't provide) --- src/builder/cfg.rs | 34 ++++++++++---- src/hugr/hugrmut.rs | 106 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 119 insertions(+), 21 deletions(-) diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index b849b07f3..d5937e027 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -27,26 +27,26 @@ pub struct CFGBuilder { pub(super) n_out_wires: usize, } -impl + AsRef> Container for CFGBuilder { - type BaseMut<'a> = &'a mut Hugr where B: 'a; - type BaseView<'a> = &'a Hugr where B: 'a; +impl Container for CFGBuilder<&mut B> { + type BaseMut<'a> = &'a mut B where Self: 'a, B: 'a; + type BaseView<'a> = &'a B where Self: 'a, B: 'a; #[inline] fn container_node(&self) -> Node { self.cfg_node } #[inline] - fn hugr_mut(&mut self) -> &mut Hugr { - self.base.as_mut() + fn hugr_mut(&mut self) -> &mut B { + self.base } #[inline] - fn hugr(&self) -> &Hugr { - self.base.as_ref() + fn hugr(&self) -> &B { + self.base } } -impl + AsRef> SubContainer for CFGBuilder { +impl SubContainer for CFGBuilder<&mut H> { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -70,6 +70,24 @@ impl CFGBuilder { } } +impl Container for CFGBuilder { + type BaseMut<'a> = &'a mut Hugr where Self: 'a; + + type BaseView<'a> = &'a Hugr where Self: 'a; + + fn container_node(&self) -> Node { + self.cfg_node + } + + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + &mut self.base + } + + fn hugr(&self) -> Self::BaseView<'_> { + &self.base + } +} + impl HugrBuilder for CFGBuilder { fn finish_hugr(self) -> Result { self.base.validate()?; diff --git a/src/hugr/hugrmut.rs b/src/hugr/hugrmut.rs index 35bf268fc..f5570edf5 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -12,7 +12,7 @@ use crate::{Hugr, Port}; use super::NodeMetadata; /// Functions for low-level building of a HUGR. (Or, in the future, a subregion thereof) -pub(crate) trait HugrMut { +pub(crate) trait HugrMut: HugrView { /// Add a node to the graph. fn add_op(&mut self, op: impl Into) -> Node; @@ -144,17 +144,14 @@ pub(crate) trait HugrMut { fn canonicalize_nodes(&mut self, rekey: impl FnMut(Node, Node)); } -impl HugrMut for T -where - T: AsRef + AsMut, +impl HugrMut for Hugr { fn add_op(&mut self, op: impl Into) -> Node { let op: OpType = op.into(); let node = self - .as_mut() .graph .add_node(op.input_count(), op.output_count()); - self.as_mut().op_types[node] = op; + self.op_types[node] = op; node.into() } @@ -163,14 +160,14 @@ where // TODO: Add a HugrMutError ? panic!("cannot remove root node"); } - self.as_mut().hierarchy.remove(node.index); - self.as_mut().graph.remove_node(node.index); - self.as_mut().op_types.remove(node.index); + self.hierarchy.remove(node.index); + self.graph.remove_node(node.index); + self.op_types.remove(node.index); Ok(()) } fn get_metadata_mut(&mut self, node: Node) -> &mut NodeMetadata { - self.as_mut().metadata.get_mut(node.index) + self.metadata.get_mut(node.index) } fn connect( @@ -180,15 +177,14 @@ where dst: Node, dst_port: usize, ) -> Result<(), HugrError> { - self.as_mut() - .graph + self.graph .link_nodes(src.index, src_port, dst.index, dst_port)?; Ok(()) } fn disconnect(&mut self, node: Node, port: Port) -> Result<(), HugrError> { let offset = port.offset; - let port = self.as_mut().graph.port_index(node.index, offset).ok_or( + let port = self.graph.port_index(node.index, offset).ok_or( portgraph::LinkError::UnknownOffset { node: node.index, offset, @@ -353,6 +349,90 @@ where } } +impl HugrMut for &mut T { + fn add_op(&mut self, op: impl Into) -> Node { + (*self).add_op(op) + } + + fn remove_node(&mut self, node: Node) -> Result<(), HugrError> { + (*self).remove_node(node) + } + + fn get_metadata_mut(&mut self, node: Node) -> &mut NodeMetadata { + (*self).get_metadata_mut(node) + } + + fn connect( + &mut self, + src: Node, + src_port: usize, + dst: Node, + dst_port: usize, + ) -> Result<(), HugrError> { + (*self).connect(src, src_port, dst, dst_port) + } + + fn disconnect(&mut self, node: Node, port: Port) -> Result<(), HugrError> { + (*self).disconnect(node, port) + } + + fn add_other_edge(&mut self, src: Node, dst: Node) -> Result<(Port, Port), HugrError> { + (*self).add_other_edge(src, dst) + } + + fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) { + (*self).set_num_ports(node, incoming, outgoing) + } + + fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range { + (*self).add_ports(node, direction, amount) + } + + fn set_parent(&mut self, node: Node, parent: Node) -> Result<(), HugrError> { + (*self).set_parent(node, parent) + } + + fn move_after_sibling(&mut self, node: Node, after: Node) -> Result<(), HugrError> { + (*self).move_after_sibling(node, after) + } + + fn move_before_sibling(&mut self, node: Node, before: Node) -> Result<(), HugrError> { + (*self).move_before_sibling(node, before) + } + + fn add_op_with_parent( + &mut self, + parent: Node, + op: impl Into, + ) -> Result { + (*self).add_op_with_parent(parent, op) + } + + fn add_op_before(&mut self, sibling: Node, op: impl Into) -> Result { + (*self).add_op_before(sibling, op) + } + + fn add_op_after(&mut self, sibling: Node, op: impl Into) -> Result { + (*self).add_op_after(sibling, op) + } + + fn replace_op(&mut self, node: Node, op: impl Into) -> OpType { + (*self).replace_op(node, op) + } + + fn insert_hugr(&mut self, root: Node, other: Hugr) -> Result { + (*self).insert_hugr(root, other) + } + + fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> Result { + (*self).insert_from_view(root, other) + } + + fn canonicalize_nodes(&mut self, rekey: impl FnMut(Node, Node)) { + (*self).canonicalize_nodes(rekey) + } +} + /// Internal implementation of `insert_hugr` and `insert_view` methods for /// AsMut. /// From 65e02f1433062802790806d133500069a46d0a21 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 24 Jul 2023 15:02:00 +0100 Subject: [PATCH 05/18] Expose HugrMut; add pub trait Buildable to parametrize all Builder classes --- src/algorithm/nest_cfgs.rs | 12 ++- src/builder.rs | 2 +- src/builder/build_traits.rs | 77 ++++++++++---- src/builder/cfg.rs | 76 ++++++-------- src/builder/conditional.rs | 28 +++--- src/builder/dataflow.rs | 40 ++++---- src/builder/module.rs | 22 ++-- src/builder/tail_loop.rs | 10 +- src/hugr/hugrmut.rs | 9 +- src/hugr/view.rs | 193 ++++++++++++++++++++++++++++++++++-- 10 files changed, 331 insertions(+), 138 deletions(-) diff --git a/src/algorithm/nest_cfgs.rs b/src/algorithm/nest_cfgs.rs index 80b4ee8c6..3735bd7f7 100644 --- a/src/algorithm/nest_cfgs.rs +++ b/src/algorithm/nest_cfgs.rs @@ -397,7 +397,9 @@ impl EdgeClassifier { #[cfg(test)] pub(crate) mod test { use super::*; - use crate::builder::{BuildError, CFGBuilder, Container, DataflowSubContainer, HugrBuilder}; + use crate::builder::{ + BuildError, Buildable, CFGBuilder, Container, DataflowSubContainer, HugrBuilder, + }; use crate::hugr::region::{FlatRegionView, Region}; use crate::ops::{ handle::{BasicBlockID, ConstID, NodeHandle}, @@ -577,7 +579,7 @@ pub(crate) mod test { dataflow_builder.finish_with_outputs([u].into_iter().chain(w)) } - fn build_if_then_else_merge + AsRef>( + fn build_if_then_else_merge( cfg: &mut CFGBuilder, const_pred: &ConstID, unit_const: &ConstID, @@ -590,7 +592,7 @@ pub(crate) mod test { Ok((split, merge)) } - fn build_then_else_merge_from_if + AsRef>( + fn build_then_else_merge_from_if( cfg: &mut CFGBuilder, unit_const: &ConstID, split: BasicBlockID, @@ -615,7 +617,7 @@ pub(crate) mod test { } // Returns loop tail - caller must link header to tail, and provide 0th successor of tail - fn build_loop_from_header + AsRef>( + fn build_loop_from_header( cfg: &mut CFGBuilder, const_pred: &ConstID, header: BasicBlockID, @@ -629,7 +631,7 @@ pub(crate) mod test { } // Result is header and tail. Caller must provide 0th successor of header (linking to tail), and 0th successor of tail. - fn build_loop + AsRef>( + fn build_loop( cfg: &mut CFGBuilder, const_pred: &ConstID, unit_const: &ConstID, diff --git a/src/builder.rs b/src/builder.rs index 910c3dd30..51fffd03c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -11,7 +11,7 @@ pub use handle::BuildHandle; mod build_traits; pub use build_traits::{ - Container, Dataflow, DataflowHugr, DataflowSubContainer, HugrBuilder, SubContainer, + Buildable, Container, Dataflow, DataflowHugr, DataflowSubContainer, HugrBuilder, SubContainer, }; mod dataflow; diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index d3a0d5b52..f9639ddc0 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -29,19 +29,59 @@ use crate::Hugr; use crate::hugr::HugrMut; +pub trait Buildable: HugrMut { + type BaseMut<'a>: Buildable + where + Self: 'a; + type BaseView<'a>: HugrView + where + Self: 'a; + /// The underlying [`Hugr`] being built + fn hugr_mut(&mut self) -> Self::BaseMut<'_>; + /// Immutable reference to HUGR being built + fn hugr(&self) -> Self::BaseView<'_>; +} + +impl Buildable for Hugr { + type BaseMut<'a> = &'a mut Hugr where Self: 'a; + + type BaseView<'a> = &'a Hugr where Self: 'a; + + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + self + } + + fn hugr(&self) -> Self::BaseView<'_> { + &self + } +} + +impl Buildable for &mut H { + type BaseMut<'a> = &'a mut H where Self: 'a; + + type BaseView<'a> = &'a H where Self: 'a; + + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + self + } + + fn hugr(&self) -> Self::BaseView<'_> { + &self + } +} + /// Trait for HUGR container builders. /// Containers are nodes that are parents of sibling graphs. /// Implementations of this trait allow the child sibling graph to be added to /// the HUGR. pub trait Container { - type BaseMut<'a>: HugrMut where Self: 'a; - type BaseView<'a>: HugrView where Self: 'a; + type Base: Buildable; /// The container node. fn container_node(&self) -> Node; /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> Self::BaseMut<'_>; + fn hugr_mut(&mut self) -> ::BaseMut<'_>; /// Immutable reference to HUGR being built - fn hugr(&self) -> Self::BaseView<'_>; + fn hugr(&self) -> ::BaseView<'_>; /// Add an [`OpType`] as the final child of the container. fn add_child_op(&mut self, op: impl Into) -> Result { let parent = self.container_node(); @@ -81,7 +121,7 @@ pub trait Container { &mut self, name: impl Into, signature: Signature, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let f_node = self.add_child_op(ops::FuncDefn { name: name.into(), signature: signature.clone(), @@ -254,7 +294,7 @@ pub trait Dataflow: Container { &mut self, signature: Signature, input_wires: impl IntoIterator, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let (dfg_n, _) = add_op_with_wires( self, ops::DFG { @@ -280,7 +320,7 @@ pub trait Dataflow: Container { &mut self, inputs: impl IntoIterator, output_types: TypeRow, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let (input_types, input_wires): (Vec, Vec) = inputs.into_iter().unzip(); let inputs: TypeRow = input_types.into(); @@ -339,7 +379,7 @@ pub trait Dataflow: Container { just_inputs: impl IntoIterator, inputs_outputs: impl IntoIterator, just_out_types: TypeRow, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let (input_types, mut input_wires): (Vec, Vec) = just_inputs.into_iter().unzip(); let (rest_types, rest_input_wires): (Vec, Vec) = @@ -373,7 +413,7 @@ pub trait Dataflow: Container { (predicate_inputs, predicate_wire): (impl IntoIterator, Wire), other_inputs: impl IntoIterator, output_types: TypeRow, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let mut input_wires = vec![predicate_wire]; let (input_types, rest_input_wires): (Vec, Vec) = other_inputs.into_iter().unzip(); @@ -528,9 +568,7 @@ pub trait Dataflow: Container { function: &FuncID, input_wires: impl IntoIterator, ) -> Result, BuildError> { - let hugr = self.hugr(); - let def_op = hugr.get_optype(function.node()); - let signature = match def_op { + let signature = match self.hugr().get_optype(function.node()) { OpType::FuncDefn(ops::FuncDefn { signature, .. }) | OpType::FuncDecl(ops::FuncDecl { signature, .. }) => signature.clone(), _ => { @@ -542,7 +580,7 @@ pub trait Dataflow: Container { }; let const_in_port = signature.output.len(); let op_id = self.add_dataflow_op(ops::Call { signature }, input_wires)?; - let src_port = self.hugr_mut().num_outputs(function.node()) - 1; + let src_port = self.hugr().num_outputs(function.node()) - 1; self.hugr_mut() .connect(function.node(), src_port, op_id.node(), const_in_port)?; @@ -588,9 +626,10 @@ fn wire_up_inputs( dst_port, )?; } - let base = data_builder.hugr_mut(); + let base = data_builder.hugr(); let op = base.get_optype(op_node); let some_df_outputs = !op.signature().output.is_empty(); + drop(base); if !any_local_df_inputs && some_df_outputs { // If op has no inputs add a StateOrder edge from input to place in // causal cone of Input node @@ -607,7 +646,7 @@ fn wire_up( dst: Node, dst_port: usize, ) -> Result { - let base = data_builder.hugr_mut(); + let mut base = data_builder.hugr_mut(); let src_offset = Port::new_outgoing(src_port); let src_parent = base.get_parent(src); @@ -654,14 +693,10 @@ fn wire_up( } } - data_builder - .hugr_mut() - .connect(src, src_port, dst, dst_port)?; + base.connect(src, src_port, dst, dst_port)?; Ok(local_source && matches!( - data_builder - .hugr_mut() - .get_optype(dst) + base.get_optype(dst) .port_kind(Port::new_incoming(dst_port)) .unwrap(), EdgeKind::Value(_) diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index d5937e027..45daa1272 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use super::{ - build_traits::SubContainer, + build_traits::{Buildable, SubContainer}, dataflow::{DFGBuilder, DFGWrapper}, handle::BuildHandle, BasicBlockID, BuildError, CfgID, Container, Dataflow, HugrBuilder, Wire, @@ -27,26 +27,25 @@ pub struct CFGBuilder { pub(super) n_out_wires: usize, } -impl Container for CFGBuilder<&mut B> { - type BaseMut<'a> = &'a mut B where Self: 'a, B: 'a; - type BaseView<'a> = &'a B where Self: 'a, B: 'a; +impl Container for CFGBuilder { + type Base = B; #[inline] fn container_node(&self) -> Node { self.cfg_node } #[inline] - fn hugr_mut(&mut self) -> &mut B { - self.base + fn hugr_mut(&mut self) -> B::BaseMut<'_> { + self.base.hugr_mut() } #[inline] - fn hugr(&self) -> &B { - self.base + fn hugr(&self) -> B::BaseView<'_> { + self.base.hugr() } } -impl SubContainer for CFGBuilder<&mut H> { +impl SubContainer for CFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -70,24 +69,6 @@ impl CFGBuilder { } } -impl Container for CFGBuilder { - type BaseMut<'a> = &'a mut Hugr where Self: 'a; - - type BaseView<'a> = &'a Hugr where Self: 'a; - - fn container_node(&self) -> Node { - self.cfg_node - } - - fn hugr_mut(&mut self) -> Self::BaseMut<'_> { - &mut self.base - } - - fn hugr(&self) -> Self::BaseView<'_> { - &self.base - } -} - impl HugrBuilder for CFGBuilder { fn finish_hugr(self) -> Result { self.base.validate()?; @@ -95,7 +76,7 @@ impl HugrBuilder for CFGBuilder { } } -impl + AsRef> CFGBuilder { +impl CFGBuilder { pub(super) fn create( mut base: B, cfg_node: Node, @@ -107,7 +88,7 @@ impl + AsRef> CFGBuilder { cfg_outputs: output, }); let exit_node = base - .as_mut() + .hugr_mut() .add_op_with_parent(cfg_node, exit_block_type)?; Ok(Self { base, @@ -145,7 +126,8 @@ impl + AsRef> CFGBuilder { inputs: TypeRow, predicate_variants: Vec, other_outputs: TypeRow, - ) -> Result, BuildError> { + ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + { self.any_block_builder(inputs, predicate_variants, other_outputs, false) } @@ -155,7 +137,8 @@ impl + AsRef> CFGBuilder { predicate_variants: Vec, other_outputs: TypeRow, entry: bool, - ) -> Result, BuildError> { + ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + { let op = OpType::BasicBlock(BasicBlock::DFB { inputs: inputs.clone(), other_outputs: other_outputs.clone(), @@ -189,7 +172,8 @@ impl + AsRef> CFGBuilder { inputs: TypeRow, outputs: TypeRow, n_cases: usize, - ) -> Result, BuildError> { + ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + { self.block_builder(inputs, vec![type_row![]; n_cases], outputs) } @@ -204,9 +188,9 @@ impl + AsRef> CFGBuilder { &mut self, predicate_variants: Vec, other_outputs: TypeRow, - ) -> Result, BuildError> { - let inputs = self - .inputs + ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + { + let inputs = (&mut self.inputs) .take() .ok_or(BuildError::EntryBuiltError(self.cfg_node))?; self.any_block_builder(inputs, predicate_variants, other_outputs, true) @@ -222,7 +206,8 @@ impl + AsRef> CFGBuilder { &mut self, outputs: TypeRow, n_cases: usize, - ) -> Result, BuildError> { + ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + { self.entry_builder(vec![type_row![]; n_cases], outputs) } @@ -251,7 +236,7 @@ impl + AsRef> CFGBuilder { /// Builder for a [`BasicBlock::DFB`] child graph. pub type BlockBuilder = DFGWrapper; -impl + AsRef> BlockBuilder { +impl BlockBuilder { /// Set the outputs of the block, with `branch_wire` being the value of the /// predicate. `outputs` are the remaining outputs. pub fn set_outputs( @@ -261,6 +246,7 @@ impl + AsRef> BlockBuilder { ) -> Result<(), BuildError> { Dataflow::set_outputs(self, [branch_wire].into_iter().chain(outputs.into_iter())) } + fn create( base: B, block_n: Node, @@ -364,12 +350,13 @@ mod test { build_basic_cfg(&mut cfg_builder)?; let h = cfg_builder.finish_hugr()?; - let mut new_builder = CFGBuilder::from_existing(h.clone(), h.root())?; + let mut h2 = h.clone(); + let mut new_builder = CFGBuilder::from_existing(&mut h2, h.root())?; assert_matches!(new_builder.simple_entry_builder(type_row![NAT], 1), Err(_)); - let h2 = new_builder.finish_hugr()?; + new_builder.finish_sub_container()?; assert_eq!(h, h2); // No new nodes added - let mut new_builder = CFGBuilder::from_existing(h.clone(), h.root())?; + let mut new_builder = CFGBuilder::from_existing(&mut h2, h.root())?; let block_builder = new_builder.simple_block_builder( vec![SimpleType::new_simple_predicate(1), NAT].into(), type_row![NAT], @@ -378,7 +365,7 @@ mod test { let new_bb = block_builder.container_node(); let [pred, nat]: [Wire; 2] = block_builder.input_wires_arr(); block_builder.finish_with_outputs(pred, [nat])?; - let h2 = new_builder.finish_hugr()?; + new_builder.finish_sub_container()?; let expected_nodes = h .children(h.root()) .chain([new_bb]) @@ -388,9 +375,10 @@ mod test { Ok(()) } - fn build_basic_cfg + AsRef>( - cfg_builder: &mut CFGBuilder, - ) -> Result<(), BuildError> { + fn build_basic_cfg(cfg_builder: &mut CFGBuilder) -> Result<(), BuildError> + where + CFGBuilder: Container, + { let sum2_variants = vec![type_row![NAT], type_row![NAT]]; let mut entry_b = cfg_builder.entry_builder(sum2_variants.clone(), type_row![])?; let entry = { diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index cff7f3538..759d3e76f 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -4,7 +4,7 @@ use crate::types::{Signature, TypeRow}; use crate::ops; use crate::ops::handle::CaseID; -use super::build_traits::SubContainer; +use super::build_traits::{Buildable, SubContainer}; use super::handle::BuildHandle; use super::HugrBuilder; use super::{ @@ -48,9 +48,8 @@ pub struct ConditionalBuilder { pub(super) case_nodes: Vec>, } -impl + AsRef> Container for ConditionalBuilder { - type BaseMut<'a> = &'a mut Hugr where T: 'a; - type BaseView<'a> = &'a Hugr where T: 'a; +impl Container for ConditionalBuilder { + type Base = T; #[inline] fn container_node(&self) -> Node { @@ -58,17 +57,17 @@ impl + AsRef> Container for ConditionalBuilder { } #[inline] - fn hugr_mut(&mut self) -> &mut Hugr { - self.base.as_mut() + fn hugr_mut(&mut self) -> ::BaseMut<'_> { + self.base.hugr_mut() } #[inline] - fn hugr(&self) -> &Hugr { - self.base.as_ref() + fn hugr(&self) -> ::BaseView<'_> { + self.base.hugr() } } -impl + AsRef> SubContainer for ConditionalBuilder { +impl SubContainer for ConditionalBuilder { type ContainerHandle = BuildHandle; fn finish_sub_container(self) -> Result { @@ -88,7 +87,7 @@ impl + AsRef> SubContainer for ConditionalBuilder { Ok((self.conditional_node, self.n_out_wires).into()) } } -impl + AsRef> ConditionalBuilder { +impl ConditionalBuilder { /// Return a builder the Case node with index `case`. /// /// # Panics @@ -99,12 +98,15 @@ impl + AsRef> ConditionalBuilder { /// /// This function will return an error if the case has already been built, /// `case` is not a valid index or if there is an error adding nodes. - pub fn case_builder(&mut self, case: usize) -> Result, BuildError> { + pub fn case_builder( + &mut self, + case: usize, + ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + { let conditional = self.conditional_node; - let control_op = self.hugr().get_optype(self.conditional_node); + let control_op = self.hugr().get_optype(self.conditional_node).clone(); let cond: ops::Conditional = control_op - .clone() .try_into() .expect("Parent node does not have Conditional optype."); let inputs = cond diff --git a/src/builder/dataflow.rs b/src/builder/dataflow.rs index dd0980454..e9a0ec416 100644 --- a/src/builder/dataflow.rs +++ b/src/builder/dataflow.rs @@ -1,4 +1,4 @@ -use super::build_traits::{HugrBuilder, SubContainer}; +use super::build_traits::{Buildable, HugrBuilder, SubContainer}; use super::handle::BuildHandle; use super::{BuildError, Container, Dataflow, DfgID, FuncID}; @@ -21,7 +21,7 @@ pub struct DFGBuilder { pub(crate) num_out_wires: usize, } -impl + AsRef> DFGBuilder { +impl DFGBuilder { pub(super) fn create_with_io( mut base: T, parent: Node, @@ -29,14 +29,14 @@ impl + AsRef> DFGBuilder { ) -> Result { let num_in_wires = signature.input.len(); let num_out_wires = signature.output.len(); - base.as_mut().add_op_with_parent( + base.hugr_mut().add_op_with_parent( parent, ops::Input { types: signature.input.clone(), resources: signature.input_resources, }, )?; - base.as_mut().add_op_with_parent( + base.hugr_mut().add_op_with_parent( parent, ops::Output { types: signature.output.clone(), @@ -82,26 +82,25 @@ impl HugrBuilder for DFGBuilder { } } -impl + AsRef> Container for DFGBuilder { - type BaseMut<'a> = &'a mut Hugr where T: 'a; - type BaseView<'a> = &'a Hugr where T: 'a; +impl Container for DFGBuilder { + type Base = B; #[inline] fn container_node(&self) -> Node { self.dfg_node } #[inline] - fn hugr_mut(&mut self) -> &mut Hugr { - self.base.as_mut() + fn hugr_mut(&mut self) -> ::BaseMut<'_> { + self.base.hugr_mut() } #[inline] - fn hugr(&self) -> &Hugr { - self.base.as_ref() + fn hugr(&self) -> ::BaseView<'_> { + self.base.hugr() } } -impl + AsRef> SubContainer for DFGBuilder { +impl SubContainer for DFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -109,7 +108,7 @@ impl + AsRef> SubContainer for DFGBuilder { } } -impl + AsRef> Dataflow for DFGBuilder { +impl Dataflow for DFGBuilder { #[inline] fn num_inputs(&self) -> usize { self.num_in_wires @@ -149,33 +148,32 @@ impl FunctionBuilder { } } -impl + AsRef, T> Container for DFGWrapper { - type BaseMut<'a> = &'a mut Hugr where B: 'a, T: 'a; - type BaseView<'a> = &'a Hugr where B: 'a, T: 'a; +impl Container for DFGWrapper { + type Base = B; #[inline] fn container_node(&self) -> Node { self.0.container_node() } #[inline] - fn hugr_mut(&mut self) -> &mut Hugr { + fn hugr_mut(&mut self) -> ::BaseMut<'_> { self.0.hugr_mut() } #[inline] - fn hugr(&self) -> &Hugr { + fn hugr(&self) -> ::BaseView<'_> { self.0.hugr() } } -impl + AsRef, T> Dataflow for DFGWrapper { +impl Dataflow for DFGWrapper { #[inline] fn num_inputs(&self) -> usize { - self.0.num_inputs() + Dataflow::num_inputs(&self.0) } } -impl + AsRef, T: From>> SubContainer for DFGWrapper { +impl>> SubContainer for DFGWrapper { type ContainerHandle = T; #[inline] diff --git a/src/builder/module.rs b/src/builder/module.rs index 133467a0a..e54a5c3f5 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -1,5 +1,5 @@ use super::{ - build_traits::HugrBuilder, + build_traits::{Buildable, HugrBuilder}, dataflow::{DFGBuilder, FunctionBuilder}, BuildError, Container, }; @@ -24,21 +24,20 @@ use crate::{hugr::HugrMut, Hugr}; #[derive(Debug, Clone, PartialEq)] pub struct ModuleBuilder(pub(super) T); -impl + AsRef> Container for ModuleBuilder { - type BaseMut<'a> = &'a mut Hugr where T: 'a; - type BaseView<'a> = &'a Hugr where T: 'a; +impl Container for ModuleBuilder { + type Base = T; #[inline] fn container_node(&self) -> Node { - self.0.as_ref().root() + self.0.root() } #[inline] - fn hugr_mut(&mut self) -> &mut Hugr { - self.0.as_mut() + fn hugr_mut(&mut self) -> ::BaseMut<'_> { + self.0.hugr_mut() } - fn hugr(&self) -> &Hugr { - self.0.as_ref() + fn hugr(&self) -> ::BaseView<'_> { + self.0.hugr() } } @@ -63,7 +62,7 @@ impl HugrBuilder for ModuleBuilder { } } -impl + AsRef> ModuleBuilder { +impl ModuleBuilder { /// Replace a [`ops::FuncDecl`] with [`ops::FuncDefn`] and return a builder for /// the defining graph. /// @@ -74,7 +73,8 @@ impl + AsRef> ModuleBuilder { pub fn define_declaration( &mut self, f_id: &FuncID, - ) -> Result, BuildError> { + ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + { let f_node = f_id.node(); let (signature, name) = if let OpType::FuncDecl(ops::FuncDecl { signature, name }) = self.hugr().get_optype(f_node) diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index 81c036287..fdadbf7c1 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -4,7 +4,7 @@ use crate::hugr::view::HugrView; use crate::types::{Signature, TypeRow}; use crate::{Hugr, Node}; -use super::build_traits::SubContainer; +use super::build_traits::{Buildable, SubContainer}; use super::handle::BuildHandle; use super::{ dataflow::{DFGBuilder, DFGWrapper}, @@ -14,7 +14,7 @@ use super::{ /// Builder for a [`ops::TailLoop`] node. pub type TailLoopBuilder = DFGWrapper>; -impl + AsRef> TailLoopBuilder { +impl TailLoopBuilder { pub(super) fn create_with_io( base: B, loop_node: Node, @@ -37,9 +37,9 @@ impl + AsRef> TailLoopBuilder { /// Get a reference to the [`ops::TailLoop`] /// that defines the signature of the [`ops::TailLoop`] - pub fn loop_signature(&self) -> Result<&ops::TailLoop, BuildError> { + pub fn loop_signature(&self) -> Result { if let OpType::TailLoop(tail_loop) = self.hugr().get_optype(self.container_node()) { - Ok(tail_loop) + Ok(tail_loop.clone()) } else { Err(BuildError::UnexpectedType { node: self.container_node(), @@ -50,7 +50,7 @@ impl + AsRef> TailLoopBuilder { /// The output types of the child graph, including the predicate as the first. pub fn internal_output_row(&self) -> Result { - self.loop_signature().map(ops::TailLoop::body_output_row) + self.loop_signature().map(|tl| tl.body_output_row()) } /// Set outputs and finish, see [`TailLoopBuilder::set_outputs`] diff --git a/src/hugr/hugrmut.rs b/src/hugr/hugrmut.rs index f5570edf5..14bc32353 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -12,7 +12,7 @@ use crate::{Hugr, Port}; use super::NodeMetadata; /// Functions for low-level building of a HUGR. (Or, in the future, a subregion thereof) -pub(crate) trait HugrMut: HugrView { +pub trait HugrMut: HugrView { /// Add a node to the graph. fn add_op(&mut self, op: impl Into) -> Node; @@ -144,13 +144,10 @@ pub(crate) trait HugrMut: HugrView { fn canonicalize_nodes(&mut self, rekey: impl FnMut(Node, Node)); } -impl HugrMut for Hugr -{ +impl HugrMut for Hugr { fn add_op(&mut self, op: impl Into) -> Node { let op: OpType = op.into(); - let node = self - .graph - .add_node(op.input_count(), op.output_count()); + let node = self.graph.add_node(op.input_count(), op.output_count()); self.op_types[node] = op; node.into() } diff --git a/src/hugr/view.rs b/src/hugr/view.rs index 25a248850..1ce91aa86 100644 --- a/src/hugr/view.rs +++ b/src/hugr/view.rs @@ -188,10 +188,7 @@ pub trait HugrView: sealed::HugrInternals { } } -impl HugrView for T -where - T: AsRef, -{ +impl HugrView for Hugr { /// An Iterator over the nodes in a Hugr(View) type Nodes<'a> = MapInto, Node> where Self: 'a; @@ -290,6 +287,162 @@ where } } +impl HugrView for &T { + type Nodes<'a> = T::Nodes<'a> + where + Self: 'a; + + type NodePorts<'a> = T::NodePorts<'a> + where + Self: 'a; + + type Children<'a> = T::Children<'a> + where + Self: 'a; + + type Neighbours<'a> = T::Neighbours<'a> + where + Self: 'a; + + type PortLinks<'a> = T::PortLinks<'a> + where + Self: 'a; + + fn root(&self) -> Node { + (**self).root() + } + + fn get_parent(&self, node: Node) -> Option { + (**self).get_parent(node) + } + + fn get_optype(&self, node: Node) -> &OpType { + (**self).get_optype(node) + } + + fn get_metadata(&self, node: Node) -> &NodeMetadata { + (**self).get_metadata(node) + } + + fn node_count(&self) -> usize { + (**self).node_count() + } + + fn edge_count(&self) -> usize { + (**self).edge_count() + } + + fn nodes(&self) -> Self::Nodes<'_> { + (**self).nodes() + } + + fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { + (**self).node_ports(node, dir) + } + + fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { + (**self).all_node_ports(node) + } + + fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { + (**self).linked_ports(node, port) + } + + fn num_ports(&self, node: Node, dir: Direction) -> usize { + (**self).num_ports(node, dir) + } + + fn children(&self, node: Node) -> Self::Children<'_> { + (**self).children(node) + } + + fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { + (**self).neighbours(node, dir) + } + + fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { + (**self).all_neighbours(node) + } +} + +impl HugrView for &mut T { + type Nodes<'a> = T::Nodes<'a> + where + Self: 'a; + + type NodePorts<'a> = T::NodePorts<'a> + where + Self: 'a; + + type Children<'a> = T::Children<'a> + where + Self: 'a; + + type Neighbours<'a> = T::Neighbours<'a> + where + Self: 'a; + + type PortLinks<'a> = T::PortLinks<'a> + where + Self: 'a; + + fn root(&self) -> Node { + (**self).root() + } + + fn get_parent(&self, node: Node) -> Option { + (**self).get_parent(node) + } + + fn get_optype(&self, node: Node) -> &OpType { + (**self).get_optype(node) + } + + fn get_metadata(&self, node: Node) -> &NodeMetadata { + (**self).get_metadata(node) + } + + fn node_count(&self) -> usize { + (**self).node_count() + } + + fn edge_count(&self) -> usize { + (**self).edge_count() + } + + fn nodes(&self) -> Self::Nodes<'_> { + (**self).nodes() + } + + fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { + (**self).node_ports(node, dir) + } + + fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { + (**self).all_node_ports(node) + } + + fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { + (**self).linked_ports(node, port) + } + + fn num_ports(&self, node: Node, dir: Direction) -> usize { + (**self).num_ports(node, dir) + } + + fn children(&self, node: Node) -> Self::Children<'_> { + (**self).children(node) + } + + fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { + (**self).neighbours(node, dir) + } + + fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { + (**self).all_neighbours(node) + } +} + pub(crate) mod sealed { use super::*; @@ -308,20 +461,38 @@ pub(crate) mod sealed { fn base_hugr(&self) -> &Hugr; } - impl HugrInternals for T - where - T: AsRef, - { + impl HugrInternals for Hugr { type Portgraph = MultiPortGraph; #[inline] fn portgraph(&self) -> &Self::Portgraph { - &self.as_ref().graph + &self.graph + } + + fn base_hugr(&self) -> &Hugr { + &self + } + } + + impl HugrInternals for &mut T { + type Portgraph = T::Portgraph; + fn portgraph(&self) -> &Self::Portgraph { + (**self).portgraph() + } + + fn base_hugr(&self) -> &Hugr { + (**self).base_hugr() + } + } + + impl HugrInternals for &T { + type Portgraph = T::Portgraph; + fn portgraph(&self) -> &Self::Portgraph { + (**self).portgraph() } - #[inline] fn base_hugr(&self) -> &Hugr { - self.as_ref() + (**self).base_hugr() } } } From e8c0d81c23486f4e78927dfc900c8ab5238ef7b9 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 18 Jul 2023 21:00:35 +0100 Subject: [PATCH 06/18] build_traits.rs: allow missing docs --- src/builder/build_traits.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index f9639ddc0..c2c47abcb 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use crate::hugr::validate::InterGraphEdgeError; use crate::hugr::view::HugrView; use crate::hugr::{Node, NodeMetadata, Port, ValidationError}; From 5e64b0a444c6a69d361540f2ca2aee2d630a669f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 19 Jul 2023 09:15:44 +0100 Subject: [PATCH 07/18] clippy (inc 1 where VSCode was wrong) --- src/builder/build_traits.rs | 4 +-- src/builder/cfg.rs | 3 +- src/builder/tail_loop.rs | 4 +-- src/hugr/hugrmut.rs | 69 +++++++++++++++---------------------- src/hugr/view.rs | 35 +++++++++---------- 5 files changed, 50 insertions(+), 65 deletions(-) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index c2c47abcb..ab83672eb 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -53,7 +53,7 @@ impl Buildable for Hugr { } fn hugr(&self) -> Self::BaseView<'_> { - &self + self } } @@ -67,7 +67,7 @@ impl Buildable for &mut H { } fn hugr(&self) -> Self::BaseView<'_> { - &self + self } } diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 45daa1272..0f4cfe324 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -190,7 +190,8 @@ impl CFGBuilder { other_outputs: TypeRow, ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> { - let inputs = (&mut self.inputs) + let inputs = self + .inputs .take() .ok_or(BuildError::EntryBuiltError(self.cfg_node))?; self.any_block_builder(inputs, predicate_variants, other_outputs, true) diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index fdadbf7c1..7bbf8cb5f 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -109,7 +109,7 @@ mod test { let [i1] = loop_b.input_wires_arr(); let const_wire = loop_b.add_load_const(ConstValue::i64(1))?; - let break_wire = loop_b.make_break(loop_b.loop_signature()?.clone(), [const_wire])?; + let break_wire = loop_b.make_break(loop_b.loop_signature()?, [const_wire])?; loop_b.set_outputs(break_wire, [i1])?; loop_b.finish_hugr() }; @@ -129,7 +129,7 @@ mod test { let loop_id = { let mut loop_b = fbuild.tail_loop_builder(vec![(BIT, b1)], vec![], type_row![NAT])?; - let signature = loop_b.loop_signature()?.clone(); + let signature = loop_b.loop_signature()?; let const_wire = loop_b.add_load_const(ConstValue::true_val())?; let [b1] = loop_b.input_wires_arr(); let conditional_id = { diff --git a/src/hugr/hugrmut.rs b/src/hugr/hugrmut.rs index 14bc32353..42479a0c0 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -153,7 +153,7 @@ impl HugrMut for Hugr { } fn remove_node(&mut self, node: Node) -> Result<(), HugrError> { - if node.index == self.as_ref().root { + if node.index == self.root { // TODO: Add a HugrMutError ? panic!("cannot remove root node"); } @@ -187,7 +187,7 @@ impl HugrMut for Hugr { offset, }, )?; - self.as_mut().graph.unlink_port(port); + self.graph.unlink_port(port); Ok(()) } @@ -206,15 +206,14 @@ impl HugrMut for Hugr { #[inline] fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) { - self.as_mut() - .graph + self.graph .set_num_ports(node.index, incoming, outgoing, |_, _| {}) } #[inline] fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range { - let mut incoming = self.as_mut().graph.num_inputs(node.index); - let mut outgoing = self.as_mut().graph.num_outputs(node.index); + let mut incoming = self.graph.num_inputs(node.index); + let mut outgoing = self.graph.num_outputs(node.index); let increment = |num: &mut usize| { let new = num.saturating_add_signed(amount); let range = *num..new; @@ -225,33 +224,26 @@ impl HugrMut for Hugr { Direction::Incoming => increment(&mut incoming), Direction::Outgoing => increment(&mut outgoing), }; - self.as_mut() - .graph + self.graph .set_num_ports(node.index, incoming, outgoing, |_, _| {}); range } fn set_parent(&mut self, node: Node, parent: Node) -> Result<(), HugrError> { - self.as_mut().hierarchy.detach(node.index); - self.as_mut() - .hierarchy - .push_child(node.index, parent.index)?; + self.hierarchy.detach(node.index); + self.hierarchy.push_child(node.index, parent.index)?; Ok(()) } fn move_after_sibling(&mut self, node: Node, after: Node) -> Result<(), HugrError> { - self.as_mut().hierarchy.detach(node.index); - self.as_mut() - .hierarchy - .insert_after(node.index, after.index)?; + self.hierarchy.detach(node.index); + self.hierarchy.insert_after(node.index, after.index)?; Ok(()) } fn move_before_sibling(&mut self, node: Node, before: Node) -> Result<(), HugrError> { - self.as_mut().hierarchy.detach(node.index); - self.as_mut() - .hierarchy - .insert_before(node.index, before.index)?; + self.hierarchy.detach(node.index); + self.hierarchy.insert_before(node.index, before.index)?; Ok(()) } @@ -261,53 +253,47 @@ impl HugrMut for Hugr { op: impl Into, ) -> Result { let node = self.add_op(op.into()); - self.as_mut() - .hierarchy - .push_child(node.index, parent.index)?; + self.hierarchy.push_child(node.index, parent.index)?; Ok(node) } fn add_op_before(&mut self, sibling: Node, op: impl Into) -> Result { let node = self.add_op(op.into()); - self.as_mut() - .hierarchy - .insert_before(node.index, sibling.index)?; + self.hierarchy.insert_before(node.index, sibling.index)?; Ok(node) } fn add_op_after(&mut self, sibling: Node, op: impl Into) -> Result { let node = self.add_op(op.into()); - self.as_mut() - .hierarchy - .insert_after(node.index, sibling.index)?; + self.hierarchy.insert_after(node.index, sibling.index)?; Ok(node) } fn replace_op(&mut self, node: Node, op: impl Into) -> OpType { - let cur = self.as_mut().op_types.get_mut(node.index); + let cur = self.op_types.get_mut(node.index); std::mem::replace(cur, op.into()) } fn insert_hugr(&mut self, root: Node, mut other: Hugr) -> Result { - let (other_root, node_map) = insert_hugr_internal(self.as_mut(), root, &other)?; + let (other_root, node_map) = insert_hugr_internal(self, root, &other)?; // Update the optypes and metadata, taking them from the other graph. for (&node, &new_node) in node_map.iter() { let optype = other.op_types.take(node); - self.as_mut().op_types.set(new_node, optype); + self.op_types.set(new_node, optype); let meta = other.metadata.take(node); - self.as_mut().set_metadata(node.into(), meta); + self.set_metadata(node.into(), meta); } Ok(other_root) } fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> Result { - let (other_root, node_map) = insert_hugr_internal(self.as_mut(), root, other)?; + let (other_root, node_map) = insert_hugr_internal(self, root, other)?; // Update the optypes and metadata, copying them from the other graph. for (&node, &new_node) in node_map.iter() { let optype = other.get_optype(node.into()); - self.as_mut().op_types.set(new_node, optype.clone()); + self.op_types.set(new_node, optype.clone()); let meta = other.get_metadata(node.into()); - self.as_mut().set_metadata(node.into(), meta.clone()); + self.set_metadata(node.into(), meta.clone()); } Ok(other_root) } @@ -330,19 +316,18 @@ impl HugrMut for Hugr { let target: Node = NodeIndex::new(position).into(); if target != source { - let hugr = self.as_mut(); - hugr.graph.swap_nodes(target.index, source.index); - hugr.op_types.swap(target.index, source.index); - hugr.hierarchy.swap_nodes(target.index, source.index); + self.graph.swap_nodes(target.index, source.index); + self.op_types.swap(target.index, source.index); + self.hierarchy.swap_nodes(target.index, source.index); rekey(source, target); } } - self.as_mut().root = NodeIndex::new(0); + self.root = NodeIndex::new(0); // Finish by compacting the copy nodes. // The operation nodes will be left in place. // This step is not strictly necessary. - self.as_mut().graph.compact_nodes(|_, _| {}); + self.graph.compact_nodes(|_, _| {}); } } diff --git a/src/hugr/view.rs b/src/hugr/view.rs index 1ce91aa86..a61326450 100644 --- a/src/hugr/view.rs +++ b/src/hugr/view.rs @@ -208,51 +208,50 @@ impl HugrView for Hugr { #[inline] fn root(&self) -> Node { - self.as_ref().root.into() + self.root.into() } #[inline] fn get_parent(&self, node: Node) -> Option { - self.as_ref().hierarchy.parent(node.index).map(Into::into) + self.hierarchy.parent(node.index).map(Into::into) } #[inline] fn get_optype(&self, node: Node) -> &OpType { - self.as_ref().op_types.get(node.index) + self.op_types.get(node.index) } #[inline] fn node_count(&self) -> usize { - self.as_ref().graph.node_count() + self.graph.node_count() } #[inline] fn edge_count(&self) -> usize { - self.as_ref().graph.link_count() + self.graph.link_count() } #[inline] fn nodes(&self) -> Self::Nodes<'_> { - self.as_ref().graph.nodes_iter().map_into() + self.graph.nodes_iter().map_into() } #[inline] fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { - self.as_ref().graph.port_offsets(node.index, dir).map_into() + self.graph.port_offsets(node.index, dir).map_into() } #[inline] fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { - self.as_ref().graph.all_port_offsets(node.index).map_into() + self.graph.all_port_offsets(node.index).map_into() } #[inline] fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { - let hugr = self.as_ref(); - let port = hugr.graph.port_index(node.index, port.offset).unwrap(); - hugr.graph + let port = self.graph.port_index(node.index, port.offset).unwrap(); + self.graph .port_links(port) - .with_context(hugr) + .with_context(self) .map_with_context(|(_, link), hugr| { let port = link.port(); let node = hugr.graph.port_node(port).unwrap(); @@ -263,27 +262,27 @@ impl HugrView for Hugr { #[inline] fn num_ports(&self, node: Node, dir: Direction) -> usize { - self.as_ref().graph.num_ports(node.index, dir) + self.graph.num_ports(node.index, dir) } #[inline] fn children(&self, node: Node) -> Self::Children<'_> { - self.as_ref().hierarchy.children(node.index).map_into() + self.hierarchy.children(node.index).map_into() } #[inline] fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { - self.as_ref().graph.neighbours(node.index, dir).map_into() + self.graph.neighbours(node.index, dir).map_into() } #[inline] fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { - self.as_ref().graph.all_neighbours(node.index).map_into() + self.graph.all_neighbours(node.index).map_into() } #[inline] fn get_metadata(&self, node: Node) -> &NodeMetadata { - self.as_ref().metadata.get(node.index) + self.metadata.get(node.index) } } @@ -470,7 +469,7 @@ pub(crate) mod sealed { } fn base_hugr(&self) -> &Hugr { - &self + self } } From 8ac5c6bb42a5d332dd4f66d2105f4ae43f4ad4b6 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Mon, 24 Jul 2023 15:11:39 +0100 Subject: [PATCH 08/18] Revert unnecessary test changes - from_existing(Hugr) still works --- src/builder/cfg.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 0f4cfe324..28c7c83bf 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -351,13 +351,12 @@ mod test { build_basic_cfg(&mut cfg_builder)?; let h = cfg_builder.finish_hugr()?; - let mut h2 = h.clone(); - let mut new_builder = CFGBuilder::from_existing(&mut h2, h.root())?; + let mut new_builder = CFGBuilder::from_existing(h.clone(), h.root())?; assert_matches!(new_builder.simple_entry_builder(type_row![NAT], 1), Err(_)); - new_builder.finish_sub_container()?; + let h2 = new_builder.finish_hugr()?; assert_eq!(h, h2); // No new nodes added - let mut new_builder = CFGBuilder::from_existing(&mut h2, h.root())?; + let mut new_builder = CFGBuilder::from_existing(h.clone(), h.root())?; let block_builder = new_builder.simple_block_builder( vec![SimpleType::new_simple_predicate(1), NAT].into(), type_row![NAT], @@ -366,7 +365,7 @@ mod test { let new_bb = block_builder.container_node(); let [pred, nat]: [Wire; 2] = block_builder.input_wires_arr(); block_builder.finish_with_outputs(pred, [nat])?; - new_builder.finish_sub_container()?; + let h2 = new_builder.finish_hugr()?; let expected_nodes = h .children(h.root()) .chain([new_bb]) From 46c35a93ef0b94648059743baf2de0bd2def8526 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 14:48:17 +0100 Subject: [PATCH 09/18] deparameterize BaseMut but return &mut; combine impl Buildable for (Hugr/&mut H -> H); return &mut BaseMut --- src/builder/build_traits.rs | 40 +++++++++++-------------------------- src/builder/cfg.rs | 12 +++++------ src/builder/conditional.rs | 4 ++-- src/builder/dataflow.rs | 4 ++-- src/builder/module.rs | 4 ++-- 5 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index 32d553d41..bbb6c7541 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -31,38 +31,22 @@ use crate::Hugr; use crate::hugr::HugrMut; pub trait Buildable: HugrMut { - type BaseMut<'a>: Buildable - where - Self: 'a; + type BaseMut: Buildable; type BaseView<'a>: HugrView where Self: 'a; /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> Self::BaseMut<'_>; + fn hugr_mut(&mut self) -> &mut Self::BaseMut; /// Immutable reference to HUGR being built fn hugr(&self) -> Self::BaseView<'_>; } -impl Buildable for Hugr { - type BaseMut<'a> = &'a mut Hugr where Self: 'a; - - type BaseView<'a> = &'a Hugr where Self: 'a; - - fn hugr_mut(&mut self) -> Self::BaseMut<'_> { - self - } - - fn hugr(&self) -> Self::BaseView<'_> { - self - } -} - -impl Buildable for &mut H { - type BaseMut<'a> = &'a mut H where Self: 'a; +impl Buildable for H { + type BaseMut = H; type BaseView<'a> = &'a H where Self: 'a; - fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + fn hugr_mut(&mut self) -> &mut Self::BaseMut { self } @@ -80,7 +64,7 @@ pub trait Container { /// The container node. fn container_node(&self) -> Node; /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> ::BaseMut<'_>; + fn hugr_mut(&mut self) -> &mut ::BaseMut; /// Immutable reference to HUGR being built fn hugr(&self) -> ::BaseView<'_>; /// Add an [`OpType`] as the final child of the container. @@ -122,7 +106,7 @@ pub trait Container { &mut self, name: impl Into, signature: Signature, - ) -> Result::BaseMut<'_>>, BuildError> { + ) -> Result::BaseMut>, BuildError> { let f_node = self.add_child_op(ops::FuncDefn { name: name.into(), signature: signature.clone(), @@ -295,7 +279,7 @@ pub trait Dataflow: Container { &mut self, signature: Signature, input_wires: impl IntoIterator, - ) -> Result::BaseMut<'_>>, BuildError> { + ) -> Result::BaseMut>, BuildError> { let (dfg_n, _) = add_op_with_wires( self, ops::DFG { @@ -321,7 +305,7 @@ pub trait Dataflow: Container { &mut self, inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result::BaseMut<'_>>, BuildError> { + ) -> Result::BaseMut>, BuildError> { let (input_types, input_wires): (Vec, Vec) = inputs.into_iter().unzip(); let inputs: SimpleRow = input_types.into(); @@ -380,7 +364,7 @@ pub trait Dataflow: Container { just_inputs: impl IntoIterator, inputs_outputs: impl IntoIterator, just_out_types: ClassicRow, - ) -> Result::BaseMut<'_>>, BuildError> { + ) -> Result::BaseMut>, BuildError> { let (input_types, mut input_wires): (Vec, Vec) = just_inputs.into_iter().unzip(); let (rest_types, rest_input_wires): (Vec, Vec) = @@ -414,7 +398,7 @@ pub trait Dataflow: Container { (predicate_inputs, predicate_wire): (impl IntoIterator, Wire), other_inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result::BaseMut<'_>>, BuildError> { + ) -> Result::BaseMut>, BuildError> { let mut input_wires = vec![predicate_wire]; let (input_types, rest_input_wires): (Vec, Vec) = other_inputs.into_iter().unzip(); @@ -647,7 +631,7 @@ fn wire_up( dst: Node, dst_port: usize, ) -> Result { - let mut base = data_builder.hugr_mut(); + let base = data_builder.hugr_mut(); let src_offset = Port::new_outgoing(src_port); let src_parent = base.get_parent(src); diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index e65b91875..4e7d10da2 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -33,7 +33,7 @@ impl Container for CFGBuilder { } #[inline] - fn hugr_mut(&mut self) -> B::BaseMut<'_> { + fn hugr_mut(&mut self) -> &mut B::BaseMut { self.base.hugr_mut() } @@ -127,7 +127,7 @@ impl CFGBuilder { inputs: SimpleRow, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + ) -> Result::Base as Buildable>::BaseMut>, BuildError> { self.any_block_builder(inputs, predicate_variants, other_outputs, false) } @@ -138,7 +138,7 @@ impl CFGBuilder { predicate_variants: Vec, other_outputs: SimpleRow, entry: bool, - ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + ) -> Result::Base as Buildable>::BaseMut>, BuildError> { let op = OpType::BasicBlock(BasicBlock::DFB { inputs: inputs.clone(), @@ -173,7 +173,7 @@ impl CFGBuilder { inputs: SimpleRow, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + ) -> Result::Base as Buildable>::BaseMut>, BuildError> { self.block_builder(inputs, vec![type_row![]; n_cases], outputs) } @@ -189,7 +189,7 @@ impl CFGBuilder { &mut self, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + ) -> Result::Base as Buildable>::BaseMut>, BuildError> { let inputs = self .inputs @@ -208,7 +208,7 @@ impl CFGBuilder { &mut self, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + ) -> Result::Base as Buildable>::BaseMut>, BuildError> { self.entry_builder(vec![type_row![]; n_cases], outputs) } diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index 1f7149feb..e66232ba4 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -57,7 +57,7 @@ impl Container for ConditionalBuilder { } #[inline] - fn hugr_mut(&mut self) -> ::BaseMut<'_> { + fn hugr_mut(&mut self) -> &mut ::BaseMut { self.base.hugr_mut() } @@ -101,7 +101,7 @@ impl ConditionalBuilder { pub fn case_builder( &mut self, case: usize, - ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + ) -> Result::Base as Buildable>::BaseMut>, BuildError> { let conditional = self.conditional_node; let control_op = self.hugr().get_optype(self.conditional_node).clone(); diff --git a/src/builder/dataflow.rs b/src/builder/dataflow.rs index 2fdb1b9b6..9479481c8 100644 --- a/src/builder/dataflow.rs +++ b/src/builder/dataflow.rs @@ -90,7 +90,7 @@ impl Container for DFGBuilder { } #[inline] - fn hugr_mut(&mut self) -> ::BaseMut<'_> { + fn hugr_mut(&mut self) -> &mut ::BaseMut { self.base.hugr_mut() } @@ -156,7 +156,7 @@ impl Container for DFGWrapper { } #[inline] - fn hugr_mut(&mut self) -> ::BaseMut<'_> { + fn hugr_mut(&mut self) -> &mut ::BaseMut { self.0.hugr_mut() } diff --git a/src/builder/module.rs b/src/builder/module.rs index e54a5c3f5..707ac5024 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -32,7 +32,7 @@ impl Container for ModuleBuilder { } #[inline] - fn hugr_mut(&mut self) -> ::BaseMut<'_> { + fn hugr_mut(&mut self) -> &mut ::BaseMut { self.0.hugr_mut() } @@ -73,7 +73,7 @@ impl ModuleBuilder { pub fn define_declaration( &mut self, f_id: &FuncID, - ) -> Result::Base as Buildable>::BaseMut<'_>>, BuildError> + ) -> Result::Base as Buildable>::BaseMut>, BuildError> { let f_node = f_id.node(); let (signature, name) = if let OpType::FuncDecl(ops::FuncDecl { signature, name }) = From 0372837fcb32b68c5e0afa82c8b4fe920e49b558 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 14:54:22 +0100 Subject: [PATCH 10/18] Combine BaseMut/BaseView -> Base; remove explicit drop(!) --- src/builder/build_traits.rs | 32 +++++++++++++------------------- src/builder/cfg.rs | 19 +++++++------------ src/builder/conditional.rs | 7 +++---- src/builder/dataflow.rs | 8 ++++---- src/builder/module.rs | 6 +++--- 5 files changed, 30 insertions(+), 42 deletions(-) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index bbb6c7541..8466d4057 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -31,26 +31,21 @@ use crate::Hugr; use crate::hugr::HugrMut; pub trait Buildable: HugrMut { - type BaseMut: Buildable; - type BaseView<'a>: HugrView - where - Self: 'a; + type Base: Buildable; /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> &mut Self::BaseMut; + fn hugr_mut(&mut self) -> &mut Self::Base; /// Immutable reference to HUGR being built - fn hugr(&self) -> Self::BaseView<'_>; + fn hugr(&self) -> &Self::Base; } impl Buildable for H { - type BaseMut = H; - - type BaseView<'a> = &'a H where Self: 'a; + type Base = H; - fn hugr_mut(&mut self) -> &mut Self::BaseMut { + fn hugr_mut(&mut self) -> &mut Self::Base { self } - fn hugr(&self) -> Self::BaseView<'_> { + fn hugr(&self) -> &Self::Base { self } } @@ -64,9 +59,9 @@ pub trait Container { /// The container node. fn container_node(&self) -> Node; /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> &mut ::BaseMut; + fn hugr_mut(&mut self) -> &mut ::Base; /// Immutable reference to HUGR being built - fn hugr(&self) -> ::BaseView<'_>; + fn hugr(&self) -> &::Base; /// Add an [`OpType`] as the final child of the container. fn add_child_op(&mut self, op: impl Into) -> Result { let parent = self.container_node(); @@ -106,7 +101,7 @@ pub trait Container { &mut self, name: impl Into, signature: Signature, - ) -> Result::BaseMut>, BuildError> { + ) -> Result::Base>, BuildError> { let f_node = self.add_child_op(ops::FuncDefn { name: name.into(), signature: signature.clone(), @@ -279,7 +274,7 @@ pub trait Dataflow: Container { &mut self, signature: Signature, input_wires: impl IntoIterator, - ) -> Result::BaseMut>, BuildError> { + ) -> Result::Base>, BuildError> { let (dfg_n, _) = add_op_with_wires( self, ops::DFG { @@ -305,7 +300,7 @@ pub trait Dataflow: Container { &mut self, inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result::BaseMut>, BuildError> { + ) -> Result::Base>, BuildError> { let (input_types, input_wires): (Vec, Vec) = inputs.into_iter().unzip(); let inputs: SimpleRow = input_types.into(); @@ -364,7 +359,7 @@ pub trait Dataflow: Container { just_inputs: impl IntoIterator, inputs_outputs: impl IntoIterator, just_out_types: ClassicRow, - ) -> Result::BaseMut>, BuildError> { + ) -> Result::Base>, BuildError> { let (input_types, mut input_wires): (Vec, Vec) = just_inputs.into_iter().unzip(); let (rest_types, rest_input_wires): (Vec, Vec) = @@ -398,7 +393,7 @@ pub trait Dataflow: Container { (predicate_inputs, predicate_wire): (impl IntoIterator, Wire), other_inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result::BaseMut>, BuildError> { + ) -> Result::Base>, BuildError> { let mut input_wires = vec![predicate_wire]; let (input_types, rest_input_wires): (Vec, Vec) = other_inputs.into_iter().unzip(); @@ -614,7 +609,6 @@ fn wire_up_inputs( let base = data_builder.hugr(); let op = base.get_optype(op_node); let some_df_outputs = !op.signature().output.is_empty(); - drop(base); if !any_local_df_inputs && some_df_outputs { // If op has no inputs add a StateOrder edge from input to place in // causal cone of Input node diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 4e7d10da2..a9edb4c34 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -33,12 +33,12 @@ impl Container for CFGBuilder { } #[inline] - fn hugr_mut(&mut self) -> &mut B::BaseMut { + fn hugr_mut(&mut self) -> &mut B::Base { self.base.hugr_mut() } #[inline] - fn hugr(&self) -> B::BaseView<'_> { + fn hugr(&self) -> &B::Base { self.base.hugr() } } @@ -127,8 +127,7 @@ impl CFGBuilder { inputs: SimpleRow, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base as Buildable>::BaseMut>, BuildError> - { + ) -> Result::Base as Buildable>::Base>, BuildError> { self.any_block_builder(inputs, predicate_variants, other_outputs, false) } @@ -138,8 +137,7 @@ impl CFGBuilder { predicate_variants: Vec, other_outputs: SimpleRow, entry: bool, - ) -> Result::Base as Buildable>::BaseMut>, BuildError> - { + ) -> Result::Base as Buildable>::Base>, BuildError> { let op = OpType::BasicBlock(BasicBlock::DFB { inputs: inputs.clone(), other_outputs: other_outputs.clone(), @@ -173,8 +171,7 @@ impl CFGBuilder { inputs: SimpleRow, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base as Buildable>::BaseMut>, BuildError> - { + ) -> Result::Base as Buildable>::Base>, BuildError> { self.block_builder(inputs, vec![type_row![]; n_cases], outputs) } @@ -189,8 +186,7 @@ impl CFGBuilder { &mut self, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base as Buildable>::BaseMut>, BuildError> - { + ) -> Result::Base as Buildable>::Base>, BuildError> { let inputs = self .inputs .take() @@ -208,8 +204,7 @@ impl CFGBuilder { &mut self, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base as Buildable>::BaseMut>, BuildError> - { + ) -> Result::Base as Buildable>::Base>, BuildError> { self.entry_builder(vec![type_row![]; n_cases], outputs) } diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index e66232ba4..b792120e9 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -57,12 +57,12 @@ impl Container for ConditionalBuilder { } #[inline] - fn hugr_mut(&mut self) -> &mut ::BaseMut { + fn hugr_mut(&mut self) -> &mut ::Base { self.base.hugr_mut() } #[inline] - fn hugr(&self) -> ::BaseView<'_> { + fn hugr(&self) -> &::Base { self.base.hugr() } } @@ -101,8 +101,7 @@ impl ConditionalBuilder { pub fn case_builder( &mut self, case: usize, - ) -> Result::Base as Buildable>::BaseMut>, BuildError> - { + ) -> Result::Base as Buildable>::Base>, BuildError> { let conditional = self.conditional_node; let control_op = self.hugr().get_optype(self.conditional_node).clone(); diff --git a/src/builder/dataflow.rs b/src/builder/dataflow.rs index 9479481c8..9ef71c2a4 100644 --- a/src/builder/dataflow.rs +++ b/src/builder/dataflow.rs @@ -90,12 +90,12 @@ impl Container for DFGBuilder { } #[inline] - fn hugr_mut(&mut self) -> &mut ::BaseMut { + fn hugr_mut(&mut self) -> &mut ::Base { self.base.hugr_mut() } #[inline] - fn hugr(&self) -> ::BaseView<'_> { + fn hugr(&self) -> &::Base { self.base.hugr() } } @@ -156,12 +156,12 @@ impl Container for DFGWrapper { } #[inline] - fn hugr_mut(&mut self) -> &mut ::BaseMut { + fn hugr_mut(&mut self) -> &mut ::Base { self.0.hugr_mut() } #[inline] - fn hugr(&self) -> ::BaseView<'_> { + fn hugr(&self) -> &::Base { self.0.hugr() } } diff --git a/src/builder/module.rs b/src/builder/module.rs index 707ac5024..3f95bd212 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -32,11 +32,11 @@ impl Container for ModuleBuilder { } #[inline] - fn hugr_mut(&mut self) -> &mut ::BaseMut { + fn hugr_mut(&mut self) -> &mut ::Base { self.0.hugr_mut() } - fn hugr(&self) -> ::BaseView<'_> { + fn hugr(&self) -> &::Base { self.0.hugr() } } @@ -73,7 +73,7 @@ impl ModuleBuilder { pub fn define_declaration( &mut self, f_id: &FuncID, - ) -> Result::Base as Buildable>::BaseMut>, BuildError> + ) -> Result::Base as Buildable>::Base>, BuildError> { let f_node = f_id.node(); let (signature, name) = if let OpType::FuncDecl(ops::FuncDecl { signature, name }) = From 630c216f96ab0aeccfb6d54e413ea4020757248d Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 15:00:22 +0100 Subject: [PATCH 11/18] Buildable does not require HugrMut, but Base constrained Buildable+HugrMut --- src/algorithm/nest_cfgs.rs | 9 +++++---- src/builder/build_traits.rs | 4 ++-- src/builder/cfg.rs | 6 ++++-- src/builder/module.rs | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/algorithm/nest_cfgs.rs b/src/algorithm/nest_cfgs.rs index 3735bd7f7..f5035aa55 100644 --- a/src/algorithm/nest_cfgs.rs +++ b/src/algorithm/nest_cfgs.rs @@ -401,6 +401,7 @@ pub(crate) mod test { BuildError, Buildable, CFGBuilder, Container, DataflowSubContainer, HugrBuilder, }; use crate::hugr::region::{FlatRegionView, Region}; + use crate::hugr::HugrMut; use crate::ops::{ handle::{BasicBlockID, ConstID, NodeHandle}, ConstValue, @@ -579,7 +580,7 @@ pub(crate) mod test { dataflow_builder.finish_with_outputs([u].into_iter().chain(w)) } - fn build_if_then_else_merge( + fn build_if_then_else_merge( cfg: &mut CFGBuilder, const_pred: &ConstID, unit_const: &ConstID, @@ -592,7 +593,7 @@ pub(crate) mod test { Ok((split, merge)) } - fn build_then_else_merge_from_if( + fn build_then_else_merge_from_if( cfg: &mut CFGBuilder, unit_const: &ConstID, split: BasicBlockID, @@ -617,7 +618,7 @@ pub(crate) mod test { } // Returns loop tail - caller must link header to tail, and provide 0th successor of tail - fn build_loop_from_header( + fn build_loop_from_header( cfg: &mut CFGBuilder, const_pred: &ConstID, header: BasicBlockID, @@ -631,7 +632,7 @@ pub(crate) mod test { } // Result is header and tail. Caller must provide 0th successor of header (linking to tail), and 0th successor of tail. - fn build_loop( + fn build_loop( cfg: &mut CFGBuilder, const_pred: &ConstID, unit_const: &ConstID, diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index 8466d4057..5c36650fb 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -30,8 +30,8 @@ use crate::Hugr; use crate::hugr::HugrMut; -pub trait Buildable: HugrMut { - type Base: Buildable; +pub trait Buildable { + type Base: Buildable + HugrMut; /// The underlying [`Hugr`] being built fn hugr_mut(&mut self) -> &mut Self::Base; /// Immutable reference to HUGR being built diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index a9edb4c34..c486ac09c 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -77,7 +77,7 @@ impl HugrBuilder for CFGBuilder { } } -impl CFGBuilder { +impl CFGBuilder { pub(super) fn create( mut base: B, cfg_node: Node, @@ -372,7 +372,9 @@ mod test { Ok(()) } - fn build_basic_cfg(cfg_builder: &mut CFGBuilder) -> Result<(), BuildError> + fn build_basic_cfg( + cfg_builder: &mut CFGBuilder, + ) -> Result<(), BuildError> where CFGBuilder: Container, { diff --git a/src/builder/module.rs b/src/builder/module.rs index 3f95bd212..ccc8a839e 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -24,7 +24,7 @@ use crate::{hugr::HugrMut, Hugr}; #[derive(Debug, Clone, PartialEq)] pub struct ModuleBuilder(pub(super) T); -impl Container for ModuleBuilder { +impl Container for ModuleBuilder { type Base = T; #[inline] fn container_node(&self) -> Node { @@ -62,7 +62,7 @@ impl HugrBuilder for ModuleBuilder { } } -impl ModuleBuilder { +impl ModuleBuilder { /// Replace a [`ops::FuncDecl`] with [`ops::FuncDefn`] and return a builder for /// the defining graph. /// From 6ae55167fe203fcf68d769a7769f25e2e612729f Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 15:22:33 +0100 Subject: [PATCH 12/18] Container: Buildable. Massive savings on albeit deeper refs? --- src/builder/build_traits.rs | 18 ++++++--------- src/builder/cfg.rs | 30 +++++++++++++------------ src/builder/conditional.rs | 25 +++++++++++---------- src/builder/dataflow.rs | 40 ++++++++++++++++++--------------- src/builder/module.rs | 30 +++++++++++-------------- src/builder/tail_loop.rs | 3 ++- src/hugr/rewrite/outline_cfg.rs | 2 +- 7 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index 5c36650fb..dba944b93 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -54,14 +54,10 @@ impl Buildable for H { /// Containers are nodes that are parents of sibling graphs. /// Implementations of this trait allow the child sibling graph to be added to /// the HUGR. -pub trait Container { - type Base: Buildable; +pub trait Container: Buildable { /// The container node. fn container_node(&self) -> Node; - /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> &mut ::Base; - /// Immutable reference to HUGR being built - fn hugr(&self) -> &::Base; + /// Add an [`OpType`] as the final child of the container. fn add_child_op(&mut self, op: impl Into) -> Result { let parent = self.container_node(); @@ -101,7 +97,7 @@ pub trait Container { &mut self, name: impl Into, signature: Signature, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let f_node = self.add_child_op(ops::FuncDefn { name: name.into(), signature: signature.clone(), @@ -274,7 +270,7 @@ pub trait Dataflow: Container { &mut self, signature: Signature, input_wires: impl IntoIterator, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let (dfg_n, _) = add_op_with_wires( self, ops::DFG { @@ -300,7 +296,7 @@ pub trait Dataflow: Container { &mut self, inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let (input_types, input_wires): (Vec, Vec) = inputs.into_iter().unzip(); let inputs: SimpleRow = input_types.into(); @@ -359,7 +355,7 @@ pub trait Dataflow: Container { just_inputs: impl IntoIterator, inputs_outputs: impl IntoIterator, just_out_types: ClassicRow, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let (input_types, mut input_wires): (Vec, Vec) = just_inputs.into_iter().unzip(); let (rest_types, rest_input_wires): (Vec, Vec) = @@ -393,7 +389,7 @@ pub trait Dataflow: Container { (predicate_inputs, predicate_wire): (impl IntoIterator, Wire), other_inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let mut input_wires = vec![predicate_wire]; let (input_types, rest_input_wires): (Vec, Vec) = other_inputs.into_iter().unzip(); diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index c486ac09c..d7683e791 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -25,25 +25,27 @@ pub struct CFGBuilder { pub(super) n_out_wires: usize, } -impl Container for CFGBuilder { +impl Buildable for CFGBuilder { type Base = B; #[inline] - fn container_node(&self) -> Node { - self.cfg_node + fn hugr_mut(&mut self) -> &mut B { + &mut self.base } #[inline] - fn hugr_mut(&mut self) -> &mut B::Base { - self.base.hugr_mut() + fn hugr(&self) -> &B { + &self.base } +} +impl Container for CFGBuilder { #[inline] - fn hugr(&self) -> &B::Base { - self.base.hugr() + fn container_node(&self) -> Node { + self.cfg_node } } -impl SubContainer for CFGBuilder { +impl SubContainer for CFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -127,7 +129,7 @@ impl CFGBuilder { inputs: SimpleRow, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base as Buildable>::Base>, BuildError> { + ) -> Result::Base>, BuildError> { self.any_block_builder(inputs, predicate_variants, other_outputs, false) } @@ -137,7 +139,7 @@ impl CFGBuilder { predicate_variants: Vec, other_outputs: SimpleRow, entry: bool, - ) -> Result::Base as Buildable>::Base>, BuildError> { + ) -> Result::Base>, BuildError> { let op = OpType::BasicBlock(BasicBlock::DFB { inputs: inputs.clone(), other_outputs: other_outputs.clone(), @@ -171,7 +173,7 @@ impl CFGBuilder { inputs: SimpleRow, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base as Buildable>::Base>, BuildError> { + ) -> Result::Base>, BuildError> { self.block_builder(inputs, vec![type_row![]; n_cases], outputs) } @@ -186,7 +188,7 @@ impl CFGBuilder { &mut self, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base as Buildable>::Base>, BuildError> { + ) -> Result::Base>, BuildError> { let inputs = self .inputs .take() @@ -204,7 +206,7 @@ impl CFGBuilder { &mut self, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base as Buildable>::Base>, BuildError> { + ) -> Result::Base>, BuildError> { self.entry_builder(vec![type_row![]; n_cases], outputs) } @@ -233,7 +235,7 @@ impl CFGBuilder { /// Builder for a [`BasicBlock::DFB`] child graph. pub type BlockBuilder = DFGWrapper; -impl BlockBuilder { +impl BlockBuilder { /// Set the outputs of the block, with `branch_wire` being the value of the /// predicate. `outputs` are the remaining outputs. pub fn set_outputs( diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index b792120e9..7d10ad9da 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -48,26 +48,27 @@ pub struct ConditionalBuilder { pub(super) case_nodes: Vec>, } -impl Container for ConditionalBuilder { - type Base = T; - +impl Buildable for ConditionalBuilder { + type Base = B; #[inline] - fn container_node(&self) -> Node { - self.conditional_node + fn hugr_mut(&mut self) -> &mut Self::Base { + &mut self.base } #[inline] - fn hugr_mut(&mut self) -> &mut ::Base { - self.base.hugr_mut() + fn hugr(&self) -> &Self::Base { + &self.base } +} +impl Container for ConditionalBuilder { #[inline] - fn hugr(&self) -> &::Base { - self.base.hugr() + fn container_node(&self) -> Node { + self.conditional_node } } -impl SubContainer for ConditionalBuilder { +impl SubContainer for ConditionalBuilder { type ContainerHandle = BuildHandle; fn finish_sub_container(self) -> Result { @@ -87,7 +88,7 @@ impl SubContainer for ConditionalBuilder { Ok((self.conditional_node, self.n_out_wires).into()) } } -impl ConditionalBuilder { +impl ConditionalBuilder { /// Return a builder the Case node with index `case`. /// /// # Panics @@ -101,7 +102,7 @@ impl ConditionalBuilder { pub fn case_builder( &mut self, case: usize, - ) -> Result::Base as Buildable>::Base>, BuildError> { + ) -> Result::Base>, BuildError> { let conditional = self.conditional_node; let control_op = self.hugr().get_optype(self.conditional_node).clone(); diff --git a/src/builder/dataflow.rs b/src/builder/dataflow.rs index 9ef71c2a4..601b63aa6 100644 --- a/src/builder/dataflow.rs +++ b/src/builder/dataflow.rs @@ -82,25 +82,27 @@ impl HugrBuilder for DFGBuilder { } } -impl Container for DFGBuilder { +impl Buildable for DFGBuilder { type Base = B; #[inline] - fn container_node(&self) -> Node { - self.dfg_node + fn hugr_mut(&mut self) -> &mut Self::Base { + &mut self.base } #[inline] - fn hugr_mut(&mut self) -> &mut ::Base { - self.base.hugr_mut() + fn hugr(&self) -> &Self::Base { + &self.base } +} +impl Container for DFGBuilder { #[inline] - fn hugr(&self) -> &::Base { - self.base.hugr() + fn container_node(&self) -> Node { + self.dfg_node } } -impl SubContainer for DFGBuilder { +impl SubContainer for DFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -108,7 +110,7 @@ impl SubContainer for DFGBuilder { } } -impl Dataflow for DFGBuilder { +impl Dataflow for DFGBuilder { #[inline] fn num_inputs(&self) -> usize { self.num_in_wires @@ -148,32 +150,34 @@ impl FunctionBuilder { } } -impl Container for DFGWrapper { +impl Buildable for DFGWrapper { type Base = B; #[inline] - fn container_node(&self) -> Node { - self.0.container_node() + fn hugr_mut(&mut self) -> &mut Self::Base { + self.0.hugr_mut() } #[inline] - fn hugr_mut(&mut self) -> &mut ::Base { - self.0.hugr_mut() + fn hugr(&self) -> &Self::Base { + self.0.hugr() } +} +impl Container for DFGWrapper { #[inline] - fn hugr(&self) -> &::Base { - self.0.hugr() + fn container_node(&self) -> Node { + self.0.container_node() } } -impl Dataflow for DFGWrapper { +impl Dataflow for DFGWrapper { #[inline] fn num_inputs(&self) -> usize { Dataflow::num_inputs(&self.0) } } -impl>> SubContainer for DFGWrapper { +impl>> SubContainer for DFGWrapper { type ContainerHandle = T; #[inline] diff --git a/src/builder/module.rs b/src/builder/module.rs index ccc8a839e..d49c0165b 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -4,11 +4,7 @@ use super::{ BuildError, Container, }; -use crate::{ - hugr::{view::HugrView, ValidationError}, - ops, - types::SimpleType, -}; +use crate::{hugr::ValidationError, ops, types::SimpleType}; use crate::ops::handle::{AliasID, FuncID, NodeHandle}; use crate::ops::OpType; @@ -23,21 +19,22 @@ use crate::{hugr::HugrMut, Hugr}; /// Builder for a HUGR module. #[derive(Debug, Clone, PartialEq)] pub struct ModuleBuilder(pub(super) T); - -impl Container for ModuleBuilder { - type Base = T; +impl Buildable for ModuleBuilder { + type Base = B; #[inline] - fn container_node(&self) -> Node { - self.0.root() + fn hugr_mut(&mut self) -> &mut Self::Base { + &mut self.0 } - #[inline] - fn hugr_mut(&mut self) -> &mut ::Base { - self.0.hugr_mut() + fn hugr(&self) -> &Self::Base { + &self.0 } +} - fn hugr(&self) -> &::Base { - self.0.hugr() +impl Container for ModuleBuilder { + #[inline] + fn container_node(&self) -> Node { + self.0.root() } } @@ -73,8 +70,7 @@ impl ModuleBuilder { pub fn define_declaration( &mut self, f_id: &FuncID, - ) -> Result::Base as Buildable>::Base>, BuildError> - { + ) -> Result::Base>, BuildError> { let f_node = f_id.node(); let (signature, name) = if let OpType::FuncDecl(ops::FuncDecl { signature, name }) = self.hugr().get_optype(f_node) diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index 436849c11..3c55715e5 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -1,3 +1,4 @@ +use crate::hugr::HugrMut; use crate::ops::{self, OpType}; use crate::hugr::view::HugrView; @@ -14,7 +15,7 @@ use super::{ /// Builder for a [`ops::TailLoop`] node. pub type TailLoopBuilder = DFGWrapper>; -impl TailLoopBuilder { +impl TailLoopBuilder { pub(super) fn create_with_io( base: B, loop_node: Node, diff --git a/src/hugr/rewrite/outline_cfg.rs b/src/hugr/rewrite/outline_cfg.rs index dc9051ae5..168026e0a 100644 --- a/src/hugr/rewrite/outline_cfg.rs +++ b/src/hugr/rewrite/outline_cfg.rs @@ -4,7 +4,7 @@ use std::collections::HashSet; use itertools::Itertools; use thiserror::Error; -use crate::builder::{CFGBuilder, Container, Dataflow, SubContainer}; +use crate::builder::{Buildable, CFGBuilder, Container, Dataflow, SubContainer}; use crate::hugr::rewrite::Rewrite; use crate::hugr::{HugrMut, HugrView}; use crate::ops::handle::NodeHandle; From 1742bc94a697ef4c6c4d8cfa51468a9645019d6a Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 15:26:58 +0100 Subject: [PATCH 13/18] Buildable::Base does not need to be Buildable! --- src/builder/build_traits.rs | 2 +- src/builder/cfg.rs | 14 ++++++-------- src/builder/conditional.rs | 8 ++++---- src/builder/dataflow.rs | 16 ++++++++-------- src/builder/module.rs | 6 +++--- src/builder/tail_loop.rs | 2 +- 6 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index dba944b93..f3d83709f 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -31,7 +31,7 @@ use crate::Hugr; use crate::hugr::HugrMut; pub trait Buildable { - type Base: Buildable + HugrMut; + type Base: HugrMut; /// The underlying [`Hugr`] being built fn hugr_mut(&mut self) -> &mut Self::Base; /// Immutable reference to HUGR being built diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index d7683e791..1cc37aa3c 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -25,7 +25,7 @@ pub struct CFGBuilder { pub(super) n_out_wires: usize, } -impl Buildable for CFGBuilder { +impl Buildable for CFGBuilder { type Base = B; #[inline] fn hugr_mut(&mut self) -> &mut B { @@ -38,14 +38,14 @@ impl Buildable for CFGBuilder { } } -impl Container for CFGBuilder { +impl Container for CFGBuilder { #[inline] fn container_node(&self) -> Node { self.cfg_node } } -impl SubContainer for CFGBuilder { +impl SubContainer for CFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -79,7 +79,7 @@ impl HugrBuilder for CFGBuilder { } } -impl CFGBuilder { +impl CFGBuilder { pub(super) fn create( mut base: B, cfg_node: Node, @@ -235,7 +235,7 @@ impl CFGBuilder { /// Builder for a [`BasicBlock::DFB`] child graph. pub type BlockBuilder = DFGWrapper; -impl BlockBuilder { +impl BlockBuilder { /// Set the outputs of the block, with `branch_wire` being the value of the /// predicate. `outputs` are the remaining outputs. pub fn set_outputs( @@ -374,9 +374,7 @@ mod test { Ok(()) } - fn build_basic_cfg( - cfg_builder: &mut CFGBuilder, - ) -> Result<(), BuildError> + fn build_basic_cfg(cfg_builder: &mut CFGBuilder) -> Result<(), BuildError> where CFGBuilder: Container, { diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index 7d10ad9da..c1a9e2b4f 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -48,7 +48,7 @@ pub struct ConditionalBuilder { pub(super) case_nodes: Vec>, } -impl Buildable for ConditionalBuilder { +impl Buildable for ConditionalBuilder { type Base = B; #[inline] fn hugr_mut(&mut self) -> &mut Self::Base { @@ -61,14 +61,14 @@ impl Buildable for ConditionalBuilder { } } -impl Container for ConditionalBuilder { +impl Container for ConditionalBuilder { #[inline] fn container_node(&self) -> Node { self.conditional_node } } -impl SubContainer for ConditionalBuilder { +impl SubContainer for ConditionalBuilder { type ContainerHandle = BuildHandle; fn finish_sub_container(self) -> Result { @@ -88,7 +88,7 @@ impl SubContainer for ConditionalBuilder { Ok((self.conditional_node, self.n_out_wires).into()) } } -impl ConditionalBuilder { +impl ConditionalBuilder { /// Return a builder the Case node with index `case`. /// /// # Panics diff --git a/src/builder/dataflow.rs b/src/builder/dataflow.rs index 601b63aa6..405064c3c 100644 --- a/src/builder/dataflow.rs +++ b/src/builder/dataflow.rs @@ -82,7 +82,7 @@ impl HugrBuilder for DFGBuilder { } } -impl Buildable for DFGBuilder { +impl Buildable for DFGBuilder { type Base = B; #[inline] fn hugr_mut(&mut self) -> &mut Self::Base { @@ -95,14 +95,14 @@ impl Buildable for DFGBuilder { } } -impl Container for DFGBuilder { +impl Container for DFGBuilder { #[inline] fn container_node(&self) -> Node { self.dfg_node } } -impl SubContainer for DFGBuilder { +impl SubContainer for DFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -110,7 +110,7 @@ impl SubContainer for DFGBuilder { } } -impl Dataflow for DFGBuilder { +impl Dataflow for DFGBuilder { #[inline] fn num_inputs(&self) -> usize { self.num_in_wires @@ -150,7 +150,7 @@ impl FunctionBuilder { } } -impl Buildable for DFGWrapper { +impl Buildable for DFGWrapper { type Base = B; #[inline] fn hugr_mut(&mut self) -> &mut Self::Base { @@ -163,21 +163,21 @@ impl Buildable for DFGWrapper { } } -impl Container for DFGWrapper { +impl Container for DFGWrapper { #[inline] fn container_node(&self) -> Node { self.0.container_node() } } -impl Dataflow for DFGWrapper { +impl Dataflow for DFGWrapper { #[inline] fn num_inputs(&self) -> usize { Dataflow::num_inputs(&self.0) } } -impl>> SubContainer for DFGWrapper { +impl>> SubContainer for DFGWrapper { type ContainerHandle = T; #[inline] diff --git a/src/builder/module.rs b/src/builder/module.rs index d49c0165b..a2d9920ff 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -19,7 +19,7 @@ use crate::{hugr::HugrMut, Hugr}; /// Builder for a HUGR module. #[derive(Debug, Clone, PartialEq)] pub struct ModuleBuilder(pub(super) T); -impl Buildable for ModuleBuilder { +impl Buildable for ModuleBuilder { type Base = B; #[inline] fn hugr_mut(&mut self) -> &mut Self::Base { @@ -31,7 +31,7 @@ impl Buildable for ModuleBuilder { } } -impl Container for ModuleBuilder { +impl Container for ModuleBuilder { #[inline] fn container_node(&self) -> Node { self.0.root() @@ -59,7 +59,7 @@ impl HugrBuilder for ModuleBuilder { } } -impl ModuleBuilder { +impl ModuleBuilder { /// Replace a [`ops::FuncDecl`] with [`ops::FuncDefn`] and return a builder for /// the defining graph. /// diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index 3c55715e5..3b4f091ea 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -15,7 +15,7 @@ use super::{ /// Builder for a [`ops::TailLoop`] node. pub type TailLoopBuilder = DFGWrapper>; -impl TailLoopBuilder { +impl TailLoopBuilder { pub(super) fn create_with_io( base: B, loop_node: Node, From 2d6ebce0fe570c8726a12899b825c39749dbf0a9 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 15:27:29 +0100 Subject: [PATCH 14/18] Drop redundant +HugrView constraint, and HugrView impl for (&impl HugrView) --- src/builder/build_traits.rs | 2 +- src/hugr/view.rs | 78 ------------------------------------- 2 files changed, 1 insertion(+), 79 deletions(-) diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index f3d83709f..05f0313ee 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -38,7 +38,7 @@ pub trait Buildable { fn hugr(&self) -> &Self::Base; } -impl Buildable for H { +impl Buildable for H { type Base = H; fn hugr_mut(&mut self) -> &mut Self::Base { diff --git a/src/hugr/view.rs b/src/hugr/view.rs index a61326450..ea7bc3e2c 100644 --- a/src/hugr/view.rs +++ b/src/hugr/view.rs @@ -286,84 +286,6 @@ impl HugrView for Hugr { } } -impl HugrView for &T { - type Nodes<'a> = T::Nodes<'a> - where - Self: 'a; - - type NodePorts<'a> = T::NodePorts<'a> - where - Self: 'a; - - type Children<'a> = T::Children<'a> - where - Self: 'a; - - type Neighbours<'a> = T::Neighbours<'a> - where - Self: 'a; - - type PortLinks<'a> = T::PortLinks<'a> - where - Self: 'a; - - fn root(&self) -> Node { - (**self).root() - } - - fn get_parent(&self, node: Node) -> Option { - (**self).get_parent(node) - } - - fn get_optype(&self, node: Node) -> &OpType { - (**self).get_optype(node) - } - - fn get_metadata(&self, node: Node) -> &NodeMetadata { - (**self).get_metadata(node) - } - - fn node_count(&self) -> usize { - (**self).node_count() - } - - fn edge_count(&self) -> usize { - (**self).edge_count() - } - - fn nodes(&self) -> Self::Nodes<'_> { - (**self).nodes() - } - - fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { - (**self).node_ports(node, dir) - } - - fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { - (**self).all_node_ports(node) - } - - fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { - (**self).linked_ports(node, port) - } - - fn num_ports(&self, node: Node, dir: Direction) -> usize { - (**self).num_ports(node, dir) - } - - fn children(&self, node: Node) -> Self::Children<'_> { - (**self).children(node) - } - - fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { - (**self).neighbours(node, dir) - } - - fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { - (**self).all_neighbours(node) - } -} - impl HugrView for &mut T { type Nodes<'a> = T::Nodes<'a> where From cc8f4893e80511714f175af0f4336307ec0787c7 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 17:41:30 +0100 Subject: [PATCH 15/18] ::Base -> B/T (whatever type param is) --- src/builder/cfg.rs | 10 +++++----- src/builder/conditional.rs | 5 +---- src/builder/module.rs | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 1cc37aa3c..7e90cfced 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -129,7 +129,7 @@ impl CFGBuilder { inputs: SimpleRow, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { self.any_block_builder(inputs, predicate_variants, other_outputs, false) } @@ -139,7 +139,7 @@ impl CFGBuilder { predicate_variants: Vec, other_outputs: SimpleRow, entry: bool, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let op = OpType::BasicBlock(BasicBlock::DFB { inputs: inputs.clone(), other_outputs: other_outputs.clone(), @@ -173,7 +173,7 @@ impl CFGBuilder { inputs: SimpleRow, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { self.block_builder(inputs, vec![type_row![]; n_cases], outputs) } @@ -188,7 +188,7 @@ impl CFGBuilder { &mut self, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let inputs = self .inputs .take() @@ -206,7 +206,7 @@ impl CFGBuilder { &mut self, outputs: SimpleRow, n_cases: usize, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { self.entry_builder(vec![type_row![]; n_cases], outputs) } diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index c1a9e2b4f..781b4e1ed 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -99,10 +99,7 @@ impl ConditionalBuilder { /// /// This function will return an error if the case has already been built, /// `case` is not a valid index or if there is an error adding nodes. - pub fn case_builder( - &mut self, - case: usize, - ) -> Result::Base>, BuildError> { + pub fn case_builder(&mut self, case: usize) -> Result, BuildError> { let conditional = self.conditional_node; let control_op = self.hugr().get_optype(self.conditional_node).clone(); diff --git a/src/builder/module.rs b/src/builder/module.rs index a2d9920ff..225a226ec 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -70,7 +70,7 @@ impl ModuleBuilder { pub fn define_declaration( &mut self, f_id: &FuncID, - ) -> Result::Base>, BuildError> { + ) -> Result, BuildError> { let f_node = f_id.node(); let (signature, name) = if let OpType::FuncDecl(ops::FuncDecl { signature, name }) = self.hugr().get_optype(f_node) From eee773cf646e6a174489a84e9226183b233b9010 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 18:00:15 +0100 Subject: [PATCH 16/18] Rewrite HugrMut impl using delegate --- Cargo.toml | 1 + src/hugr/hugrmut.rs | 116 ++++++++++++++------------------------------ 2 files changed, 37 insertions(+), 80 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 84e5250c1..e59f71e64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ html-escape = "0.2.13" bitvec = { version = "1.0.1", features = ["serde"] } enum_dispatch = "0.3.11" lazy_static = "1.4.0" +delegate = "0.10.0" petgraph = { version="0.6.3", default-features = false} context-iterators = "0.2.0" serde_json = "1.0.97" diff --git a/src/hugr/hugrmut.rs b/src/hugr/hugrmut.rs index 42479a0c0..b07a4bfba 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -1,5 +1,6 @@ //! Base HUGR builder providing low-level building blocks. +use delegate::delegate; use std::collections::HashMap; use std::ops::Range; @@ -332,86 +333,41 @@ impl HugrMut for Hugr { } impl HugrMut for &mut T { - fn add_op(&mut self, op: impl Into) -> Node { - (*self).add_op(op) - } - - fn remove_node(&mut self, node: Node) -> Result<(), HugrError> { - (*self).remove_node(node) - } - - fn get_metadata_mut(&mut self, node: Node) -> &mut NodeMetadata { - (*self).get_metadata_mut(node) - } - - fn connect( - &mut self, - src: Node, - src_port: usize, - dst: Node, - dst_port: usize, - ) -> Result<(), HugrError> { - (*self).connect(src, src_port, dst, dst_port) - } - - fn disconnect(&mut self, node: Node, port: Port) -> Result<(), HugrError> { - (*self).disconnect(node, port) - } - - fn add_other_edge(&mut self, src: Node, dst: Node) -> Result<(Port, Port), HugrError> { - (*self).add_other_edge(src, dst) - } - - fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) { - (*self).set_num_ports(node, incoming, outgoing) - } - - fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range { - (*self).add_ports(node, direction, amount) - } - - fn set_parent(&mut self, node: Node, parent: Node) -> Result<(), HugrError> { - (*self).set_parent(node, parent) - } - - fn move_after_sibling(&mut self, node: Node, after: Node) -> Result<(), HugrError> { - (*self).move_after_sibling(node, after) - } - - fn move_before_sibling(&mut self, node: Node, before: Node) -> Result<(), HugrError> { - (*self).move_before_sibling(node, before) - } - - fn add_op_with_parent( - &mut self, - parent: Node, - op: impl Into, - ) -> Result { - (*self).add_op_with_parent(parent, op) - } - - fn add_op_before(&mut self, sibling: Node, op: impl Into) -> Result { - (*self).add_op_before(sibling, op) - } - - fn add_op_after(&mut self, sibling: Node, op: impl Into) -> Result { - (*self).add_op_after(sibling, op) - } - - fn replace_op(&mut self, node: Node, op: impl Into) -> OpType { - (*self).replace_op(node, op) - } - - fn insert_hugr(&mut self, root: Node, other: Hugr) -> Result { - (*self).insert_hugr(root, other) - } - - fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> Result { - (*self).insert_from_view(root, other) - } - - fn canonicalize_nodes(&mut self, rekey: impl FnMut(Node, Node)) { - (*self).canonicalize_nodes(rekey) + delegate! { + to (*self) { + fn add_op(&mut self, op: impl Into) -> Node; + fn remove_node(&mut self, node: Node) -> Result<(), HugrError>; + fn get_metadata_mut(&mut self, node: Node) -> &mut NodeMetadata; + + fn connect( + &mut self, + src: Node, + src_port: usize, + dst: Node, + dst_port: usize, + ) -> Result<(), HugrError>; + + fn disconnect(&mut self, node: Node, port: Port) -> Result<(), HugrError>; + fn add_other_edge(&mut self, src: Node, dst: Node) -> Result<(Port, Port), HugrError>; + fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize); + fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range; + fn set_parent(&mut self, node: Node, parent: Node) -> Result<(), HugrError>; + fn move_after_sibling(&mut self, node: Node, after: Node) -> Result<(), HugrError>; + fn move_before_sibling(&mut self, node: Node, before: Node) -> Result<(), HugrError>; + + fn add_op_with_parent( + &mut self, + parent: Node, + op: impl Into, + ) -> Result; + + fn add_op_before(&mut self, sibling: Node, op: impl Into) -> Result; + fn add_op_after(&mut self, sibling: Node, op: impl Into) -> Result; + fn replace_op(&mut self, node: Node, op: impl Into) -> OpType; + fn insert_hugr(&mut self, root: Node, other: Hugr) -> Result; + fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> Result; + fn canonicalize_nodes(&mut self, rekey: impl FnMut(Node, Node)); + } } } From f4cc4afb626a3ecf65da2a0d6df1ecaffc55ec8e Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 18:02:03 +0100 Subject: [PATCH 17/18] Impl HugrView using delegate --- src/hugr/view.rs | 72 ++++++++++++------------------------------------ 1 file changed, 18 insertions(+), 54 deletions(-) diff --git a/src/hugr/view.rs b/src/hugr/view.rs index ea7bc3e2c..abe681876 100644 --- a/src/hugr/view.rs +++ b/src/hugr/view.rs @@ -5,6 +5,7 @@ use std::iter::FusedIterator; use std::ops::Deref; use context_iterators::{ContextIterator, IntoContextIterator, MapCtx, MapWithCtx, WithCtx}; +use delegate::delegate; use itertools::{Itertools, MapInto}; use portgraph::dot::{DotFormat, EdgeStyle, NodeStyle, PortStyle}; use portgraph::{multiportgraph, LinkView, MultiPortGraph, PortView}; @@ -307,60 +308,23 @@ impl HugrView for &mut T { where Self: 'a; - fn root(&self) -> Node { - (**self).root() - } - - fn get_parent(&self, node: Node) -> Option { - (**self).get_parent(node) - } - - fn get_optype(&self, node: Node) -> &OpType { - (**self).get_optype(node) - } - - fn get_metadata(&self, node: Node) -> &NodeMetadata { - (**self).get_metadata(node) - } - - fn node_count(&self) -> usize { - (**self).node_count() - } - - fn edge_count(&self) -> usize { - (**self).edge_count() - } - - fn nodes(&self) -> Self::Nodes<'_> { - (**self).nodes() - } - - fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { - (**self).node_ports(node, dir) - } - - fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { - (**self).all_node_ports(node) - } - - fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { - (**self).linked_ports(node, port) - } - - fn num_ports(&self, node: Node, dir: Direction) -> usize { - (**self).num_ports(node, dir) - } - - fn children(&self, node: Node) -> Self::Children<'_> { - (**self).children(node) - } - - fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { - (**self).neighbours(node, dir) - } - - fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { - (**self).all_neighbours(node) + delegate! { + to (**self) { + fn root(&self) -> Node; + fn get_parent(&self, node: Node) -> Option; + fn get_optype(&self, node: Node) -> &OpType; + fn get_metadata(&self, node: Node) -> &NodeMetadata; + fn node_count(&self) -> usize; + fn edge_count(&self) -> usize; + fn nodes(&self) -> Self::Nodes<'_>; + fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_>; + fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_>; + fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_>; + fn num_ports(&self, node: Node, dir: Direction) -> usize; + fn children(&self, node: Node) -> Self::Children<'_>; + fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_>; + fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_>; + } } } From 3cee27a39b580ae95d5e49aa85f23cefeef048b1 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 25 Jul 2023 19:37:54 +0100 Subject: [PATCH 18/18] Reinstate BaseMut<'a>: Buildable+HugrMut and BaseView<'a> -> max 1 indirection No blanket impl Foo for &[mut] F (for Foo=HugrMut/HugrView/Buildable) Implement Buildable for + AsMut> Buildable does not require HugrMut (too awkward as needs many impls) Revert hugrmut.rs and view.rs to branch main --- Cargo.toml | 1 - src/builder/build_traits.rs | 39 ++++++----- src/builder/cfg.rs | 35 +++++----- src/builder/conditional.rs | 24 ++++--- src/builder/dataflow.rs | 34 ++++----- src/builder/module.rs | 22 +++--- src/builder/tail_loop.rs | 2 +- src/hugr/hugrmut.rs | 134 ++++++++++++++++-------------------- src/hugr/view.rs | 112 ++++++++---------------------- 9 files changed, 173 insertions(+), 230 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e59f71e64..84e5250c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ html-escape = "0.2.13" bitvec = { version = "1.0.1", features = ["serde"] } enum_dispatch = "0.3.11" lazy_static = "1.4.0" -delegate = "0.10.0" petgraph = { version="0.6.3", default-features = false} context-iterators = "0.2.0" serde_json = "1.0.97" diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index 05f0313ee..aa2098e1e 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -31,22 +31,29 @@ use crate::Hugr; use crate::hugr::HugrMut; pub trait Buildable { - type Base: HugrMut; + type BaseMut<'a>: Buildable + HugrMut + where + Self: 'a; + type BaseView<'a>: HugrView + where + Self: 'a; /// The underlying [`Hugr`] being built - fn hugr_mut(&mut self) -> &mut Self::Base; + fn hugr_mut(&mut self) -> Self::BaseMut<'_>; /// Immutable reference to HUGR being built - fn hugr(&self) -> &Self::Base; + fn hugr(&self) -> Self::BaseView<'_>; } -impl Buildable for H { - type Base = H; +impl + AsRef> Buildable for T { + type BaseMut<'a> = &'a mut Hugr where Self: 'a; - fn hugr_mut(&mut self) -> &mut Self::Base { - self + type BaseView<'a> = &'a Hugr where Self: 'a; + + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + self.as_mut() } - fn hugr(&self) -> &Self::Base { - self + fn hugr(&self) -> Self::BaseView<'_> { + self.as_ref() } } @@ -57,7 +64,6 @@ impl Buildable for H { pub trait Container: Buildable { /// The container node. fn container_node(&self) -> Node; - /// Add an [`OpType`] as the final child of the container. fn add_child_op(&mut self, op: impl Into) -> Result { let parent = self.container_node(); @@ -97,7 +103,7 @@ pub trait Container: Buildable { &mut self, name: impl Into, signature: Signature, - ) -> Result, BuildError> { + ) -> Result>, BuildError> { let f_node = self.add_child_op(ops::FuncDefn { name: name.into(), signature: signature.clone(), @@ -270,7 +276,7 @@ pub trait Dataflow: Container { &mut self, signature: Signature, input_wires: impl IntoIterator, - ) -> Result, BuildError> { + ) -> Result>, BuildError> { let (dfg_n, _) = add_op_with_wires( self, ops::DFG { @@ -296,7 +302,7 @@ pub trait Dataflow: Container { &mut self, inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result, BuildError> { + ) -> Result>, BuildError> { let (input_types, input_wires): (Vec, Vec) = inputs.into_iter().unzip(); let inputs: SimpleRow = input_types.into(); @@ -355,7 +361,7 @@ pub trait Dataflow: Container { just_inputs: impl IntoIterator, inputs_outputs: impl IntoIterator, just_out_types: ClassicRow, - ) -> Result, BuildError> { + ) -> Result>, BuildError> { let (input_types, mut input_wires): (Vec, Vec) = just_inputs.into_iter().unzip(); let (rest_types, rest_input_wires): (Vec, Vec) = @@ -389,7 +395,7 @@ pub trait Dataflow: Container { (predicate_inputs, predicate_wire): (impl IntoIterator, Wire), other_inputs: impl IntoIterator, output_types: SimpleRow, - ) -> Result, BuildError> { + ) -> Result>, BuildError> { let mut input_wires = vec![predicate_wire]; let (input_types, rest_input_wires): (Vec, Vec) = other_inputs.into_iter().unzip(); @@ -605,6 +611,7 @@ fn wire_up_inputs( let base = data_builder.hugr(); let op = base.get_optype(op_node); let some_df_outputs = !op.signature().output.is_empty(); + drop(base); if !any_local_df_inputs && some_df_outputs { // If op has no inputs add a StateOrder edge from input to place in // causal cone of Input node @@ -621,7 +628,7 @@ fn wire_up( dst: Node, dst_port: usize, ) -> Result { - let base = data_builder.hugr_mut(); + let mut base = data_builder.hugr_mut(); let src_offset = Port::new_outgoing(src_port); let src_parent = base.get_parent(src); diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 7e90cfced..5ab71137c 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -25,27 +25,28 @@ pub struct CFGBuilder { pub(super) n_out_wires: usize, } -impl Buildable for CFGBuilder { - type Base = B; +impl Buildable for CFGBuilder { + type BaseMut<'a> = B::BaseMut<'a> where Self: 'a; + type BaseView<'a> = B::BaseView<'a> where Self: 'a; #[inline] - fn hugr_mut(&mut self) -> &mut B { - &mut self.base + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + self.base.hugr_mut() } #[inline] - fn hugr(&self) -> &B { - &self.base + fn hugr(&self) -> Self::BaseView<'_> { + self.base.hugr() } } -impl Container for CFGBuilder { +impl Container for CFGBuilder { #[inline] fn container_node(&self) -> Node { self.cfg_node } } -impl SubContainer for CFGBuilder { +impl SubContainer for CFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -79,7 +80,7 @@ impl HugrBuilder for CFGBuilder { } } -impl CFGBuilder { +impl CFGBuilder { pub(super) fn create( mut base: B, cfg_node: Node, @@ -129,7 +130,7 @@ impl CFGBuilder { inputs: SimpleRow, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { self.any_block_builder(inputs, predicate_variants, other_outputs, false) } @@ -139,7 +140,7 @@ impl CFGBuilder { predicate_variants: Vec, other_outputs: SimpleRow, entry: bool, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let op = OpType::BasicBlock(BasicBlock::DFB { inputs: inputs.clone(), other_outputs: other_outputs.clone(), @@ -173,7 +174,7 @@ impl CFGBuilder { inputs: SimpleRow, outputs: SimpleRow, n_cases: usize, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { self.block_builder(inputs, vec![type_row![]; n_cases], outputs) } @@ -188,7 +189,7 @@ impl CFGBuilder { &mut self, predicate_variants: Vec, other_outputs: SimpleRow, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let inputs = self .inputs .take() @@ -206,7 +207,7 @@ impl CFGBuilder { &mut self, outputs: SimpleRow, n_cases: usize, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { self.entry_builder(vec![type_row![]; n_cases], outputs) } @@ -235,7 +236,7 @@ impl CFGBuilder { /// Builder for a [`BasicBlock::DFB`] child graph. pub type BlockBuilder = DFGWrapper; -impl BlockBuilder { +impl BlockBuilder { /// Set the outputs of the block, with `branch_wire` being the value of the /// predicate. `outputs` are the remaining outputs. pub fn set_outputs( @@ -374,7 +375,9 @@ mod test { Ok(()) } - fn build_basic_cfg(cfg_builder: &mut CFGBuilder) -> Result<(), BuildError> + fn build_basic_cfg( + cfg_builder: &mut CFGBuilder, + ) -> Result<(), BuildError> where CFGBuilder: Container, { diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index 781b4e1ed..c0ee5fe75 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -48,27 +48,28 @@ pub struct ConditionalBuilder { pub(super) case_nodes: Vec>, } -impl Buildable for ConditionalBuilder { - type Base = B; +impl Buildable for ConditionalBuilder { + type BaseMut<'a> = B::BaseMut<'a> where Self: 'a; + type BaseView<'a> = B::BaseView<'a> where Self: 'a; #[inline] - fn hugr_mut(&mut self) -> &mut Self::Base { - &mut self.base + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + self.base.hugr_mut() } #[inline] - fn hugr(&self) -> &Self::Base { - &self.base + fn hugr(&self) -> Self::BaseView<'_> { + self.base.hugr() } } -impl Container for ConditionalBuilder { +impl Container for ConditionalBuilder { #[inline] fn container_node(&self) -> Node { self.conditional_node } } -impl SubContainer for ConditionalBuilder { +impl SubContainer for ConditionalBuilder { type ContainerHandle = BuildHandle; fn finish_sub_container(self) -> Result { @@ -88,7 +89,7 @@ impl SubContainer for ConditionalBuilder { Ok((self.conditional_node, self.n_out_wires).into()) } } -impl ConditionalBuilder { +impl ConditionalBuilder { /// Return a builder the Case node with index `case`. /// /// # Panics @@ -99,7 +100,10 @@ impl ConditionalBuilder { /// /// This function will return an error if the case has already been built, /// `case` is not a valid index or if there is an error adding nodes. - pub fn case_builder(&mut self, case: usize) -> Result, BuildError> { + pub fn case_builder( + &mut self, + case: usize, + ) -> Result::BaseMut<'_>>, BuildError> { let conditional = self.conditional_node; let control_op = self.hugr().get_optype(self.conditional_node).clone(); diff --git a/src/builder/dataflow.rs b/src/builder/dataflow.rs index 405064c3c..20b8f49f6 100644 --- a/src/builder/dataflow.rs +++ b/src/builder/dataflow.rs @@ -82,27 +82,28 @@ impl HugrBuilder for DFGBuilder { } } -impl Buildable for DFGBuilder { - type Base = B; +impl Buildable for DFGBuilder { + type BaseMut<'a> = B::BaseMut<'a> where Self: 'a; + type BaseView<'a> = B::BaseView<'a> where Self: 'a; #[inline] - fn hugr_mut(&mut self) -> &mut Self::Base { - &mut self.base + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + self.base.hugr_mut() } #[inline] - fn hugr(&self) -> &Self::Base { - &self.base + fn hugr(&self) -> Self::BaseView<'_> { + self.base.hugr() } } -impl Container for DFGBuilder { +impl Container for DFGBuilder { #[inline] fn container_node(&self) -> Node { self.dfg_node } } -impl SubContainer for DFGBuilder { +impl SubContainer for DFGBuilder { type ContainerHandle = BuildHandle; #[inline] fn finish_sub_container(self) -> Result { @@ -110,7 +111,7 @@ impl SubContainer for DFGBuilder { } } -impl Dataflow for DFGBuilder { +impl Dataflow for DFGBuilder { #[inline] fn num_inputs(&self) -> usize { self.num_in_wires @@ -150,34 +151,35 @@ impl FunctionBuilder { } } -impl Buildable for DFGWrapper { - type Base = B; +impl Buildable for DFGWrapper { + type BaseMut<'a> = B::BaseMut<'a> where Self: 'a; + type BaseView<'a> = B::BaseView<'a> where Self: 'a; #[inline] - fn hugr_mut(&mut self) -> &mut Self::Base { + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { self.0.hugr_mut() } #[inline] - fn hugr(&self) -> &Self::Base { + fn hugr(&self) -> Self::BaseView<'_> { self.0.hugr() } } -impl Container for DFGWrapper { +impl Container for DFGWrapper { #[inline] fn container_node(&self) -> Node { self.0.container_node() } } -impl Dataflow for DFGWrapper { +impl Dataflow for DFGWrapper { #[inline] fn num_inputs(&self) -> usize { Dataflow::num_inputs(&self.0) } } -impl>> SubContainer for DFGWrapper { +impl>> SubContainer for DFGWrapper { type ContainerHandle = T; #[inline] diff --git a/src/builder/module.rs b/src/builder/module.rs index 225a226ec..7a402d83a 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -4,7 +4,7 @@ use super::{ BuildError, Container, }; -use crate::{hugr::ValidationError, ops, types::SimpleType}; +use crate::{hugr::ValidationError, ops, types::SimpleType, HugrView}; use crate::ops::handle::{AliasID, FuncID, NodeHandle}; use crate::ops::OpType; @@ -19,19 +19,21 @@ use crate::{hugr::HugrMut, Hugr}; /// Builder for a HUGR module. #[derive(Debug, Clone, PartialEq)] pub struct ModuleBuilder(pub(super) T); -impl Buildable for ModuleBuilder { - type Base = B; +impl Buildable for ModuleBuilder { + type BaseMut<'a> = B::BaseMut<'a> where Self: 'a; + type BaseView<'a> = B::BaseView<'a> where Self: 'a; + #[inline] - fn hugr_mut(&mut self) -> &mut Self::Base { - &mut self.0 + fn hugr_mut(&mut self) -> Self::BaseMut<'_> { + self.0.hugr_mut() } - fn hugr(&self) -> &Self::Base { - &self.0 + fn hugr(&self) -> Self::BaseView<'_> { + self.0.hugr() } } -impl Container for ModuleBuilder { +impl Container for ModuleBuilder { #[inline] fn container_node(&self) -> Node { self.0.root() @@ -59,7 +61,7 @@ impl HugrBuilder for ModuleBuilder { } } -impl ModuleBuilder { +impl ModuleBuilder { /// Replace a [`ops::FuncDecl`] with [`ops::FuncDefn`] and return a builder for /// the defining graph. /// @@ -70,7 +72,7 @@ impl ModuleBuilder { pub fn define_declaration( &mut self, f_id: &FuncID, - ) -> Result, BuildError> { + ) -> Result::BaseMut<'_>>, BuildError> { let f_node = f_id.node(); let (signature, name) = if let OpType::FuncDecl(ops::FuncDecl { signature, name }) = self.hugr().get_optype(f_node) diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index 3b4f091ea..3c55715e5 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -15,7 +15,7 @@ use super::{ /// Builder for a [`ops::TailLoop`] node. pub type TailLoopBuilder = DFGWrapper>; -impl TailLoopBuilder { +impl TailLoopBuilder { pub(super) fn create_with_io( base: B, loop_node: Node, diff --git a/src/hugr/hugrmut.rs b/src/hugr/hugrmut.rs index b07a4bfba..248332d51 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -1,6 +1,5 @@ //! Base HUGR builder providing low-level building blocks. -use delegate::delegate; use std::collections::HashMap; use std::ops::Range; @@ -145,27 +144,33 @@ pub trait HugrMut: HugrView { fn canonicalize_nodes(&mut self, rekey: impl FnMut(Node, Node)); } -impl HugrMut for Hugr { +impl HugrMut for T +where + T: AsRef + AsMut, +{ fn add_op(&mut self, op: impl Into) -> Node { let op: OpType = op.into(); - let node = self.graph.add_node(op.input_count(), op.output_count()); - self.op_types[node] = op; + let node = self + .as_mut() + .graph + .add_node(op.input_count(), op.output_count()); + self.as_mut().op_types[node] = op; node.into() } fn remove_node(&mut self, node: Node) -> Result<(), HugrError> { - if node.index == self.root { + if node.index == self.as_ref().root { // TODO: Add a HugrMutError ? panic!("cannot remove root node"); } - self.hierarchy.remove(node.index); - self.graph.remove_node(node.index); - self.op_types.remove(node.index); + self.as_mut().hierarchy.remove(node.index); + self.as_mut().graph.remove_node(node.index); + self.as_mut().op_types.remove(node.index); Ok(()) } fn get_metadata_mut(&mut self, node: Node) -> &mut NodeMetadata { - self.metadata.get_mut(node.index) + self.as_mut().metadata.get_mut(node.index) } fn connect( @@ -175,20 +180,21 @@ impl HugrMut for Hugr { dst: Node, dst_port: usize, ) -> Result<(), HugrError> { - self.graph + self.as_mut() + .graph .link_nodes(src.index, src_port, dst.index, dst_port)?; Ok(()) } fn disconnect(&mut self, node: Node, port: Port) -> Result<(), HugrError> { let offset = port.offset; - let port = self.graph.port_index(node.index, offset).ok_or( + let port = self.as_mut().graph.port_index(node.index, offset).ok_or( portgraph::LinkError::UnknownOffset { node: node.index, offset, }, )?; - self.graph.unlink_port(port); + self.as_mut().graph.unlink_port(port); Ok(()) } @@ -207,14 +213,15 @@ impl HugrMut for Hugr { #[inline] fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) { - self.graph + self.as_mut() + .graph .set_num_ports(node.index, incoming, outgoing, |_, _| {}) } #[inline] fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range { - let mut incoming = self.graph.num_inputs(node.index); - let mut outgoing = self.graph.num_outputs(node.index); + let mut incoming = self.as_mut().graph.num_inputs(node.index); + let mut outgoing = self.as_mut().graph.num_outputs(node.index); let increment = |num: &mut usize| { let new = num.saturating_add_signed(amount); let range = *num..new; @@ -225,26 +232,33 @@ impl HugrMut for Hugr { Direction::Incoming => increment(&mut incoming), Direction::Outgoing => increment(&mut outgoing), }; - self.graph + self.as_mut() + .graph .set_num_ports(node.index, incoming, outgoing, |_, _| {}); range } fn set_parent(&mut self, node: Node, parent: Node) -> Result<(), HugrError> { - self.hierarchy.detach(node.index); - self.hierarchy.push_child(node.index, parent.index)?; + self.as_mut().hierarchy.detach(node.index); + self.as_mut() + .hierarchy + .push_child(node.index, parent.index)?; Ok(()) } fn move_after_sibling(&mut self, node: Node, after: Node) -> Result<(), HugrError> { - self.hierarchy.detach(node.index); - self.hierarchy.insert_after(node.index, after.index)?; + self.as_mut().hierarchy.detach(node.index); + self.as_mut() + .hierarchy + .insert_after(node.index, after.index)?; Ok(()) } fn move_before_sibling(&mut self, node: Node, before: Node) -> Result<(), HugrError> { - self.hierarchy.detach(node.index); - self.hierarchy.insert_before(node.index, before.index)?; + self.as_mut().hierarchy.detach(node.index); + self.as_mut() + .hierarchy + .insert_before(node.index, before.index)?; Ok(()) } @@ -254,47 +268,53 @@ impl HugrMut for Hugr { op: impl Into, ) -> Result { let node = self.add_op(op.into()); - self.hierarchy.push_child(node.index, parent.index)?; + self.as_mut() + .hierarchy + .push_child(node.index, parent.index)?; Ok(node) } fn add_op_before(&mut self, sibling: Node, op: impl Into) -> Result { let node = self.add_op(op.into()); - self.hierarchy.insert_before(node.index, sibling.index)?; + self.as_mut() + .hierarchy + .insert_before(node.index, sibling.index)?; Ok(node) } fn add_op_after(&mut self, sibling: Node, op: impl Into) -> Result { let node = self.add_op(op.into()); - self.hierarchy.insert_after(node.index, sibling.index)?; + self.as_mut() + .hierarchy + .insert_after(node.index, sibling.index)?; Ok(node) } fn replace_op(&mut self, node: Node, op: impl Into) -> OpType { - let cur = self.op_types.get_mut(node.index); + let cur = self.as_mut().op_types.get_mut(node.index); std::mem::replace(cur, op.into()) } fn insert_hugr(&mut self, root: Node, mut other: Hugr) -> Result { - let (other_root, node_map) = insert_hugr_internal(self, root, &other)?; + let (other_root, node_map) = insert_hugr_internal(self.as_mut(), root, &other)?; // Update the optypes and metadata, taking them from the other graph. for (&node, &new_node) in node_map.iter() { let optype = other.op_types.take(node); - self.op_types.set(new_node, optype); + self.as_mut().op_types.set(new_node, optype); let meta = other.metadata.take(node); - self.set_metadata(node.into(), meta); + self.as_mut().set_metadata(node.into(), meta); } Ok(other_root) } fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> Result { - let (other_root, node_map) = insert_hugr_internal(self, root, other)?; + let (other_root, node_map) = insert_hugr_internal(self.as_mut(), root, other)?; // Update the optypes and metadata, copying them from the other graph. for (&node, &new_node) in node_map.iter() { let optype = other.get_optype(node.into()); - self.op_types.set(new_node, optype.clone()); + self.as_mut().op_types.set(new_node, optype.clone()); let meta = other.get_metadata(node.into()); - self.set_metadata(node.into(), meta.clone()); + self.as_mut().set_metadata(node.into(), meta.clone()); } Ok(other_root) } @@ -317,57 +337,19 @@ impl HugrMut for Hugr { let target: Node = NodeIndex::new(position).into(); if target != source { - self.graph.swap_nodes(target.index, source.index); - self.op_types.swap(target.index, source.index); - self.hierarchy.swap_nodes(target.index, source.index); + let hugr = self.as_mut(); + hugr.graph.swap_nodes(target.index, source.index); + hugr.op_types.swap(target.index, source.index); + hugr.hierarchy.swap_nodes(target.index, source.index); rekey(source, target); } } - self.root = NodeIndex::new(0); + self.as_mut().root = NodeIndex::new(0); // Finish by compacting the copy nodes. // The operation nodes will be left in place. // This step is not strictly necessary. - self.graph.compact_nodes(|_, _| {}); - } -} - -impl HugrMut for &mut T { - delegate! { - to (*self) { - fn add_op(&mut self, op: impl Into) -> Node; - fn remove_node(&mut self, node: Node) -> Result<(), HugrError>; - fn get_metadata_mut(&mut self, node: Node) -> &mut NodeMetadata; - - fn connect( - &mut self, - src: Node, - src_port: usize, - dst: Node, - dst_port: usize, - ) -> Result<(), HugrError>; - - fn disconnect(&mut self, node: Node, port: Port) -> Result<(), HugrError>; - fn add_other_edge(&mut self, src: Node, dst: Node) -> Result<(Port, Port), HugrError>; - fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize); - fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range; - fn set_parent(&mut self, node: Node, parent: Node) -> Result<(), HugrError>; - fn move_after_sibling(&mut self, node: Node, after: Node) -> Result<(), HugrError>; - fn move_before_sibling(&mut self, node: Node, before: Node) -> Result<(), HugrError>; - - fn add_op_with_parent( - &mut self, - parent: Node, - op: impl Into, - ) -> Result; - - fn add_op_before(&mut self, sibling: Node, op: impl Into) -> Result; - fn add_op_after(&mut self, sibling: Node, op: impl Into) -> Result; - fn replace_op(&mut self, node: Node, op: impl Into) -> OpType; - fn insert_hugr(&mut self, root: Node, other: Hugr) -> Result; - fn insert_from_view(&mut self, root: Node, other: &impl HugrView) -> Result; - fn canonicalize_nodes(&mut self, rekey: impl FnMut(Node, Node)); - } + self.as_mut().graph.compact_nodes(|_, _| {}); } } diff --git a/src/hugr/view.rs b/src/hugr/view.rs index abe681876..25a248850 100644 --- a/src/hugr/view.rs +++ b/src/hugr/view.rs @@ -5,7 +5,6 @@ use std::iter::FusedIterator; use std::ops::Deref; use context_iterators::{ContextIterator, IntoContextIterator, MapCtx, MapWithCtx, WithCtx}; -use delegate::delegate; use itertools::{Itertools, MapInto}; use portgraph::dot::{DotFormat, EdgeStyle, NodeStyle, PortStyle}; use portgraph::{multiportgraph, LinkView, MultiPortGraph, PortView}; @@ -189,7 +188,10 @@ pub trait HugrView: sealed::HugrInternals { } } -impl HugrView for Hugr { +impl HugrView for T +where + T: AsRef, +{ /// An Iterator over the nodes in a Hugr(View) type Nodes<'a> = MapInto, Node> where Self: 'a; @@ -209,50 +211,51 @@ impl HugrView for Hugr { #[inline] fn root(&self) -> Node { - self.root.into() + self.as_ref().root.into() } #[inline] fn get_parent(&self, node: Node) -> Option { - self.hierarchy.parent(node.index).map(Into::into) + self.as_ref().hierarchy.parent(node.index).map(Into::into) } #[inline] fn get_optype(&self, node: Node) -> &OpType { - self.op_types.get(node.index) + self.as_ref().op_types.get(node.index) } #[inline] fn node_count(&self) -> usize { - self.graph.node_count() + self.as_ref().graph.node_count() } #[inline] fn edge_count(&self) -> usize { - self.graph.link_count() + self.as_ref().graph.link_count() } #[inline] fn nodes(&self) -> Self::Nodes<'_> { - self.graph.nodes_iter().map_into() + self.as_ref().graph.nodes_iter().map_into() } #[inline] fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { - self.graph.port_offsets(node.index, dir).map_into() + self.as_ref().graph.port_offsets(node.index, dir).map_into() } #[inline] fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { - self.graph.all_port_offsets(node.index).map_into() + self.as_ref().graph.all_port_offsets(node.index).map_into() } #[inline] fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { - let port = self.graph.port_index(node.index, port.offset).unwrap(); - self.graph + let hugr = self.as_ref(); + let port = hugr.graph.port_index(node.index, port.offset).unwrap(); + hugr.graph .port_links(port) - .with_context(self) + .with_context(hugr) .map_with_context(|(_, link), hugr| { let port = link.port(); let node = hugr.graph.port_node(port).unwrap(); @@ -263,68 +266,27 @@ impl HugrView for Hugr { #[inline] fn num_ports(&self, node: Node, dir: Direction) -> usize { - self.graph.num_ports(node.index, dir) + self.as_ref().graph.num_ports(node.index, dir) } #[inline] fn children(&self, node: Node) -> Self::Children<'_> { - self.hierarchy.children(node.index).map_into() + self.as_ref().hierarchy.children(node.index).map_into() } #[inline] fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { - self.graph.neighbours(node.index, dir).map_into() + self.as_ref().graph.neighbours(node.index, dir).map_into() } #[inline] fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { - self.graph.all_neighbours(node.index).map_into() + self.as_ref().graph.all_neighbours(node.index).map_into() } #[inline] fn get_metadata(&self, node: Node) -> &NodeMetadata { - self.metadata.get(node.index) - } -} - -impl HugrView for &mut T { - type Nodes<'a> = T::Nodes<'a> - where - Self: 'a; - - type NodePorts<'a> = T::NodePorts<'a> - where - Self: 'a; - - type Children<'a> = T::Children<'a> - where - Self: 'a; - - type Neighbours<'a> = T::Neighbours<'a> - where - Self: 'a; - - type PortLinks<'a> = T::PortLinks<'a> - where - Self: 'a; - - delegate! { - to (**self) { - fn root(&self) -> Node; - fn get_parent(&self, node: Node) -> Option; - fn get_optype(&self, node: Node) -> &OpType; - fn get_metadata(&self, node: Node) -> &NodeMetadata; - fn node_count(&self) -> usize; - fn edge_count(&self) -> usize; - fn nodes(&self) -> Self::Nodes<'_>; - fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_>; - fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_>; - fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_>; - fn num_ports(&self, node: Node, dir: Direction) -> usize; - fn children(&self, node: Node) -> Self::Children<'_>; - fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_>; - fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_>; - } + self.as_ref().metadata.get(node.index) } } @@ -346,38 +308,20 @@ pub(crate) mod sealed { fn base_hugr(&self) -> &Hugr; } - impl HugrInternals for Hugr { + impl HugrInternals for T + where + T: AsRef, + { type Portgraph = MultiPortGraph; #[inline] fn portgraph(&self) -> &Self::Portgraph { - &self.graph - } - - fn base_hugr(&self) -> &Hugr { - self - } - } - - impl HugrInternals for &mut T { - type Portgraph = T::Portgraph; - fn portgraph(&self) -> &Self::Portgraph { - (**self).portgraph() - } - - fn base_hugr(&self) -> &Hugr { - (**self).base_hugr() - } - } - - impl HugrInternals for &T { - type Portgraph = T::Portgraph; - fn portgraph(&self) -> &Self::Portgraph { - (**self).portgraph() + &self.as_ref().graph } + #[inline] fn base_hugr(&self) -> &Hugr { - (**self).base_hugr() + self.as_ref() } } }