From bbff0c94413f0626be44d61d52858027ac452702 Mon Sep 17 00:00:00 2001 From: Seyon Sivarajah Date: Mon, 8 Jul 2024 13:53:51 +0100 Subject: [PATCH] fix: bring back input_extensions serialized field in rust NodeSer (#1275) (skip serializing, deserialize to None) Closes #1270 --- hugr-core/src/hugr.rs | 2 +- hugr-core/src/hugr/serialize.rs | 5 + hugr-core/src/hugr/serialize/test.rs | 21 +- hugr-core/src/hugr/validate/test.rs | 2 +- hugr-core/src/ops.rs | 2 +- hugr-core/src/ops/module.rs | 8 +- resources/test/issue-1270.json | 1147 ++++++++++++++++++++++++++ 7 files changed, 1180 insertions(+), 7 deletions(-) create mode 100644 resources/test/issue-1270.json diff --git a/hugr-core/src/hugr.rs b/hugr-core/src/hugr.rs index fc07e936a..7b16c6ff3 100644 --- a/hugr-core/src/hugr.rs +++ b/hugr-core/src/hugr.rs @@ -51,7 +51,7 @@ pub struct Hugr { impl Default for Hugr { fn default() -> Self { - Self::new(crate::ops::Module) + Self::new(crate::ops::Module::new()) } } diff --git a/hugr-core/src/hugr/serialize.rs b/hugr-core/src/hugr/serialize.rs index f5554094b..779d58cd7 100644 --- a/hugr-core/src/hugr/serialize.rs +++ b/hugr-core/src/hugr/serialize.rs @@ -49,6 +49,9 @@ struct NodeSer { parent: Node, #[serde(flatten)] op: OpType, + + #[serde(skip_serializing, default)] + input_extensions: Option, } /// Version 1 of the HUGR serialization format. @@ -146,6 +149,7 @@ impl TryFrom<&Hugr> for SerHugrV1 { nodes[new_node] = Some(NodeSer { parent, op: opt.clone(), + input_extensions: None, }); metadata[new_node].clone_from(hugr.metadata.get(n.pg_index())); } @@ -203,6 +207,7 @@ impl TryFrom for Hugr { let NodeSer { parent: root_parent, op: root_type, + .. } = nodes.next().unwrap(); if root_parent.index() != 0 { return Err(HUGRSerializationError::FirstNodeNotRoot(root_parent)); diff --git a/hugr-core/src/hugr/serialize/test.rs b/hugr-core/src/hugr/serialize/test.rs index 441581630..275dbb845 100644 --- a/hugr-core/src/hugr/serialize/test.rs +++ b/hugr-core/src/hugr/serialize/test.rs @@ -203,7 +203,7 @@ fn gen_optype(g: &MultiPortGraph, node: portgraph::NodeIndex) -> OpType { .into(), (true, false) => Input::new(vec![NAT; outputs - 1]).into(), (false, true) => Output::new(vec![NAT; inputs - 1]).into(), - (true, true) => Module.into(), + (true, true) => Module::new().into(), } } @@ -451,7 +451,7 @@ fn roundtrip_polyfunctype(#[case] poly_func_type: PolyFuncType) { } #[rstest] -#[case(ops::Module)] +#[case(ops::Module::new())] #[case(ops::FuncDefn { name: "polyfunc1".into(), signature: polyfunctype1()})] #[case(ops::FuncDecl { name: "polyfunc2".into(), signature: polyfunctype1()})] #[case(ops::AliasDefn { name: "aliasdefn".into(), definition: Type::new_unit_sum(4)})] @@ -466,9 +466,20 @@ fn roundtrip_optype(#[case] optype: impl Into + std::fmt::Debug) { check_testing_roundtrip(NodeSer { parent: portgraph::NodeIndex::new(0).into(), op: optype.into(), + input_extensions: None, }); } +#[test] +/// issue 1270 +fn input_extensions_deser() { + // load a file serialised with `input_extensions` fields on all ops + let _: Hugr = serde_json::from_reader(std::io::BufReader::new( + std::fs::File::open(crate::test_file!("issue-1270.json")).unwrap(), + )) + .unwrap(); +} + mod proptest { use super::check_testing_roundtrip; use super::{NodeSer, SimpleOpDef}; @@ -484,7 +495,11 @@ mod proptest { (0..i32::MAX as usize).prop_map(|x| portgraph::NodeIndex::new(x).into()), any::(), ) - .prop_map(|(parent, op)| NodeSer { parent, op }) + .prop_map(|(parent, op)| NodeSer { + parent, + op, + input_extensions: None, + }) .boxed() } } diff --git a/hugr-core/src/hugr/validate/test.rs b/hugr-core/src/hugr/validate/test.rs index 9e14ddbbe..832d441b9 100644 --- a/hugr-core/src/hugr/validate/test.rs +++ b/hugr-core/src/hugr/validate/test.rs @@ -74,7 +74,7 @@ fn invalid_root() { assert_eq!(b.validate(&EMPTY_REG), Ok(())); // Add another hierarchy root - let other = b.add_node(ops::Module.into()); + let other = b.add_node(ops::Module::new().into()); assert_matches!( b.validate(&EMPTY_REG), Err(ValidationError::NoParent { node }) => assert_eq!(node, other) diff --git a/hugr-core/src/ops.rs b/hugr-core/src/ops.rs index 76f3e54a4..480db67ad 100644 --- a/hugr-core/src/ops.rs +++ b/hugr-core/src/ops.rs @@ -125,7 +125,7 @@ impl_op_ref_try_into!(Conditional); impl_op_ref_try_into!(Case); /// The default OpType (as returned by [Default::default]) -pub const DEFAULT_OPTYPE: OpType = OpType::Module(Module); +pub const DEFAULT_OPTYPE: OpType = OpType::Module(Module::new()); impl Default for OpType { fn default() -> Self { diff --git a/hugr-core/src/ops/module.rs b/hugr-core/src/ops/module.rs index 40c189b68..8d81d24c0 100644 --- a/hugr-core/src/ops/module.rs +++ b/hugr-core/src/ops/module.rs @@ -15,9 +15,15 @@ use super::StaticTag; use super::{impl_op_name, OpTag, OpTrait}; /// The root of a module, parent of all other `OpType`s. -#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(test, derive(Arbitrary))] pub struct Module; +impl Module { + /// Construct a new Module. + pub const fn new() -> Self { + Self + } +} impl_op_name!(Module); diff --git a/resources/test/issue-1270.json b/resources/test/issue-1270.json new file mode 100644 index 000000000..40b4f46e1 --- /dev/null +++ b/resources/test/issue-1270.json @@ -0,0 +1,1147 @@ +{ + "version": "v1", + "nodes": [ + { + "parent": 0, + "input_extensions": null, + "op": "Module" + }, + { + "parent": 8, + "input_extensions": null, + "op": "DataflowBlock", + "inputs": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "other_outputs": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "sum_rows": [ + [] + ], + "extension_delta": [] + }, + { + "parent": 8, + "input_extensions": null, + "op": "ExitBlock", + "cfg_outputs": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ] + }, + { + "parent": 7, + "input_extensions": null, + "op": "Input", + "types": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ] + }, + { + "parent": 1, + "input_extensions": null, + "op": "Input", + "types": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ] + }, + { + "parent": 1, + "input_extensions": null, + "op": "Output", + "types": [ + { + "t": "Sum", + "s": "Unit", + "size": 1 + }, + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ] + }, + { + "parent": 7, + "input_extensions": null, + "op": "Output", + "types": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ] + }, + { + "parent": 0, + "input_extensions": null, + "op": "FuncDefn", + "name": "my_func", + "signature": { + "params": [], + "body": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "output": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "extension_reqs": [] + } + } + }, + { + "parent": 7, + "input_extensions": null, + "op": "CFG", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "output": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "extension_reqs": [] + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "Const", + "v": { + "v": "Extension", + "extensions": [ + "arithmetic.float.types" + ], + "typ": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + "value": { + "c": "ConstF64", + "v": { + "value": 1.5707963267948966 + } + } + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "LoadConstant", + "datatype": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "Const", + "v": { + "v": "Extension", + "extensions": [ + "arithmetic.float.types" + ], + "typ": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + "value": { + "c": "ConstF64", + "v": { + "value": -1.5707963267948966 + } + } + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "LoadConstant", + "datatype": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "PhasedX", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "Const", + "v": { + "v": "Extension", + "extensions": [ + "arithmetic.float.types" + ], + "typ": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + "value": { + "c": "ConstF64", + "v": { + "value": 3.141592653589793 + } + } + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "LoadConstant", + "datatype": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "RzF64", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "Const", + "v": { + "v": "Extension", + "extensions": [ + "arithmetic.float.types" + ], + "typ": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + "value": { + "c": "ConstF64", + "v": { + "value": 1.5707963267948966 + } + } + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "LoadConstant", + "datatype": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "Const", + "v": { + "v": "Extension", + "extensions": [ + "arithmetic.float.types" + ], + "typ": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + "value": { + "c": "ConstF64", + "v": { + "value": -1.5707963267948966 + } + } + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "LoadConstant", + "datatype": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "PhasedX", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "Const", + "v": { + "v": "Extension", + "extensions": [ + "arithmetic.float.types" + ], + "typ": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + }, + "value": { + "c": "ConstF64", + "v": { + "value": 3.141592653589793 + } + } + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "LoadConstant", + "datatype": { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "RzF64", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "arithmetic.float.types", + "id": "float64", + "args": [], + "bound": "C" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "ZZMax", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "MakeTuple", + "tys": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ] + }, + { + "parent": 1, + "input_extensions": null, + "op": "UnpackTuple", + "tys": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ] + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "Measure", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "QFree", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "output": [], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "Measure", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "output": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + }, + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "CustomOp", + "extension": "quantum.tket2", + "op_name": "QFree", + "signature": { + "t": "G", + "input": [ + { + "t": "Opaque", + "extension": "prelude", + "id": "qubit", + "args": [], + "bound": "A" + } + ], + "output": [], + "extension_reqs": [] + }, + "description": "", + "args": [] + }, + { + "parent": 1, + "input_extensions": null, + "op": "MakeTuple", + "tys": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ] + }, + { + "parent": 1, + "input_extensions": null, + "op": "UnpackTuple", + "tys": [ + { + "t": "Sum", + "s": "Unit", + "size": 2 + } + ] + }, + { + "parent": 1, + "input_extensions": null, + "op": "Tag", + "tag": 0, + "variants": [ + [] + ] + } + ], + "edges": [ + [ + [ + 3, + 0 + ], + [ + 8, + 0 + ] + ], + [ + [ + 3, + 1 + ], + [ + 8, + 1 + ] + ], + [ + [ + 8, + 0 + ], + [ + 6, + 0 + ] + ], + [ + [ + 1, + 0 + ], + [ + 2, + null + ] + ], + [ + [ + 4, + 0 + ], + [ + 13, + 0 + ] + ], + [ + [ + 4, + 1 + ], + [ + 21, + 0 + ] + ], + [ + [ + 9, + 0 + ], + [ + 10, + 0 + ] + ], + [ + [ + 10, + 0 + ], + [ + 13, + 1 + ] + ], + [ + [ + 11, + 0 + ], + [ + 12, + 0 + ] + ], + [ + [ + 12, + 0 + ], + [ + 13, + 2 + ] + ], + [ + [ + 13, + 0 + ], + [ + 16, + 0 + ] + ], + [ + [ + 14, + 0 + ], + [ + 15, + 0 + ] + ], + [ + [ + 15, + 0 + ], + [ + 16, + 1 + ] + ], + [ + [ + 16, + 0 + ], + [ + 25, + 0 + ] + ], + [ + [ + 17, + 0 + ], + [ + 18, + 0 + ] + ], + [ + [ + 18, + 0 + ], + [ + 21, + 1 + ] + ], + [ + [ + 19, + 0 + ], + [ + 20, + 0 + ] + ], + [ + [ + 20, + 0 + ], + [ + 21, + 2 + ] + ], + [ + [ + 21, + 0 + ], + [ + 24, + 0 + ] + ], + [ + [ + 22, + 0 + ], + [ + 23, + 0 + ] + ], + [ + [ + 23, + 0 + ], + [ + 24, + 1 + ] + ], + [ + [ + 24, + 0 + ], + [ + 25, + 1 + ] + ], + [ + [ + 25, + 0 + ], + [ + 26, + 0 + ] + ], + [ + [ + 25, + 1 + ], + [ + 26, + 1 + ] + ], + [ + [ + 26, + 0 + ], + [ + 27, + 0 + ] + ], + [ + [ + 27, + 0 + ], + [ + 28, + 0 + ] + ], + [ + [ + 27, + 1 + ], + [ + 30, + 0 + ] + ], + [ + [ + 28, + 0 + ], + [ + 29, + 0 + ] + ], + [ + [ + 30, + 0 + ], + [ + 31, + 0 + ] + ], + [ + [ + 30, + 1 + ], + [ + 32, + 0 + ] + ], + [ + [ + 32, + 0 + ], + [ + 33, + 0 + ] + ], + [ + [ + 33, + 0 + ], + [ + 5, + 1 + ] + ], + [ + [ + 34, + 0 + ], + [ + 5, + 0 + ] + ] + ], + "metadata": null, + "encoder": "hugr-py v0.2.0a1" +}