Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions hugr-core/src/hugr/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,27 @@ pub trait PatchVerification {
/// error.
fn verify(&self, h: &impl HugrView<Node = Self::Node>) -> Result<(), Self::Error>;

/// Returns a set of nodes referenced by the rewrite. Modifying any of these
/// nodes will invalidate it.
/// The nodes invalidated by the rewrite. Deprecated: implement
/// [Self::invalidated_nodes] instead. The default returns the empty
/// iterator; this should be fine as there are no external calls.
#[deprecated(note = "Use/implement invalidated_nodes instead")]
fn invalidation_set(&self) -> impl Iterator<Item = Self::Node> {
std::iter::empty()
}

/// Returns the nodes removed or altered by the rewrite. Modifying any of these
/// nodes will invalidate the rewrite.
///
/// Two `impl Rewrite`s can be composed if their invalidation sets are
/// Two `impl Rewrite`s can be composed if their `invalidated_nodes` are
/// disjoint.
fn invalidation_set(&self) -> impl Iterator<Item = Self::Node>;
fn invalidated_nodes(
&self,
h: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
let _ = h;
#[expect(deprecated)]
self.invalidation_set()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me a little nervous - rather than being breaking when we remove invalidation_set, is it better just to be breaking now? what do you think?

}
}

/// A patch that can be applied to a mutable Hugr of type `H`.
Expand Down Expand Up @@ -142,8 +157,11 @@ impl<R: PatchVerification> PatchVerification for Transactional<R> {
}

#[inline]
fn invalidation_set(&self) -> impl Iterator<Item = Self::Node> {
self.underlying.invalidation_set()
fn invalidated_nodes(
&self,
h: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
self.underlying.invalidated_nodes(h)
}
}

Expand Down
14 changes: 10 additions & 4 deletions hugr-core/src/hugr/patch/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ impl<N: HugrNode> PatchVerification for RemoveLoadConstant<N> {
Ok(())
}

fn invalidation_set(&self) -> impl Iterator<Item = N> {
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
iter::once(self.0)
}
}
Expand Down Expand Up @@ -93,7 +96,10 @@ impl<N: HugrNode> PatchVerification for RemoveConst<N> {
Ok(())
}

fn invalidation_set(&self) -> impl Iterator<Item = N> {
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
iter::once(self.0)
}
}
Expand Down Expand Up @@ -158,15 +164,15 @@ mod test {

let remove_1 = RemoveLoadConstant(load_1_node);
assert_eq!(
remove_1.invalidation_set().exactly_one().ok(),
remove_1.invalidated_nodes(&h).exactly_one().ok(),
Some(load_1_node)
);

let remove_2 = RemoveLoadConstant(load_2_node);

let remove_con = RemoveConst(con_node);
assert_eq!(
remove_con.invalidation_set().exactly_one().ok(),
remove_con.invalidated_nodes(&h).exactly_one().ok(),
Some(con_node)
);

Expand Down
2 changes: 1 addition & 1 deletion hugr-core/src/hugr/patch/inline_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<N: HugrNode> PatchVerification for InlineCall<N> {
Ok(())
}

fn invalidation_set(&self) -> impl Iterator<Item = N> {
fn invalidated_nodes(&self, _: &impl HugrView<Node = N>) -> impl Iterator<Item = N> {
Some(self.0).into_iter()
}
}
Expand Down
7 changes: 5 additions & 2 deletions hugr-core/src/hugr/patch/inline_dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use super::{PatchHugrMut, PatchVerification};
use crate::ops::handle::{DfgID, NodeHandle};
use crate::{IncomingPort, Node, OutgoingPort, PortIndex};
use crate::{HugrView, IncomingPort, Node, OutgoingPort, PortIndex};

/// Structure identifying an `InlineDFG` rewrite from the spec
pub struct InlineDFG(pub DfgID);
Expand Down Expand Up @@ -43,7 +43,10 @@ impl PatchVerification for InlineDFG {
Ok(())
}

fn invalidation_set(&self) -> impl Iterator<Item = Node> {
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
[self.0.node()].into_iter()
}
}
Expand Down
7 changes: 5 additions & 2 deletions hugr-core/src/hugr/patch/insert_cut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ impl<N: HugrNode> PatchVerification for InsertCut<N> {
}

#[inline]
fn invalidation_set(&self) -> impl Iterator<Item = N> {
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
iter::once(self.parent)
.chain(self.targets.iter().map(|(n, _)| *n))
.unique()
Expand Down Expand Up @@ -179,7 +182,7 @@ mod tests {
let targets: Vec<_> = h.all_linked_inputs(i).collect();
let inserter = InsertCut::new(h.entrypoint(), targets, replacement);
assert_eq!(
inserter.invalidation_set().collect::<Vec<Node>>(),
inserter.invalidated_nodes(&h).collect::<Vec<Node>>(),
vec![h.entrypoint(), o]
);

Expand Down
5 changes: 4 additions & 1 deletion hugr-core/src/hugr/patch/insert_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ impl<N: HugrNode> PatchVerification for IdentityInsertion<N> {
}

#[inline]
fn invalidation_set(&self) -> impl Iterator<Item = N> {
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
iter::once(self.post_node)
}
}
Expand Down
5 changes: 4 additions & 1 deletion hugr-core/src/hugr/patch/outline_cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ impl PatchVerification for OutlineCfg {
Ok(())
}

fn invalidation_set(&self) -> impl Iterator<Item = Node> {
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
self.blocks.iter().copied()
}
}
Expand Down
5 changes: 4 additions & 1 deletion hugr-core/src/hugr/patch/replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,10 @@ impl<HostNode: HugrNode> PatchVerification for Replacement<HostNode> {
Ok(())
}

fn invalidation_set(&self) -> impl Iterator<Item = HostNode> {
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
self.removal.iter().copied()
}
}
Expand Down
14 changes: 11 additions & 3 deletions hugr-core/src/hugr/patch/simple_replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,11 @@ impl<HostNode: HugrNode> SimpleReplacement<HostNode> {
let subgraph = subgraph.map_nodes(node_map);
SimpleReplacement::try_new(subgraph, new_host, replacement.clone())
}

/// Allows to get the [Self::invalidated_nodes] without requiring a [HugrView].
pub fn invalidation_set(&self) -> impl Iterator<Item = HostNode> {
self.subgraph.nodes().iter().copied()
}
}

impl<HostNode: HugrNode> PatchVerification for SimpleReplacement<HostNode> {
Expand All @@ -527,8 +532,11 @@ impl<HostNode: HugrNode> PatchVerification for SimpleReplacement<HostNode> {
}

#[inline]
fn invalidation_set(&self) -> impl Iterator<Item = HostNode> {
self.subgraph.nodes().iter().copied()
fn invalidated_nodes(
&self,
_: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
self.invalidation_set()
}
}

Expand Down Expand Up @@ -864,7 +872,7 @@ pub(in crate::hugr::patch) mod test {

// Check invalidation set
assert_eq!(
HashSet::<_>::from_iter(r.invalidation_set()),
HashSet::<_>::from_iter(r.invalidated_nodes(&h)),
HashSet::<_>::from_iter([h_node_cx, h_node_h0, h_node_h1]),
);

Expand Down
5 changes: 3 additions & 2 deletions hugr-persistent/src/persistent_hugr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use delegate::delegate;
use derive_more::derive::From;
use hugr_core::{
Hugr, HugrView, IncomingPort, Node, OutgoingPort, Port, SimpleReplacement,
hugr::patch::{Patch, PatchVerification, simple_replace},
hugr::patch::{Patch, simple_replace},
};
use itertools::{Either, Itertools};
use relrc::RelRc;
Expand Down Expand Up @@ -170,7 +170,8 @@ impl<'a> From<&'a RelRc<CommitData, ()>> for &'a Commit {
/// [`PersistentHugr`] implements [`HugrView`], so that it can used as
/// a drop-in substitute for a Hugr wherever read-only access is required. It
/// does not implement [`HugrMut`](hugr_core::hugr::hugrmut::HugrMut), however.
/// Mutations must be performed by applying patches (see [`PatchVerification`]
/// Mutations must be performed by applying patches (see
/// [`PatchVerification`](hugr_core::hugr::patch::PatchVerification)
/// and [`Patch`]). Currently, only [`SimpleReplacement`] patches are supported.
/// You can use [`Self::add_replacement`] to add a patch to `self`, or use the
/// aforementioned patch traits.
Expand Down
Loading