Skip to content

Commit fbbf237

Browse files
authored
feat: Export the portgraph hierarchy in HugrInternals (#2057)
Currently external packages can query the hugr's portgraph, but they cannot access the associated hierarchy. This non-breaking change adds a default-implemented method to `HugrInternals` that returns it. It returns a `Cow` instead of a straight reference, that can be used for more exotic hugr wrappers. See the `base_hugr` refactoring issue for more discussion: #1926 We don't expose a mutable ref, modifications can be done via `HugrMutInternals` methods.
1 parent 3c1d25b commit fbbf237

File tree

4 files changed

+24
-4
lines changed

4 files changed

+24
-4
lines changed

hugr-core/src/hugr/internal.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ pub trait HugrInternals {
3232
/// Returns a reference to the underlying portgraph.
3333
fn portgraph(&self) -> Self::Portgraph<'_>;
3434

35+
/// Returns the portgraph [Hierarchy](portgraph::Hierarchy) of the graph
36+
/// returned by [`HugrInternals::portgraph`].
37+
#[inline]
38+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy> {
39+
Cow::Borrowed(&self.base_hugr().hierarchy)
40+
}
41+
3542
/// Returns the Hugr at the base of a chain of views.
3643
fn base_hugr(&self) -> &Hugr;
3744

@@ -58,6 +65,11 @@ impl HugrInternals for Hugr {
5865
&self.graph
5966
}
6067

68+
#[inline]
69+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy> {
70+
Cow::Borrowed(&self.hierarchy)
71+
}
72+
6173
#[inline]
6274
fn base_hugr(&self) -> &Hugr {
6375
self
@@ -87,6 +99,7 @@ impl<T: HugrInternals> HugrInternals for &T {
8799
delegate! {
88100
to (**self) {
89101
fn portgraph(&self) -> Self::Portgraph<'_>;
102+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy>;
90103
fn base_hugr(&self) -> &Hugr;
91104
fn root_node(&self) -> Self::Node;
92105
fn get_pg_index(&self, node: Self::Node) -> portgraph::NodeIndex;
@@ -105,6 +118,7 @@ impl<T: HugrInternals> HugrInternals for &mut T {
105118
delegate! {
106119
to (**self) {
107120
fn portgraph(&self) -> Self::Portgraph<'_>;
121+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy>;
108122
fn base_hugr(&self) -> &Hugr;
109123
fn root_node(&self) -> Self::Node;
110124
fn get_pg_index(&self, node: Self::Node) -> portgraph::NodeIndex;
@@ -123,6 +137,7 @@ impl<T: HugrInternals> HugrInternals for Rc<T> {
123137
delegate! {
124138
to (**self) {
125139
fn portgraph(&self) -> Self::Portgraph<'_>;
140+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy>;
126141
fn base_hugr(&self) -> &Hugr;
127142
fn root_node(&self) -> Self::Node;
128143
fn get_pg_index(&self, node: Self::Node) -> portgraph::NodeIndex;
@@ -141,6 +156,7 @@ impl<T: HugrInternals> HugrInternals for Arc<T> {
141156
delegate! {
142157
to (**self) {
143158
fn portgraph(&self) -> Self::Portgraph<'_>;
159+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy>;
144160
fn base_hugr(&self) -> &Hugr;
145161
fn root_node(&self) -> Self::Node;
146162
fn get_pg_index(&self, node: Self::Node) -> portgraph::NodeIndex;
@@ -159,6 +175,7 @@ impl<T: HugrInternals> HugrInternals for Box<T> {
159175
delegate! {
160176
to (**self) {
161177
fn portgraph(&self) -> Self::Portgraph<'_>;
178+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy>;
162179
fn base_hugr(&self) -> &Hugr;
163180
fn root_node(&self) -> Self::Node;
164181
fn get_pg_index(&self, node: Self::Node) -> portgraph::NodeIndex;
@@ -177,6 +194,7 @@ impl<T: HugrInternals + ToOwned> HugrInternals for Cow<'_, T> {
177194
delegate! {
178195
to self.as_ref() {
179196
fn portgraph(&self) -> Self::Portgraph<'_>;
197+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy>;
180198
fn base_hugr(&self) -> &Hugr;
181199
fn root_node(&self) -> Self::Node;
182200
fn get_pg_index(&self, node: Self::Node) -> portgraph::NodeIndex;

hugr-core/src/hugr/validate.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::types::type_param::TypeParam;
1919
use crate::types::EdgeKind;
2020
use crate::{Direction, Hugr, Node, Port};
2121

22+
use super::internal::HugrInternals;
2223
use super::views::{HierarchyView, HugrView, SiblingGraph};
2324
use super::ExtensionError;
2425

@@ -104,7 +105,7 @@ impl<'a> ValidationContext<'a> {
104105
/// Check the validity of the HUGR.
105106
pub fn validate(&mut self) -> Result<(), ValidationError> {
106107
// Root node must be a root in the hierarchy.
107-
if !self.hugr.hierarchy.is_root(self.hugr.root) {
108+
if !self.hugr.hierarchy().is_root(self.hugr.root) {
108109
return Err(ValidationError::RootNotRoot {
109110
node: self.hugr.root(),
110111
});
@@ -315,7 +316,7 @@ impl<'a> ValidationContext<'a> {
315316
fn validate_children(&self, node: Node, op_type: &OpType) -> Result<(), ValidationError> {
316317
let flags = op_type.validity_flags();
317318

318-
if self.hugr.hierarchy.child_count(node.pg_index()) > 0 {
319+
if self.hugr.hierarchy().child_count(node.pg_index()) > 0 {
319320
if flags.allowed_children.is_empty() {
320321
return Err(ValidationError::NonContainerWithChildren {
321322
node,
@@ -362,7 +363,7 @@ impl<'a> ValidationContext<'a> {
362363

363364
// Additional validations running over the edges of the contained graph
364365
if let Some(edge_check) = flags.edge_check {
365-
for source in self.hugr.hierarchy.children(node.pg_index()) {
366+
for source in self.hugr.hierarchy().children(node.pg_index()) {
366367
for target in self.hugr.graph.output_neighbours(source) {
367368
if self.hugr.hierarchy.parent(target) != Some(node.pg_index()) {
368369
continue;

hugr-core/src/hugr/views/descendants.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ where
169169
&self.graph
170170
}
171171

172-
#[inline]
173172
fn base_hugr(&self) -> &Hugr {
174173
self.hugr
175174
}

hugr-core/src/hugr/views/root_checked.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::marker::PhantomData;
23

34
use delegate::delegate;
@@ -58,6 +59,7 @@ impl<H: AsRef<Hugr>, Root> HugrInternals for RootChecked<H, Root> {
5859
delegate! {
5960
to self.as_ref() {
6061
fn portgraph(&self) -> Self::Portgraph<'_>;
62+
fn hierarchy(&self) -> Cow<'_, portgraph::Hierarchy>;
6163
fn base_hugr(&self) -> &Hugr;
6264
fn root_node(&self) -> Node;
6365
fn get_pg_index(&self, node: Node) -> portgraph::NodeIndex;

0 commit comments

Comments
 (0)