Skip to content

Commit

Permalink
feat: Improve error message on failed custom op validation (#1416)
Browse files Browse the repository at this point in the history
Prints the node and operation in the error message.

Before:
```console
$ hugr validate test.hugr
Error validating HUGR: Type arguments of node did not match params declared by definition: Wrong number of type arguments: 1 vs expected 0 declared type parameters
```

After:
```console
$ hugr validate test.hugr
Error validating HUGR: Error in signature of operation 'Not' in Node(27): Type arguments of node did not match params declared by definition: Wrong number of type arguments: 1 vs expected 0 declared type parameters
```
  • Loading branch information
aborgna-q authored Aug 12, 2024
1 parent 67bb8a0 commit 6639c52
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 8 deletions.
8 changes: 6 additions & 2 deletions hugr-core/src/hugr/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,12 @@ pub enum ValidationError {
#[error("Node {node:?} needs a concrete ExtensionSet - inference will provide this for Case/CFG/Conditional/DataflowBlock/DFG/TailLoop only")]
ExtensionsNotInferred { node: Node },
/// Error in a node signature
#[error("Error in signature of node {node:?}: {cause}")]
SignatureError { node: Node, cause: SignatureError },
#[error("Error in signature of node {node}: {cause}")]
SignatureError {
node: Node,
#[source]
cause: SignatureError,
},
/// Error in a [CustomOp] serialized as an [Opaque].
///
/// [CustomOp]: crate::ops::CustomOp
Expand Down
26 changes: 20 additions & 6 deletions hugr-core/src/ops/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,21 +393,28 @@ pub fn resolve_extension_ops(
/// If the serialized opaque resolves to a definition that conflicts with what
/// was serialized
pub fn resolve_opaque_op(
_n: Node,
node: Node,
opaque: &OpaqueOp,
extension_registry: &ExtensionRegistry,
) -> Result<Option<ExtensionOp>, CustomOpError> {
if let Some(r) = extension_registry.get(&opaque.extension) {
// Fail if the Extension was found but did not have the expected operation
let Some(def) = r.get_op(&opaque.name) else {
return Err(CustomOpError::OpNotFoundInExtension(
node,
opaque.name.clone(),
r.name().clone(),
));
};
let ext_op = ExtensionOp::new(def.clone(), opaque.args.clone(), extension_registry)?;
let ext_op = ExtensionOp::new(def.clone(), opaque.args.clone(), extension_registry)
.map_err(|e| CustomOpError::SignatureError {
node,
name: opaque.name.clone(),
cause: e,
})?;
if opaque.signature() != ext_op.signature() {
return Err(CustomOpError::SignatureMismatch {
node,
extension: opaque.extension.clone(),
op: def.name().clone(),
computed: ext_op.signature.clone(),
Expand All @@ -426,20 +433,27 @@ pub fn resolve_opaque_op(
#[non_exhaustive]
pub enum CustomOpError {
/// The Extension was found but did not contain the expected OpDef
#[error("Operation {0} not found in Extension {1}")]
OpNotFoundInExtension(OpName, ExtensionId),
#[error("Operation '{1}' in {0} not found in Extension {2}")]
OpNotFoundInExtension(Node, OpName, ExtensionId),
/// Extension and OpDef found, but computed signature did not match stored
#[error("Conflicting signature: resolved {op} in extension {extension} to a concrete implementation which computed {computed} but stored signature was {stored}")]
#[allow(missing_docs)]
SignatureMismatch {
node: Node,
extension: ExtensionId,
op: OpName,
stored: Signature,
computed: Signature,
},
/// An error in computing the signature of the ExtensionOp
#[error(transparent)]
SignatureError(#[from] SignatureError),
#[error("Error in signature of operation '{name}' in {node}: {cause}")]
#[allow(missing_docs)]
SignatureError {
node: Node,
name: OpName,
#[source]
cause: SignatureError,
},
}

#[cfg(test)]
Expand Down

0 comments on commit 6639c52

Please sign in to comment.