-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: add op's extension to signature check in resolve_opaque_op
#1317
Changes from 13 commits
4f3cda8
7948129
c520ece
d03d990
143e507
dd3bc4b
865ecfb
118152d
3742ddd
db6534b
e119e26
b5008f0
f319896
0aa0a30
1a5f330
a0a0cab
13d898c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -134,7 +134,7 @@ impl DataflowOpTrait for CustomOp { | |
/// The signature of the operation. | ||
fn signature(&self) -> FunctionType { | ||
match self { | ||
Self::Opaque(op) => op.signature.clone(), | ||
Self::Opaque(op) => op.signature(), | ||
Self::Extension(ext_op) => ext_op.signature(), | ||
} | ||
} | ||
|
@@ -276,7 +276,15 @@ impl DataflowOpTrait for ExtensionOp { | |
} | ||
} | ||
|
||
/// An opaquely-serialized op that refers to an as-yet-unresolved [`OpDef`] | ||
/// An opaquely-serialized op that refers to an as-yet-unresolved [`OpDef`]. | ||
/// | ||
/// All [CustomOp]s are serialised as `OpaqueOp`s. | ||
/// | ||
/// The signature of a [CustomOp] always includes that op's extension. We do not | ||
/// require that the `signature` field of [OpaqueOp] contains `extension`, | ||
/// instead we are careful to add it whenever we look at the `signature` of an | ||
/// `OpaqueOp`. This is a small efficiency in serialisation and allows us to | ||
/// be more liberal in deserialisation. | ||
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] | ||
#[cfg_attr(test, derive(Arbitrary))] | ||
pub struct OpaqueOp { | ||
|
@@ -286,6 +294,9 @@ pub struct OpaqueOp { | |
#[cfg_attr(test, proptest(strategy = "any_nonempty_string()"))] | ||
description: String, // cache in advance so description() can return &str | ||
args: Vec<TypeArg>, | ||
// note that `signature` may not include `extension`. Thus this field must | ||
doug-q marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// remain private, and should be accessed through | ||
// `DataflowOpTrait::signature`. | ||
signature: FunctionType, | ||
} | ||
|
||
|
@@ -343,7 +354,9 @@ impl DataflowOpTrait for OpaqueOp { | |
} | ||
|
||
fn signature(&self) -> FunctionType { | ||
self.signature.clone() | ||
self.signature | ||
.clone() | ||
.with_extension_delta(self.extension().clone()) | ||
} | ||
} | ||
|
||
|
@@ -392,9 +405,8 @@ pub fn resolve_opaque_op( | |
r.name().clone(), | ||
)); | ||
}; | ||
let ext_op = | ||
ExtensionOp::new(def.clone(), opaque.args.clone(), extension_registry).unwrap(); | ||
if opaque.signature != ext_op.signature { | ||
let ext_op = ExtensionOp::new(def.clone(), opaque.args.clone(), extension_registry)?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The change from |
||
if opaque.signature() != ext_op.signature() { | ||
return Err(CustomOpError::SignatureMismatch { | ||
extension: opaque.extension.clone(), | ||
op: def.name().clone(), | ||
|
@@ -425,10 +437,14 @@ pub enum CustomOpError { | |
stored: FunctionType, | ||
computed: FunctionType, | ||
}, | ||
/// An error in computing the signature of the ExtensionOp | ||
#[error(transparent)] | ||
SignatureError(#[from] SignatureError), | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
|
||
use crate::{ | ||
extension::prelude::{BOOL_T, QB_T, USIZE_T}, | ||
std_extensions::arithmetic::{ | ||
|
@@ -453,13 +469,15 @@ mod test { | |
assert_eq!(op.name(), "res.op"); | ||
assert_eq!(DataflowOpTrait::description(&op), "desc"); | ||
assert_eq!(op.args(), &[TypeArg::Type { ty: USIZE_T }]); | ||
assert_eq!(op.signature(), sig); | ||
assert_eq!( | ||
op.signature(), | ||
sig.with_extension_delta(op.extension().clone()) | ||
); | ||
assert!(op.is_opaque()); | ||
assert!(!op.is_extension_op()); | ||
} | ||
|
||
#[test] | ||
#[should_panic] // https://github.com/CQCL/hugr/issues/1315 | ||
fn resolve_opaque_op() { | ||
let registry = &INT_OPS_REGISTRY; | ||
let i0 = &INT_TYPES[0]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,8 @@ | |
from hugr import tys, val | ||
|
||
#: HUGR 64-bit IEEE 754-2019 floating point type. | ||
FLOAT_EXT_ID = "arithmetic.float.types" | ||
FLOAT_T = tys.Opaque( | ||
extension=FLOAT_EXT_ID, | ||
extension="arithmetic.float.types", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: don't really see any need to revert here |
||
id="float64", | ||
args=[], | ||
bound=tys.TypeBound.Copyable, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why
?
->unwrap
everywhere? It does make things a lot longer and look like you are changing more than you are.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unwrap is much better than ? in tests because you get a src location on failure. I changed them all to be able to fix the test and thought I might as well leave it in a debuggable state.