diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d9546eaf7..d00b538de 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,8 +11,19 @@ repos: - id: check-yaml - id: detect-private-key - id: end-of-file-fixer - exclude: ^specification/schema/ + exclude: | + (?x)^( + specification/schema/.*| + .*.snap| + .*.snap.new + )$ - id: trailing-whitespace + exclude: | + (?x)^( + specification/schema/.*| + .*.snap| + .*.snap.new + )$ - id: fix-byte-order-marker - id: mixed-line-ending # Python-specific diff --git a/quantinuum-hugr-py/src/quantinuum_hugr/serialization/ops.py b/quantinuum-hugr-py/src/quantinuum_hugr/serialization/ops.py index 2bc9824dd..9490a5c57 100644 --- a/quantinuum-hugr-py/src/quantinuum_hugr/serialization/ops.py +++ b/quantinuum-hugr-py/src/quantinuum_hugr/serialization/ops.py @@ -178,11 +178,9 @@ def insert_child_dfg_signature(self, inputs: TypeRow, outputs: TypeRow) -> None: if isinstance(pred, tys.UnitSum): self.sum_rows = [[] for _ in range(cast(tys.UnitSum, pred).size)] else: - assert isinstance(pred, tys.GeneralSum) self.sum_rows = [] for variant in pred.rows: - assert isinstance(variant, tys.TupleType) - self.sum_rows.append(variant.inner) + self.sum_rows.append(variant) self.other_outputs = outputs[1:] class Config: @@ -346,8 +344,7 @@ def insert_port_types(self, in_types: TypeRow, out_types: TypeRow) -> None: assert isinstance(pred, tys.GeneralSum) self.sum_rows = [] for ty in pred.rows: - assert isinstance(ty, tys.TupleType) - self.sum_rows.append(ty.inner) + self.sum_rows.append(ty) self.other_inputs = list(in_types[1:]) self.outputs = list(out_types) diff --git a/quantinuum-hugr-py/src/quantinuum_hugr/serialization/tys.py b/quantinuum-hugr-py/src/quantinuum_hugr/serialization/tys.py index effc53d18..cea1a40cc 100644 --- a/quantinuum-hugr-py/src/quantinuum_hugr/serialization/tys.py +++ b/quantinuum-hugr-py/src/quantinuum_hugr/serialization/tys.py @@ -144,13 +144,6 @@ class Array(MultiContainer): len: int -class TupleType(BaseModel): - """Product type, known-size tuple over elements of type row.""" - - t: Literal["Tuple"] = "Tuple" - inner: "TypeRow" - - class UnitSum(BaseModel): """Simple predicate where all variants are empty tuples.""" @@ -286,7 +279,7 @@ class Type(RootModel): """A HUGR type.""" root: Annotated[ - Qubit | Variable | USize | PolyFuncType | Array | TupleType | SumType | Opaque, + Qubit | Variable | USize | PolyFuncType | Array | SumType | Opaque, WrapValidator(_json_custom_error_validator), ] = Field(discriminator="t") diff --git a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_cfg.snap b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_cfg.snap index fa89312ff..397c1d92f 100644 --- a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_cfg.snap +++ b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_cfg.snap @@ -1,5 +1,46 @@ --- -source: src/hugr/views/tests.rs +source: quantinuum-hugr/src/hugr/views/tests.rs expression: h.dot_string() --- -"digraph {\n0 [shape=plain label=<
(0) CFG
>]\n1 [shape=plain label=<
0
(1) ExitBlock
>]\n2 [shape=plain label=<
0
(2) DataflowBlock
01
>]\n2:out0 -> 6:in0 [style=\"dashed\"]\n2:out1 -> 1:in0 [style=\"dashed\"]\n3 [shape=plain label=<
(3) Input
0: usize
>]\n3:out0 -> 5:in0 [style=\"\"]\n4 [shape=plain label=<
0: Sum(General([TypeRow { types: [Type(Extension(CustomType { extension: IdentList(\"prelude\"), id: \"usize\", args: [], bound: Eq }), Eq)] }, TypeRow { types: [Type(Extension(CustomType { extension: IdentList(\"prelude\"), id: \"usize\", args: [], bound: Eq }), Eq)] }]))
(4) Output
>]\n5 [shape=plain label=<
0: usize
(5) Tag
0: Sum(General([TypeRow { types: [Type(Extension(CustomType { extension: IdentList(\"prelude\"), id: \"usize\", args: [], bound: Eq }), Eq)] }, TypeRow { types: [Type(Extension(CustomType { extension: IdentList(\"prelude\"), id: \"usize\", args: [], bound: Eq }), Eq)] }]))
>]\n5:out0 -> 4:in0 [style=\"\"]\n6 [shape=plain label=<
0
(6) DataflowBlock
0
>]\n6:out0 -> 1:in0 [style=\"dashed\"]\n7 [shape=plain label=<
(7) Input
0: usize
>]\n7:out0 -> 8:in1 [style=\"\"]\n8 [shape=plain label=<
0: Sum(UnitSum(1))1: usize
(8) Output
>]\n9 [shape=plain label=<
(9) const:sum:{tag:0, vals:[]}
0: Sum(UnitSum(1))
>]\n9:out0 -> 10:in0 [style=\"\"]\n10 [shape=plain label=<
0: Sum(UnitSum(1))
(10) LoadConstant
0: Sum(UnitSum(1))
>]\n10:out0 -> 8:in0 [style=\"\"]\nhier0 [shape=plain label=\"0\"]\nhier0 -> hier2 [style = \"dashed\"] \nhier0 -> hier1 [style = \"dashed\"] \nhier0 -> hier6 [style = \"dashed\"] \nhier1 [shape=plain label=\"1\"]\nhier2 [shape=plain label=\"2\"]\nhier2 -> hier3 [style = \"dashed\"] \nhier2 -> hier4 [style = \"dashed\"] \nhier2 -> hier5 [style = \"dashed\"] \nhier3 [shape=plain label=\"3\"]\nhier4 [shape=plain label=\"4\"]\nhier5 [shape=plain label=\"5\"]\nhier6 [shape=plain label=\"6\"]\nhier6 -> hier7 [style = \"dashed\"] \nhier6 -> hier8 [style = \"dashed\"] \nhier6 -> hier9 [style = \"dashed\"] \nhier6 -> hier10 [style = \"dashed\"] \nhier7 [shape=plain label=\"7\"]\nhier8 [shape=plain label=\"8\"]\nhier9 [shape=plain label=\"9\"]\nhier10 [shape=plain label=\"10\"]\n}\n" +digraph { +0 [shape=plain label=<
(0) CFG
>] +1 [shape=plain label=<
0
(1) ExitBlock
>] +2 [shape=plain label=<
0
(2) DataflowBlock
01
>] +2:out0 -> 6:in0 [style="dashed"] +2:out1 -> 1:in0 [style="dashed"] +3 [shape=plain label=<
(3) Input
0: usize
>] +3:out0 -> 5:in0 [style=""] +4 [shape=plain label=<
0: [usize]+[usize]
(4) Output
>] +5 [shape=plain label=<
0: usize
(5) Tag
0: [usize]+[usize]
>] +5:out0 -> 4:in0 [style=""] +6 [shape=plain label=<
0
(6) DataflowBlock
0
>] +6:out0 -> 1:in0 [style="dashed"] +7 [shape=plain label=<
(7) Input
0: usize
>] +7:out0 -> 8:in1 [style=""] +8 [shape=plain label=<
0: []1: usize
(8) Output
>] +9 [shape=plain label=<
(9) const:sum:{tag:0, vals:[]}
0: []
>] +9:out0 -> 10:in0 [style=""] +10 [shape=plain label=<
0: []
(10) LoadConstant
0: []
>] +10:out0 -> 8:in0 [style=""] +hier0 [shape=plain label="0"] +hier0 -> hier2 [style = "dashed"] +hier0 -> hier1 [style = "dashed"] +hier0 -> hier6 [style = "dashed"] +hier1 [shape=plain label="1"] +hier2 [shape=plain label="2"] +hier2 -> hier3 [style = "dashed"] +hier2 -> hier4 [style = "dashed"] +hier2 -> hier5 [style = "dashed"] +hier3 [shape=plain label="3"] +hier4 [shape=plain label="4"] +hier5 [shape=plain label="5"] +hier6 [shape=plain label="6"] +hier6 -> hier7 [style = "dashed"] +hier6 -> hier8 [style = "dashed"] +hier6 -> hier9 [style = "dashed"] +hier6 -> hier10 [style = "dashed"] +hier7 [shape=plain label="7"] +hier8 [shape=plain label="8"] +hier9 [shape=plain label="9"] +hier10 [shape=plain label="10"] +} diff --git a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_dfg.snap b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_dfg.snap index 5e7d86242..1eb650776 100644 --- a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_dfg.snap +++ b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_dfg.snap @@ -1,5 +1,27 @@ --- -source: src/hugr/views/tests.rs +source: quantinuum-hugr/src/hugr/views/tests.rs expression: h.dot_string() --- -"digraph {\n0 [shape=plain label=<
(0) DFG
>]\n1 [shape=plain label=<
(1) Input
0: qubit1: qubit
>]\n1:out0 -> 3:in0 [style=\"\"]\n1:out1 -> 3:in1 [style=\"\"]\n2 [shape=plain label=<
0: qubit1: qubit
(2) Output
>]\n3 [shape=plain label=<
0: qubit1: qubit
(3) test.quantum.CX
0: qubit1: qubit
>]\n3:out0 -> 4:in1 [style=\"\"]\n3:out1 -> 4:in0 [style=\"\"]\n3:out2 -> 4:in2 [style=\"dotted\"]\n4 [shape=plain label=<
0: qubit1: qubit
(4) test.quantum.CX
0: qubit1: qubit
>]\n4:out0 -> 2:in0 [style=\"\"]\n4:out1 -> 2:in1 [style=\"\"]\nhier0 [shape=plain label=\"0\"]\nhier0 -> hier1 [style = \"dashed\"] \nhier0 -> hier2 [style = \"dashed\"] \nhier0 -> hier3 [style = \"dashed\"] \nhier0 -> hier4 [style = \"dashed\"] \nhier1 [shape=plain label=\"1\"]\nhier2 [shape=plain label=\"2\"]\nhier3 [shape=plain label=\"3\"]\nhier4 [shape=plain label=\"4\"]\n}\n" +digraph { +0 [shape=plain label=<
(0) DFG
>] +1 [shape=plain label=<
(1) Input
0: qubit1: qubit
>] +1:out0 -> 3:in0 [style=""] +1:out1 -> 3:in1 [style=""] +2 [shape=plain label=<
0: qubit1: qubit
(2) Output
>] +3 [shape=plain label=<
0: qubit1: qubit
(3) test.quantum.CX
0: qubit1: qubit
>] +3:out0 -> 4:in1 [style=""] +3:out1 -> 4:in0 [style=""] +3:out2 -> 4:in2 [style="dotted"] +4 [shape=plain label=<
0: qubit1: qubit
(4) test.quantum.CX
0: qubit1: qubit
>] +4:out0 -> 2:in0 [style=""] +4:out1 -> 2:in1 [style=""] +hier0 [shape=plain label="0"] +hier0 -> hier1 [style = "dashed"] +hier0 -> hier2 [style = "dashed"] +hier0 -> hier3 [style = "dashed"] +hier0 -> hier4 [style = "dashed"] +hier1 [shape=plain label="1"] +hier2 [shape=plain label="2"] +hier3 [shape=plain label="3"] +hier4 [shape=plain label="4"] +} diff --git a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_empty_dfg.snap b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_empty_dfg.snap index 7180af21f..278a39718 100644 --- a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_empty_dfg.snap +++ b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__dot_empty_dfg.snap @@ -1,5 +1,15 @@ --- -source: src/hugr/views/tests.rs +source: quantinuum-hugr/src/hugr/views/tests.rs expression: h.dot_string() --- -"digraph {\n0 [shape=plain label=<
(0) DFG
>]\n1 [shape=plain label=<
(1) Input
0: Sum(UnitSum(2))
>]\n1:out0 -> 2:in0 [style=\"\"]\n2 [shape=plain label=<
0: Sum(UnitSum(2))
(2) Output
>]\nhier0 [shape=plain label=\"0\"]\nhier0 -> hier1 [style = \"dashed\"] \nhier0 -> hier2 [style = \"dashed\"] \nhier1 [shape=plain label=\"1\"]\nhier2 [shape=plain label=\"2\"]\n}\n" +digraph { +0 [shape=plain label=<
(0) DFG
>] +1 [shape=plain label=<
(1) Input
0: []+[]
>] +1:out0 -> 2:in0 [style=""] +2 [shape=plain label=<
0: []+[]
(2) Output
>] +hier0 [shape=plain label="0"] +hier0 -> hier1 [style = "dashed"] +hier0 -> hier2 [style = "dashed"] +hier1 [shape=plain label="1"] +hier2 [shape=plain label="2"] +} diff --git a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_cfg.snap b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_cfg.snap index b796a8c7e..8a89d24ba 100644 --- a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_cfg.snap +++ b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_cfg.snap @@ -1,5 +1,5 @@ --- -source: src/hugr/views/tests.rs +source: quantinuum-hugr/src/hugr/views/tests.rs expression: h.mermaid_string() --- graph LR @@ -11,7 +11,7 @@ graph LR 3--"0:0
usize"-->5 4["(4) Output"] 5["(5) Tag"] - 5--"0:0
Sum(General([TypeRow { types: [Type(Extension(CustomType { extension: IdentList(#quot;prelude#quot;), id: #quot;usize#quot;, args: [], bound: Eq }), Eq)] }, TypeRow { types: [Type(Extension(CustomType { extension: IdentList(#quot;prelude#quot;), id: #quot;usize#quot;, args: [], bound: Eq }), Eq)] }]))"-->4 + 5--"0:0
[usize]+[usize]"-->4 end 2-."0:0".->6 2-."1:0".->1 @@ -22,9 +22,9 @@ graph LR 7--"0:1
usize"-->8 8["(8) Output"] 9["(9) const:sum:{tag:0, vals:[]}"] - 9--"0:0
Sum(UnitSum(1))"-->10 + 9--"0:0
[]"-->10 10["(10) LoadConstant"] - 10--"0:0
Sum(UnitSum(1))"-->8 + 10--"0:0
[]"-->8 end 6-."0:0".->1 end diff --git a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_empty_dfg.snap b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_empty_dfg.snap index d807ab294..df8a755b7 100644 --- a/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_empty_dfg.snap +++ b/quantinuum-hugr/src/hugr/views/snapshots/hugr__hugr__views__tests__mmd_empty_dfg.snap @@ -1,11 +1,11 @@ --- -source: src/hugr/views/tests.rs +source: quantinuum-hugr/src/hugr/views/tests.rs expression: h.mermaid_string() --- graph LR subgraph 0 ["(0) DFG"] direction LR 1["(1) Input"] - 1--"0:0
Sum(UnitSum(2))"-->2 + 1--"0:0
[]+[]"-->2 2["(2) Output"] end diff --git a/quantinuum-hugr/src/hugr/views/tests.rs b/quantinuum-hugr/src/hugr/views/tests.rs index 200d0e89c..678459578 100644 --- a/quantinuum-hugr/src/hugr/views/tests.rs +++ b/quantinuum-hugr/src/hugr/views/tests.rs @@ -71,7 +71,7 @@ fn node_connections( #[case::empty_dfg("dot_empty_dfg", crate::builder::test::simple_dfg_hugr())] #[cfg_attr(miri, ignore)] // Opening files is not supported in (isolated) miri fn dot_string(#[case] test_name: &str, #[case] h: Hugr) { - insta::assert_yaml_snapshot!(test_name, h.dot_string()); + insta::assert_snapshot!(test_name, h.dot_string()); } /// Render some hugrs into mermaid format. diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index f2ba105b5..08c91159e 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -9,6 +9,7 @@ pub mod type_param; pub mod type_row; pub use crate::ops::constant::{ConstTypeError, CustomCheckFailure}; +use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; pub use poly_func::PolyFuncType; @@ -18,7 +19,7 @@ pub use type_param::TypeArg; pub use type_row::TypeRow; use itertools::FoldWhile::{Continue, Done}; -use itertools::Itertools; +use itertools::{repeat_n, Itertools}; use serde::{Deserialize, Serialize}; use crate::extension::{ExtensionRegistry, SignatureError}; @@ -100,20 +101,35 @@ pub(crate) fn least_upper_bound(mut tags: impl Iterator) -> Ty .into_inner() } -#[derive(Clone, PartialEq, Debug, Eq, derive_more::Display, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Debug, Eq, Serialize, Deserialize)] #[serde(tag = "s")] /// Representation of a Sum type. /// Either store the types of the variants, or in the special (but common) case /// of a UnitSum (sum over empty tuples), store only the size of the Sum. pub enum SumType { + /// Special case of a Sum over unit types. #[allow(missing_docs)] - #[display(fmt = "UnitSum({})", "size")] Unit { size: u8 }, + /// General case of a Sum type. #[allow(missing_docs)] - #[display(fmt = "General({:?})", "rows")] General { rows: Vec }, } +impl std::fmt::Display for SumType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.num_variants() == 0 { + return write!(f, "⊥"); + } + + match self { + SumType::Unit { size } => { + display_list_with_separator(repeat_n("[]", *size as usize), f, "+") + } + SumType::General { rows } => display_list_with_separator(rows.iter(), f, "+"), + } + } +} + impl SumType { /// Initialize a new sum type. pub fn new(variants: impl IntoIterator) -> Self @@ -175,10 +191,7 @@ pub enum TypeEnum { #[display(fmt = "Variable({})", _0)] Variable(usize, TypeBound), #[allow(missing_docs)] - #[display(fmt = "Tuple({})", "_0")] - Tuple(TypeRow), - #[allow(missing_docs)] - #[display(fmt = "Sum({})", "_0")] + #[display(fmt = "{}", "_0")] Sum(SumType), } impl TypeEnum { @@ -195,7 +208,6 @@ impl TypeEnum { .flat_map(TypeRow::iter) .map(Type::least_upper_bound), ), - TypeEnum::Tuple(ts) => least_upper_bound(ts.iter().map(Type::least_upper_bound)), } } } @@ -242,7 +254,7 @@ impl Type { /// An empty `TypeRow`. Provided here for convenience pub const EMPTY_TYPEROW: TypeRow = type_row![]; /// Unit type (empty tuple). - pub const UNIT: Self = Self(TypeEnum::Tuple(Self::EMPTY_TYPEROW), TypeBound::Eq); + pub const UNIT: Self = Self(TypeEnum::Sum(SumType::Unit { size: 1 }), TypeBound::Eq); const EMPTY_TYPEROW_REF: &'static TypeRow = &Self::EMPTY_TYPEROW; @@ -254,7 +266,11 @@ impl Type { /// Initialize a new tuple type by providing the elements. #[inline(always)] pub fn new_tuple(types: impl Into) -> Self { - Self::new(TypeEnum::Tuple(types.into())) + let row = types.into(); + match row.len() { + 0 => Self::UNIT, + _ => Self::new_sum([row]), + } } /// Initialize a new sum type by providing the possible variant types. @@ -326,7 +342,6 @@ impl Type { // There is no need to check the components against the bound, // that is guaranteed by construction (even for deserialization) match &self.0 { - TypeEnum::Tuple(row) => validate_each(extension_registry, var_decls, row.iter()), TypeEnum::Sum(SumType::General { rows }) => validate_each( extension_registry, var_decls, @@ -346,7 +361,6 @@ impl Type { TypeEnum::Variable(idx, bound) => t.apply_typevar(*idx, *bound), TypeEnum::Extension(cty) => Type::new_extension(cty.substitute(t)), TypeEnum::Function(bf) => Type::new_function(bf.substitute(t)), - TypeEnum::Tuple(elems) => Type::new_tuple(subst_row(elems, t)), TypeEnum::Sum(SumType::General { rows }) => { Type::new_sum(rows.iter().map(|x| subst_row(x, t))) } @@ -430,8 +444,8 @@ pub(crate) mod test { Type::new_alias(AliasDecl::new("my_alias", TypeBound::Eq)), ]); assert_eq!( - t.to_string(), - "Tuple([usize, Function(forall . [[]][]), my_custom, Alias(my_alias)])".to_string() + &t.to_string(), + "[usize, Function(forall . [[]][]), my_custom, Alias(my_alias)]" ); } diff --git a/quantinuum-hugr/src/types/serialize.rs b/quantinuum-hugr/src/types/serialize.rs index 77859fc40..f2299ffb7 100644 --- a/quantinuum-hugr/src/types/serialize.rs +++ b/quantinuum-hugr/src/types/serialize.rs @@ -1,4 +1,4 @@ -use super::{PolyFuncType, SumType, Type, TypeArg, TypeBound, TypeEnum, TypeRow}; +use super::{PolyFuncType, SumType, Type, TypeArg, TypeBound, TypeEnum}; use super::custom::CustomType; @@ -11,7 +11,6 @@ pub(super) enum SerSimpleType { Q, I, G(Box), - Tuple { inner: TypeRow }, Sum(SumType), Array { inner: Box, len: u64 }, Opaque(CustomType), @@ -35,7 +34,6 @@ impl From for SerSimpleType { TypeEnum::Function(sig) => SerSimpleType::G(sig), TypeEnum::Variable(i, b) => SerSimpleType::V { i, b }, TypeEnum::Sum(sum) => SerSimpleType::Sum(sum), - TypeEnum::Tuple(inner) => SerSimpleType::Tuple { inner }, } } } @@ -46,7 +44,6 @@ impl From for Type { SerSimpleType::Q => QB_T, SerSimpleType::I => USIZE_T, SerSimpleType::G(sig) => Type::new_function(*sig), - SerSimpleType::Tuple { inner } => Type::new_tuple(inner), SerSimpleType::Sum(sum) => sum.into(), SerSimpleType::Array { inner, len } => { array_type(TypeArg::BoundedNat { n: len }, (*inner).into()) diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index a4805b8ed..1f0d379cb 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -55,6 +55,11 @@ impl TypeRow { self.iter().chain(rest).cloned().collect_vec().into() } + /// Returns a reference to the types in the row. + pub fn as_slice(&self) -> &[Type] { + &self.types + } + delegate! { to self.types { /// Iterator over the types in the row. @@ -104,7 +109,7 @@ impl Deref for TypeRow { type Target = [Type]; fn deref(&self) -> &Self::Target { - &self.types + self.as_slice() } } diff --git a/quantinuum-hugr/src/utils.rs b/quantinuum-hugr/src/utils.rs index bf7225e3e..b8230de33 100644 --- a/quantinuum-hugr/src/utils.rs +++ b/quantinuum-hugr/src/utils.rs @@ -5,14 +5,28 @@ use itertools::Itertools; /// Write a comma separated list of of some types. /// Like debug_list, but using the Display instance rather than Debug, /// and not adding surrounding square brackets. -pub fn display_list(ts: &[T], f: &mut fmt::Formatter) -> fmt::Result +pub fn display_list(ts: impl IntoIterator, f: &mut fmt::Formatter) -> fmt::Result +where + T: Display, +{ + display_list_with_separator(ts, f, ", ") +} + +/// Write a separated list of of some types, using a custom separator. +/// Like debug_list, but using the Display instance rather than Debug, +/// and not adding surrounding square brackets. +pub fn display_list_with_separator( + ts: impl IntoIterator, + f: &mut fmt::Formatter, + sep: &str, +) -> fmt::Result where T: Display, { let mut first = true; - for t in ts.iter() { + for t in ts.into_iter() { if !first { - f.write_str(", ")?; + f.write_str(sep)?; } t.fmt(f)?; if first { diff --git a/specification/hugr.md b/specification/hugr.md index dc57299af..46ed8fe2b 100644 --- a/specification/hugr.md +++ b/specification/hugr.md @@ -794,8 +794,7 @@ The Hugr defines a number of type constructors, that can be instantiated into ty Extensions ::= (Extension)* -- a set, not a list -Type ::= Tuple(#) -- fixed-arity, heterogeneous components - | Sum([#]) -- disjoint union of rows of other types, tagged by unsigned int +Type ::= Sum([#]) -- disjoint union of rows of other types, tagged by unsigned int | Opaque(Name, [TypeArg]) -- a (instantiation of a) custom type defined by an extension | Function(TypeParams, #, #, Extensions) -- polymorphic with type parameters, -- function arguments + results, and delta (see below) @@ -804,11 +803,13 @@ Type ::= Tuple(#) -- fixed-arity, heterogeneous components (We write `[Foo]` to indicate a list of Foo's.) +Tuples are represented as Sum types with a single variant. The type `(int<1>,int<2>)` is represented as `Sum([#(int<1>,int<2>)])`. + The majority of types will be Opaque ones defined by extensions including the [standard library](#standard-library). However a number of types can be constructed using only the core type constructors: for example the empty tuple type, aka `unit`, with exactly one instance (so 0 bits of data); the empty sum, with no instances; the empty Function type (taking no arguments and producing no results - `void -> void`); and compositions thereof. Types representing functions are generally `CopyableType`, but not `EqType`. (It is undecidable whether two functions produce the same result for all possible inputs, or similarly whether one computation graph can be rewritten into another by semantic-preserving rewrites). -Tuples and Sums are `CopyableType` (respectively, `EqType`) if all their components are; they are also fixed-size if their components are. +Sums are `CopyableType` (respectively, `EqType`) if all their components are; they are also fixed-size if their components are. ### Polymorphism diff --git a/specification/schema/hugr_schema_v0.json b/specification/schema/hugr_schema_v0.json index db5ad9db3..6092f5636 100644 --- a/specification/schema/hugr_schema_v0.json +++ b/specification/schema/hugr_schema_v0.json @@ -1622,4 +1622,4 @@ ], "title": "Hugr", "type": "object" -} \ No newline at end of file +} diff --git a/specification/schema/hugr_schema_v1.json b/specification/schema/hugr_schema_v1.json index 3e0a38165..1ca87f089 100644 --- a/specification/schema/hugr_schema_v1.json +++ b/specification/schema/hugr_schema_v1.json @@ -1276,28 +1276,6 @@ "title": "TupleParam", "type": "object" }, - "TupleType": { - "description": "Product type, known-size tuple over elements of type row.", - "properties": { - "t": { - "const": "Tuple", - "default": "Tuple", - "title": "T" - }, - "inner": { - "items": { - "$ref": "#/$defs/Type" - }, - "title": "Inner", - "type": "array" - } - }, - "required": [ - "inner" - ], - "title": "TupleType", - "type": "object" - }, "Type": { "description": "A HUGR type.", "discriminator": { @@ -1308,7 +1286,6 @@ "Opaque": "#/$defs/Opaque", "Q": "#/$defs/Qubit", "Sum": "#/$defs/SumType", - "Tuple": "#/$defs/TupleType", "V": "#/$defs/Variable" }, "propertyName": "t" @@ -1329,9 +1306,6 @@ { "$ref": "#/$defs/Array" }, - { - "$ref": "#/$defs/TupleType" - }, { "$ref": "#/$defs/SumType" },