Skip to content

Commit

Permalink
feat: add ApplyResult associated type to Rewrite (#472)
Browse files Browse the repository at this point in the history
Closes #471

BREAKING CHANGE: implementers of `Rewrite` must define `ApplyResult`.

---------

Co-authored-by: Agustín Borgna <121866228+aborgna-q@users.noreply.github.com>
  • Loading branch information
ss2165 and aborgna-q authored Aug 31, 2023
1 parent 60bc143 commit 1aaecb0
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 4 deletions.
5 changes: 4 additions & 1 deletion src/hugr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ pub type Direction = portgraph::Direction;
/// Public API for HUGRs.
impl Hugr {
/// Applies a rewrite to the graph.
pub fn apply_rewrite<E>(&mut self, rw: impl Rewrite<Error = E>) -> Result<(), E> {
pub fn apply_rewrite<R, E>(
&mut self,
rw: impl Rewrite<ApplyResult = R, Error = E>,
) -> Result<R, E> {
rw.apply(self)
}

Expand Down
9 changes: 6 additions & 3 deletions src/hugr/rewrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ pub use simple_replace::{SimpleReplacement, SimpleReplacementError};
pub trait Rewrite {
/// The type of Error with which this Rewrite may fail
type Error: std::error::Error;

/// The type returned on successful application of the rewrite.
type ApplyResult;
/// If `true`, [self.apply]'s of this rewrite guarantee that they do not mutate the Hugr when they return an Err.
/// If `false`, there is no guarantee; the Hugr should be assumed invalid when Err is returned.
const UNCHANGED_ON_FAILURE: bool;
Expand All @@ -22,13 +23,14 @@ pub trait Rewrite {
fn verify(&self, h: &Hugr) -> Result<(), Self::Error>;

/// Mutate the specified Hugr, or fail with an error.
/// Returns [`Self::ApplyResult`] if successful.
/// If [self.unchanged_on_failure] is true, then `h` must be unchanged if Err is returned.
/// See also [self.verify]
/// # Panics
/// May panic if-and-only-if `h` would have failed [Hugr::validate]; that is,
/// implementations may begin with `assert!(h.validate())`, with `debug_assert!(h.validate())`
/// being preferred.
fn apply(self, h: &mut Hugr) -> Result<(), Self::Error>;
fn apply(self, h: &mut Hugr) -> Result<Self::ApplyResult, Self::Error>;
}

/// Wraps any rewrite into a transaction (i.e. that has no effect upon failure)
Expand All @@ -40,13 +42,14 @@ pub struct Transactional<R> {
// is not yet supported, https://github.com/rust-lang/rust/issues/92827
impl<R: Rewrite> Rewrite for Transactional<R> {
type Error = R::Error;
type ApplyResult = R::ApplyResult;
const UNCHANGED_ON_FAILURE: bool = true;

fn verify(&self, h: &Hugr) -> Result<(), Self::Error> {
self.underlying.verify(h)
}

fn apply(self, h: &mut Hugr) -> Result<(), Self::Error> {
fn apply(self, h: &mut Hugr) -> Result<Self::ApplyResult, Self::Error> {
if R::UNCHANGED_ON_FAILURE {
return self.underlying.apply(h);
}
Expand Down
2 changes: 2 additions & 0 deletions src/hugr/rewrite/outline_cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ impl OutlineCfg {

impl Rewrite for OutlineCfg {
type Error = OutlineCfgError;
type ApplyResult = ();

const UNCHANGED_ON_FAILURE: bool = true;
fn verify(&self, h: &Hugr) -> Result<(), OutlineCfgError> {
self.compute_entry_exit_outside(h)?;
Expand Down
2 changes: 2 additions & 0 deletions src/hugr/rewrite/simple_replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ impl SimpleReplacement {

impl Rewrite for SimpleReplacement {
type Error = SimpleReplacementError;
type ApplyResult = ();

const UNCHANGED_ON_FAILURE: bool = true;

fn verify(&self, _h: &Hugr) -> Result<(), SimpleReplacementError> {
Expand Down

0 comments on commit 1aaecb0

Please sign in to comment.