From cea0745d3b7cceb50f593671562a8fe1af323d89 Mon Sep 17 00:00:00 2001 From: Douglas Wilson Date: Tue, 14 May 2024 10:53:33 +0100 Subject: [PATCH 1/4] Revert "remove `VerifyLevel` etc, assert! -> debug_assert!" This reverts commit 20b35d67cbf3c778abd67757c0c4d8cf1954a9e0. --- hugr/src/algorithm.rs | 31 +++++++++ hugr/src/algorithm/const_fold.rs | 114 ++++++++++++++++++++----------- 2 files changed, 107 insertions(+), 38 deletions(-) diff --git a/hugr/src/algorithm.rs b/hugr/src/algorithm.rs index 585e25a01..403632ecd 100644 --- a/hugr/src/algorithm.rs +++ b/hugr/src/algorithm.rs @@ -4,3 +4,34 @@ pub mod const_fold; mod half_node; pub mod merge_bbs; pub mod nest_cfgs; + +#[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq)] +/// A type for algorithms to take as configuration, specifying how much +/// verification they should do. Algorithms that accept this configuration +/// should at least verify that input HUGRs are valid, and that output HUGRs are +/// valid. +/// +/// The default level is `None` because verification can be expensive. +pub enum VerifyLevel { + /// Do no verification. + None, + /// Verify using [HugrView::validate_no_extensions]. This is useful when you + /// do not expect valid Extension annotations on Nodes. + /// + /// [HugrView::validate_no_extensions]: crate::HugrView::validate_no_extensions + WithoutExtensions, + /// Verify using [HugrView::validate]. + /// + /// [HugrView::validate]: crate::HugrView::validate + WithExtensions, +} + +impl Default for VerifyLevel { + fn default() -> Self { + if cfg!(test) { + Self::WithoutExtensions + } else { + Self::None + } + } +} diff --git a/hugr/src/algorithm/const_fold.rs b/hugr/src/algorithm/const_fold.rs index f2b0dab24..cf4f61749 100644 --- a/hugr/src/algorithm/const_fold.rs +++ b/hugr/src/algorithm/const_fold.rs @@ -22,6 +22,8 @@ use crate::{ Hugr, HugrView, IncomingPort, Node, SimpleReplacement, }; +use super::VerifyLevel; + #[derive(Error, Debug)] #[allow(missing_docs)] pub enum ConstFoldError { @@ -35,6 +37,79 @@ pub enum ConstFoldError { SimpleReplaceError(#[from] SimpleReplacementError), } +impl ConstFoldError { + fn verify_err(label: impl Into, err: ValidationError) -> Self { + Self::VerifyError { + label: label.into(), + err, + } + } +} + +#[derive(Debug, Clone, Copy, Default)] +/// A configuration for the Constant Folding pass. +pub struct ConstFoldConfig { + verify: VerifyLevel, +} + +impl ConstFoldConfig { + /// Create a new `ConstFoldConfig` with default configuration. + pub fn new() -> Self { + Self::default() + } + + /// Build a `ConstFoldConfig` with the given [VerifyLevel]. + pub fn with_verify(mut self, verify: VerifyLevel) -> Self { + self.verify = verify; + self + } + + fn verify_impl( + &self, + label: &str, + h: &impl HugrView, + reg: &ExtensionRegistry, + ) -> Result<(), ConstFoldError> { + match self.verify { + VerifyLevel::None => Ok(()), + VerifyLevel::WithoutExtensions => h.validate_no_extensions(reg), + VerifyLevel::WithExtensions => h.validate(reg), + } + .map_err(|err| ConstFoldError::verify_err(label, err)) + } + + /// Run the Constant Folding pass. + pub fn run(&self, h: &mut impl HugrMut, reg: &ExtensionRegistry) -> Result<(), ConstFoldError> { + self.verify_impl("input", h, reg)?; + loop { + // We can only safely apply a single replacement. Applying a + // replacement removes nodes and edges which may be referenced by + // further replacements returned by find_consts. Even worse, if we + // attempted to apply those replacements, expecting them to fail if + // the nodes and edges they reference had been deleted, they may + // succeed because new nodes and edges reused the ids. + // + // We could be a lot smarter here, keeping track of `LoadConstant` + // nodes and only looking at their out neighbours. + let Some((replace, removes)) = find_consts(h, h.nodes(), reg).next() else { + break; + }; + h.apply_rewrite(replace)?; + for rem in removes { + // We are optimistically applying these [RemoveLoadConstant] and + // [RemoveConst] rewrites without checking whether the nodes + // they attempt to remove have remaining uses. If they do, then + // the rewrite fails and we move on. + if let Ok(const_node) = h.apply_rewrite(rem) { + // if the LoadConst was removed, try removing the Const too. + let _ = h.apply_rewrite(RemoveConst(const_node)); + } + } + } + self.verify_impl("output", h, reg) + } +} + /// Tag some output constants with [`OutgoingPort`] inferred from the ordering. fn out_row(consts: impl IntoIterator) -> ConstFoldResult { let vec = consts @@ -200,44 +275,7 @@ fn get_const(hugr: &impl HugrView, op_node: Node, in_p: IncomingPort) -> Option< /// Exhaustively apply constant folding to a HUGR. pub fn constant_fold_pass(h: &mut H, reg: &ExtensionRegistry) { - #[cfg(test)] - let verify = |label, h: &H| { - h.validate_no_extensions(reg).unwrap_or_else(|err| { - panic!( - "constant_fold_pass: failed to verify {label} HUGR: {err}\n{}", - h.mermaid_string() - ) - }) - }; - #[cfg(test)] - verify("input", h); - loop { - // We can only safely apply a single replacement. Applying a - // replacement removes nodes and edges which may be referenced by - // further replacements returned by find_consts. Even worse, if we - // attempted to apply those replacements, expecting them to fail if - // the nodes and edges they reference had been deleted, they may - // succeed because new nodes and edges reused the ids. - // - // We could be a lot smarter here, keeping track of `LoadConstant` - // nodes and only looking at their out neighbours. - let Some((replace, removes)) = find_consts(h, h.nodes(), reg).next() else { - break; - }; - h.apply_rewrite(replace).unwrap(); - for rem in removes { - // We are optimistically applying these [RemoveLoadConstant] and - // [RemoveConst] rewrites without checking whether the nodes - // they attempt to remove have remaining uses. If they do, then - // the rewrite fails and we move on. - if let Ok(const_node) = h.apply_rewrite(rem) { - // if the LoadConst was removed, try removing the Const too. - let _ = h.apply_rewrite(RemoveConst(const_node)); - } - } - } - #[cfg(test)] - verify("output", h); + ConstFoldConfig::default().run(h, reg).unwrap() } #[cfg(test)] From 62472a76c733100eff370c42cfa452d0add48080 Mon Sep 17 00:00:00 2001 From: Douglas Wilson Date: Tue, 14 May 2024 10:54:36 +0100 Subject: [PATCH 2/4] wip --- hugr/src/algorithm.rs | 32 +--------- hugr/src/algorithm/const_fold.rs | 98 +++++++++++------------------ hugr/src/algorithm/verify.rs | 102 +++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 92 deletions(-) create mode 100644 hugr/src/algorithm/verify.rs diff --git a/hugr/src/algorithm.rs b/hugr/src/algorithm.rs index 403632ecd..7010c395e 100644 --- a/hugr/src/algorithm.rs +++ b/hugr/src/algorithm.rs @@ -4,34 +4,4 @@ pub mod const_fold; mod half_node; pub mod merge_bbs; pub mod nest_cfgs; - -#[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq)] -/// A type for algorithms to take as configuration, specifying how much -/// verification they should do. Algorithms that accept this configuration -/// should at least verify that input HUGRs are valid, and that output HUGRs are -/// valid. -/// -/// The default level is `None` because verification can be expensive. -pub enum VerifyLevel { - /// Do no verification. - None, - /// Verify using [HugrView::validate_no_extensions]. This is useful when you - /// do not expect valid Extension annotations on Nodes. - /// - /// [HugrView::validate_no_extensions]: crate::HugrView::validate_no_extensions - WithoutExtensions, - /// Verify using [HugrView::validate]. - /// - /// [HugrView::validate]: crate::HugrView::validate - WithExtensions, -} - -impl Default for VerifyLevel { - fn default() -> Self { - if cfg!(test) { - Self::WithoutExtensions - } else { - Self::None - } - } -} +pub mod verify; diff --git a/hugr/src/algorithm/const_fold.rs b/hugr/src/algorithm/const_fold.rs index cf4f61749..7cff27b46 100644 --- a/hugr/src/algorithm/const_fold.rs +++ b/hugr/src/algorithm/const_fold.rs @@ -5,7 +5,8 @@ use std::collections::{BTreeSet, HashMap}; use itertools::Itertools; use thiserror::Error; -use crate::hugr::{SimpleReplacementError, ValidationError}; +use crate::algorithm::verify::{VerifyError, VerifyLevel}; +use crate::hugr::SimpleReplacementError; use crate::types::SumType; use crate::Direction; use crate::{ @@ -22,91 +23,66 @@ use crate::{ Hugr, HugrView, IncomingPort, Node, SimpleReplacement, }; -use super::VerifyLevel; - #[derive(Error, Debug)] #[allow(missing_docs)] pub enum ConstFoldError { - #[error("Failed to verify {label} HUGR: {err}")] - VerifyError { - label: String, - #[source] - err: ValidationError, - }, #[error(transparent)] - SimpleReplaceError(#[from] SimpleReplacementError), -} - -impl ConstFoldError { - fn verify_err(label: impl Into, err: ValidationError) -> Self { - Self::VerifyError { - label: label.into(), - err, - } - } + SimpleReplacementError(#[from] SimpleReplacementError), + #[error(transparent)] + VerifyError(#[from] VerifyError), } #[derive(Debug, Clone, Copy, Default)] /// A configuration for the Constant Folding pass. -pub struct ConstFoldConfig { +pub struct ConstantFoldPass { verify: VerifyLevel, } -impl ConstFoldConfig { +impl ConstantFoldPass { /// Create a new `ConstFoldConfig` with default configuration. pub fn new() -> Self { Self::default() } /// Build a `ConstFoldConfig` with the given [VerifyLevel]. - pub fn with_verify(mut self, verify: VerifyLevel) -> Self { + pub fn verify_level(mut self, verify: VerifyLevel) -> Self { self.verify = verify; self } - fn verify_impl( + /// Run the Constant Folding pass. + pub fn run( &self, - label: &str, - h: &impl HugrView, + hugr: &mut H, reg: &ExtensionRegistry, ) -> Result<(), ConstFoldError> { - match self.verify { - VerifyLevel::None => Ok(()), - VerifyLevel::WithoutExtensions => h.validate_no_extensions(reg), - VerifyLevel::WithExtensions => h.validate(reg), - } - .map_err(|err| ConstFoldError::verify_err(label, err)) - } - - /// Run the Constant Folding pass. - pub fn run(&self, h: &mut impl HugrMut, reg: &ExtensionRegistry) -> Result<(), ConstFoldError> { - self.verify_impl("input", h, reg)?; - loop { - // We can only safely apply a single replacement. Applying a - // replacement removes nodes and edges which may be referenced by - // further replacements returned by find_consts. Even worse, if we - // attempted to apply those replacements, expecting them to fail if - // the nodes and edges they reference had been deleted, they may - // succeed because new nodes and edges reused the ids. - // - // We could be a lot smarter here, keeping track of `LoadConstant` - // nodes and only looking at their out neighbours. - let Some((replace, removes)) = find_consts(h, h.nodes(), reg).next() else { - break; - }; - h.apply_rewrite(replace)?; - for rem in removes { - // We are optimistically applying these [RemoveLoadConstant] and - // [RemoveConst] rewrites without checking whether the nodes - // they attempt to remove have remaining uses. If they do, then - // the rewrite fails and we move on. - if let Ok(const_node) = h.apply_rewrite(rem) { - // if the LoadConst was removed, try removing the Const too. - let _ = h.apply_rewrite(RemoveConst(const_node)); + self.verify.run_verified_pass(hugr, reg, |hugr: &mut H| { + loop { + // We can only safely apply a single replacement. Applying a + // replacement removes nodes and edges which may be referenced by + // further replacements returned by find_consts. Even worse, if we + // attempted to apply those replacements, expecting them to fail if + // the nodes and edges they reference had been deleted, they may + // succeed because new nodes and edges reused the ids. + // + // We could be a lot smarter here, keeping track of `LoadConstant` + // nodes and only looking at their out neighbours. + let Some((replace, removes)) = find_consts(hugr, hugr.nodes(), reg).next() else { + break Ok(()); + }; + hugr.apply_rewrite(replace)?; + for rem in removes { + // We are optimistically applying these [RemoveLoadConstant] and + // [RemoveConst] rewrites without checking whether the nodes + // they attempt to remove have remaining uses. If they do, then + // the rewrite fails and we move on. + if let Ok(const_node) = hugr.apply_rewrite(rem) { + // if the LoadConst was removed, try removing the Const too. + let _ = hugr.apply_rewrite(RemoveConst(const_node)); + } } } - } - self.verify_impl("output", h, reg) + }) } } @@ -275,7 +251,7 @@ fn get_const(hugr: &impl HugrView, op_node: Node, in_p: IncomingPort) -> Option< /// Exhaustively apply constant folding to a HUGR. pub fn constant_fold_pass(h: &mut H, reg: &ExtensionRegistry) { - ConstFoldConfig::default().run(h, reg).unwrap() + ConstantFoldPass::default().run(h, reg).unwrap() } #[cfg(test)] diff --git a/hugr/src/algorithm/verify.rs b/hugr/src/algorithm/verify.rs new file mode 100644 index 000000000..475636734 --- /dev/null +++ b/hugr/src/algorithm/verify.rs @@ -0,0 +1,102 @@ +//! Provides [VerifyLevel] with tools to run passes with configurable +//! verification. + +use thiserror::Error; + +use crate::{ + extension::ExtensionRegistry, + hugr::{HugrMut, ValidationError}, + HugrView, +}; + +#[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq)] +/// A type for running [HugrMut] algorithms with verification. +/// +/// Provides [VerifyLevel::run_verified_pass] to invoke a closure with pre and +/// post verification. +/// +/// The default level is `None` because verification can be expensive. +pub enum VerifyLevel { + /// Do no verification. + None, + /// Verify using [HugrView::validate_no_extensions]. This is useful when you + /// do not expect valid Extension annotations on Nodes. + /// + /// [HugrView::validate_no_extensions]: crate::HugrView::validate_no_extensions + WithoutExtensions, + /// Verify using [HugrView::validate]. + /// + /// [HugrView::validate]: crate::HugrView::validate + WithExtensions, +} + +#[derive(Error, Debug)] +#[allow(missing_docs)] +pub enum VerifyError { + #[error("Failed to verify input HUGR: {err}\n{pretty_hugr}")] + InputError { + #[source] + err: ValidationError, + pretty_hugr: String, + }, + #[error("Failed to verify output HUGR: {err}\n{pretty_hugr}")] + OutputError { + #[source] + err: ValidationError, + pretty_hugr: String, + }, +} + +impl Default for VerifyLevel { + fn default() -> Self { + if cfg!(test) { + // Many tests fail when run with Self::WithExtensions + Self::WithoutExtensions + } else { + Self::None + } + } +} + +impl VerifyLevel { + /// Run an operation on a [HugrMut]. `hugr` will be verified according to + /// [self](VerifyLevel), then `pass` will be invoked. If `pass` succeeds + /// then `hugr` will be verified again. + pub fn run_verified_pass( + &self, + hugr: &mut H, + reg: &ExtensionRegistry, + pass: impl FnOnce(&mut H) -> Result, + ) -> Result + where + VerifyError: Into, + { + self.verify_impl(hugr, reg, |err, pretty_hugr| VerifyError::InputError { + err, + pretty_hugr, + })?; + let result = pass(hugr)?; + self.verify_impl(hugr, reg, |err, pretty_hugr| VerifyError::OutputError { + err, + pretty_hugr, + })?; + Ok(result) + } + + fn verify_impl( + &self, + hugr: &impl HugrView, + reg: &ExtensionRegistry, + mk_err: impl FnOnce(ValidationError, String) -> VerifyError, + ) -> Result<(), E> + where + VerifyError: Into, + { + match self { + VerifyLevel::None => Ok(()), + VerifyLevel::WithoutExtensions => hugr.validate_no_extensions(reg), + VerifyLevel::WithExtensions => hugr.validate(reg), + } + .map_err(|err| mk_err(err, hugr.mermaid_string()).into()) + } +} From 9353e62cd80aade2c675595b319790278511d5f8 Mon Sep 17 00:00:00 2001 From: Douglas Wilson Date: Tue, 14 May 2024 11:59:33 +0100 Subject: [PATCH 3/4] Pass &self to pass --- hugr/src/algorithm/const_fold.rs | 2 +- hugr/src/algorithm/verify.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hugr/src/algorithm/const_fold.rs b/hugr/src/algorithm/const_fold.rs index 7cff27b46..6d81c3768 100644 --- a/hugr/src/algorithm/const_fold.rs +++ b/hugr/src/algorithm/const_fold.rs @@ -56,7 +56,7 @@ impl ConstantFoldPass { hugr: &mut H, reg: &ExtensionRegistry, ) -> Result<(), ConstFoldError> { - self.verify.run_verified_pass(hugr, reg, |hugr: &mut H| { + self.verify.run_verified_pass(hugr, reg, |hugr: &mut H, _| { loop { // We can only safely apply a single replacement. Applying a // replacement removes nodes and edges which may be referenced by diff --git a/hugr/src/algorithm/verify.rs b/hugr/src/algorithm/verify.rs index 475636734..11df86532 100644 --- a/hugr/src/algorithm/verify.rs +++ b/hugr/src/algorithm/verify.rs @@ -12,8 +12,8 @@ use crate::{ #[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq)] /// A type for running [HugrMut] algorithms with verification. /// -/// Provides [VerifyLevel::run_verified_pass] to invoke a closure with pre and -/// post verification. +/// Provides [VerifyLevel::run_verified_pass] to invoke a closure with pre and post +/// verification. /// /// The default level is `None` because verification can be expensive. pub enum VerifyLevel { @@ -66,7 +66,7 @@ impl VerifyLevel { &self, hugr: &mut H, reg: &ExtensionRegistry, - pass: impl FnOnce(&mut H) -> Result, + pass: impl FnOnce(&mut H, &Self) -> Result, ) -> Result where VerifyError: Into, @@ -75,7 +75,7 @@ impl VerifyLevel { err, pretty_hugr, })?; - let result = pass(hugr)?; + let result = pass(hugr, self)?; self.verify_impl(hugr, reg, |err, pretty_hugr| VerifyError::OutputError { err, pretty_hugr, From 3993a2d84ce6c20246805eff6fbe161895b5abf8 Mon Sep 17 00:00:00 2001 From: Douglas Wilson Date: Thu, 6 Jun 2024 10:01:47 +0100 Subject: [PATCH 4/4] rename verify -> validation --- hugr-passes/src/const_fold.rs | 64 ++++++++++---------- hugr-passes/src/lib.rs | 2 +- hugr-passes/src/{verify.rs => validation.rs} | 54 ++++++++--------- 3 files changed, 60 insertions(+), 60 deletions(-) rename hugr-passes/src/{verify.rs => validation.rs} (51%) diff --git a/hugr-passes/src/const_fold.rs b/hugr-passes/src/const_fold.rs index 8ec21a222..b882699d5 100644 --- a/hugr-passes/src/const_fold.rs +++ b/hugr-passes/src/const_fold.rs @@ -23,7 +23,7 @@ use hugr_core::{ Hugr, HugrView, IncomingPort, Node, SimpleReplacement, }; -use crate::verify::{VerifyError, VerifyLevel}; +use crate::validation::{ValidatePassError, ValidationLevel}; #[derive(Error, Debug)] #[allow(missing_docs)] @@ -31,13 +31,13 @@ pub enum ConstFoldError { #[error(transparent)] SimpleReplacementError(#[from] SimpleReplacementError), #[error(transparent)] - VerifyError(#[from] VerifyError), + ValidationError(#[from] ValidatePassError), } #[derive(Debug, Clone, Copy, Default)] /// A configuration for the Constant Folding pass. pub struct ConstantFoldPass { - verify: VerifyLevel, + validation: ValidationLevel, } impl ConstantFoldPass { @@ -46,9 +46,9 @@ impl ConstantFoldPass { Self::default() } - /// Build a `ConstFoldConfig` with the given [VerifyLevel]. - pub fn verify_level(mut self, verify: VerifyLevel) -> Self { - self.verify = verify; + /// Build a `ConstFoldConfig` with the given [ValidationLevel]. + pub fn validation_level(mut self, level: ValidationLevel) -> Self { + self.validation = level; self } @@ -58,33 +58,35 @@ impl ConstantFoldPass { hugr: &mut H, reg: &ExtensionRegistry, ) -> Result<(), ConstFoldError> { - self.verify.run_verified_pass(hugr, reg, |hugr: &mut H, _| { - loop { - // We can only safely apply a single replacement. Applying a - // replacement removes nodes and edges which may be referenced by - // further replacements returned by find_consts. Even worse, if we - // attempted to apply those replacements, expecting them to fail if - // the nodes and edges they reference had been deleted, they may - // succeed because new nodes and edges reused the ids. - // - // We could be a lot smarter here, keeping track of `LoadConstant` - // nodes and only looking at their out neighbours. - let Some((replace, removes)) = find_consts(hugr, hugr.nodes(), reg).next() else { - break Ok(()); - }; - hugr.apply_rewrite(replace)?; - for rem in removes { - // We are optimistically applying these [RemoveLoadConstant] and - // [RemoveConst] rewrites without checking whether the nodes - // they attempt to remove have remaining uses. If they do, then - // the rewrite fails and we move on. - if let Ok(const_node) = hugr.apply_rewrite(rem) { - // if the LoadConst was removed, try removing the Const too. - let _ = hugr.apply_rewrite(RemoveConst(const_node)); + self.validation + .run_validated_pass(hugr, reg, |hugr: &mut H, _| { + loop { + // We can only safely apply a single replacement. Applying a + // replacement removes nodes and edges which may be referenced by + // further replacements returned by find_consts. Even worse, if we + // attempted to apply those replacements, expecting them to fail if + // the nodes and edges they reference had been deleted, they may + // succeed because new nodes and edges reused the ids. + // + // We could be a lot smarter here, keeping track of `LoadConstant` + // nodes and only looking at their out neighbours. + let Some((replace, removes)) = find_consts(hugr, hugr.nodes(), reg).next() + else { + break Ok(()); + }; + hugr.apply_rewrite(replace)?; + for rem in removes { + // We are optimistically applying these [RemoveLoadConstant] and + // [RemoveConst] rewrites without checking whether the nodes + // they attempt to remove have remaining uses. If they do, then + // the rewrite fails and we move on. + if let Ok(const_node) = hugr.apply_rewrite(rem) { + // if the LoadConst was removed, try removing the Const too. + let _ = hugr.apply_rewrite(RemoveConst(const_node)); + } } } - } - }) + }) } } diff --git a/hugr-passes/src/lib.rs b/hugr-passes/src/lib.rs index ddaf5cad0..f6e09b71b 100644 --- a/hugr-passes/src/lib.rs +++ b/hugr-passes/src/lib.rs @@ -4,4 +4,4 @@ pub mod const_fold; mod half_node; pub mod merge_bbs; pub mod nest_cfgs; -pub mod verify; +pub mod validation; diff --git a/hugr-passes/src/verify.rs b/hugr-passes/src/validation.rs similarity index 51% rename from hugr-passes/src/verify.rs rename to hugr-passes/src/validation.rs index b0be5a01e..68fa43601 100644 --- a/hugr-passes/src/verify.rs +++ b/hugr-passes/src/validation.rs @@ -1,5 +1,5 @@ -//! Provides [VerifyLevel] with tools to run passes with configurable -//! verification. +//! Provides [ValidationLevel] with tools to run passes with configurable +//! validation. use thiserror::Error; @@ -12,30 +12,30 @@ use hugr_core::{ #[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq)] /// A type for running [HugrMut] algorithms with verification. /// -/// Provides [VerifyLevel::run_verified_pass] to invoke a closure with pre and post -/// verification. +/// Provides [ValidationLevel::run_validated_pass] to invoke a closure with pre and post +/// validation. /// -/// The default level is `None` because verification can be expensive. -pub enum VerifyLevel { +/// The default level is `None` because validation can be expensive. +pub enum ValidationLevel { /// Do no verification. None, - /// Verify using [HugrView::validate_no_extensions]. This is useful when you + /// Validate using [HugrView::validate_no_extensions]. This is useful when you /// do not expect valid Extension annotations on Nodes. WithoutExtensions, - /// Verify using [HugrView::validate]. + /// Validate using [HugrView::validate]. WithExtensions, } #[derive(Error, Debug)] #[allow(missing_docs)] -pub enum VerifyError { - #[error("Failed to verify input HUGR: {err}\n{pretty_hugr}")] +pub enum ValidatePassError { + #[error("Failed to validate input HUGR: {err}\n{pretty_hugr}")] InputError { #[source] err: ValidationError, pretty_hugr: String, }, - #[error("Failed to verify output HUGR: {err}\n{pretty_hugr}")] + #[error("Failed to validate output HUGR: {err}\n{pretty_hugr}")] OutputError { #[source] err: ValidationError, @@ -43,7 +43,7 @@ pub enum VerifyError { }, } -impl Default for VerifyLevel { +impl Default for ValidationLevel { fn default() -> Self { if cfg!(test) { // Many tests fail when run with Self::WithExtensions @@ -54,44 +54,42 @@ impl Default for VerifyLevel { } } -impl VerifyLevel { +impl ValidationLevel { /// Run an operation on a [HugrMut]. `hugr` will be verified according to - /// [self](VerifyLevel), then `pass` will be invoked. If `pass` succeeds + /// [self](ValidationLevel), then `pass` will be invoked. If `pass` succeeds /// then `hugr` will be verified again. - pub fn run_verified_pass( + pub fn run_validated_pass( &self, hugr: &mut H, reg: &ExtensionRegistry, pass: impl FnOnce(&mut H, &Self) -> Result, ) -> Result where - VerifyError: Into, + ValidatePassError: Into, { - self.verify_impl(hugr, reg, |err, pretty_hugr| VerifyError::InputError { - err, - pretty_hugr, + self.validation_impl(hugr, reg, |err, pretty_hugr| { + ValidatePassError::InputError { err, pretty_hugr } })?; let result = pass(hugr, self)?; - self.verify_impl(hugr, reg, |err, pretty_hugr| VerifyError::OutputError { - err, - pretty_hugr, + self.validation_impl(hugr, reg, |err, pretty_hugr| { + ValidatePassError::OutputError { err, pretty_hugr } })?; Ok(result) } - fn verify_impl( + fn validation_impl( &self, hugr: &impl HugrView, reg: &ExtensionRegistry, - mk_err: impl FnOnce(ValidationError, String) -> VerifyError, + mk_err: impl FnOnce(ValidationError, String) -> ValidatePassError, ) -> Result<(), E> where - VerifyError: Into, + ValidatePassError: Into, { match self { - VerifyLevel::None => Ok(()), - VerifyLevel::WithoutExtensions => hugr.validate_no_extensions(reg), - VerifyLevel::WithExtensions => hugr.validate(reg), + ValidationLevel::None => Ok(()), + ValidationLevel::WithoutExtensions => hugr.validate_no_extensions(reg), + ValidationLevel::WithExtensions => hugr.validate(reg), } .map_err(|err| mk_err(err, hugr.mermaid_string()).into()) }