diff --git a/hugr-core/examples/extension/declarative.yaml b/hugr-core/examples/extension/declarative.yaml index a04a1e4bc..b619b0df6 100644 --- a/hugr-core/examples/extension/declarative.yaml +++ b/hugr-core/examples/extension/declarative.yaml @@ -9,7 +9,7 @@ extensions: # Parameters are not currently supported. name: CopyableType description: A simple type with no parameters - # Types may have a "Eq", "Copyable", or "Any" bound. + # Types may have a "Copyable", or "Any" bound. # This field is optional and defaults to "Any". bound: Copyable operations: diff --git a/hugr-core/src/extension/declarative/types.rs b/hugr-core/src/extension/declarative/types.rs index 952c534b6..a0e5cef5a 100644 --- a/hugr-core/src/extension/declarative/types.rs +++ b/hugr-core/src/extension/declarative/types.rs @@ -79,8 +79,6 @@ impl TypeDeclaration { Debug, Copy, Clone, Serialize, Deserialize, Hash, PartialEq, Eq, Default, derive_more::Display, )] enum TypeDefBoundDeclaration { - /// The equality operation is valid on this type. - Eq, /// The type can be copied in the program. Copyable, /// No bound on the type. @@ -91,7 +89,6 @@ enum TypeDefBoundDeclaration { impl From for TypeDefBound { fn from(bound: TypeDefBoundDeclaration) -> Self { match bound { - TypeDefBoundDeclaration::Eq => Self::Explicit(TypeBound::Eq), TypeDefBoundDeclaration::Copyable => Self::Explicit(TypeBound::Copyable), TypeDefBoundDeclaration::Any => Self::Explicit(TypeBound::Any), } diff --git a/hugr-core/src/extension/op_def.rs b/hugr-core/src/extension/op_def.rs index 7babc084a..06114a582 100644 --- a/hugr-core/src/extension/op_def.rs +++ b/hugr-core/src/extension/op_def.rs @@ -674,7 +674,7 @@ pub(super) mod test { assert_eq!(def.validate_args(&args, &PRELUDE_REGISTRY, &[]), Ok(())); // Second arg may be a variable (substitutable) - let tyvar = Type::new_var_use(0, TypeBound::Eq); + let tyvar = Type::new_var_use(0, TypeBound::Copyable); let tyvars: Vec = vec![tyvar.clone(); 3]; let args = [TypeArg::BoundedNat { n: 3 }, tyvar.clone().into()]; assert_eq!( @@ -684,7 +684,7 @@ pub(super) mod test { .with_extension_delta(EXT_ID) ) ); - def.validate_args(&args, &PRELUDE_REGISTRY, &[TypeBound::Eq.into()]) + def.validate_args(&args, &PRELUDE_REGISTRY, &[TypeBound::Copyable.into()]) .unwrap(); // quick sanity check that we are validating the args - note changed bound: @@ -692,7 +692,7 @@ pub(super) mod test { def.validate_args(&args, &PRELUDE_REGISTRY, &[TypeBound::Any.into()]), Err(SignatureError::TypeVarDoesNotMatchDeclaration { actual: TypeBound::Any.into(), - cached: TypeBound::Eq.into() + cached: TypeBound::Copyable.into() }) ); @@ -729,16 +729,16 @@ pub(super) mod test { Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; - let tv = Type::new_var_use(1, TypeBound::Eq); + let tv = Type::new_var_use(1, TypeBound::Copyable); let args = [TypeArg::Type { ty: tv.clone() }]; - let decls = [TypeParam::Extensions, TypeBound::Eq.into()]; + let decls = [TypeParam::Extensions, TypeBound::Copyable.into()]; def.validate_args(&args, &EMPTY_REG, &decls).unwrap(); assert_eq!( def.compute_signature(&args, &EMPTY_REG), Ok(Signature::new_endo(tv).with_extension_delta(EXT_ID)) ); // But not with an external row variable - let arg: TypeArg = TypeRV::new_row_var_use(0, TypeBound::Eq).into(); + let arg: TypeArg = TypeRV::new_row_var_use(0, TypeBound::Copyable).into(); assert_eq!( def.compute_signature(&[arg.clone()], &EMPTY_REG), Err(SignatureError::TypeArgMismatch( diff --git a/hugr-core/src/extension/prelude.rs b/hugr-core/src/extension/prelude.rs index 12a61f19c..c220618fa 100644 --- a/hugr-core/src/extension/prelude.rs +++ b/hugr-core/src/extension/prelude.rs @@ -93,14 +93,14 @@ lazy_static! { TypeName::new_inline("usize"), vec![], "usize".into(), - TypeDefBound::Explicit(crate::types::TypeBound::Eq), + TypeDefBound::Explicit(crate::types::TypeBound::Copyable), ) .unwrap(); prelude.add_type( STRING_TYPE_NAME, vec![], "string".into(), - TypeDefBound::Explicit(crate::types::TypeBound::Eq), + TypeDefBound::Explicit(crate::types::TypeBound::Copyable), ) .unwrap(); prelude.add_op( @@ -137,7 +137,7 @@ lazy_static! { ERROR_TYPE_NAME, vec![], "Simple opaque error type.".into(), - TypeDefBound::Explicit(TypeBound::Eq), + TypeDefBound::Explicit(TypeBound::Copyable), ) .unwrap(); prelude @@ -158,8 +158,11 @@ lazy_static! { } -pub(crate) const USIZE_CUSTOM_T: CustomType = - CustomType::new_simple(TypeName::new_inline("usize"), PRELUDE_ID, TypeBound::Eq); +pub(crate) const USIZE_CUSTOM_T: CustomType = CustomType::new_simple( + TypeName::new_inline("usize"), + PRELUDE_ID, + TypeBound::Copyable, +); pub(crate) const QB_CUSTOM_T: CustomType = CustomType::new_simple(TypeName::new_inline("qubit"), PRELUDE_ID, TypeBound::Any); @@ -214,7 +217,7 @@ pub const STRING_TYPE_NAME: TypeName = TypeName::new_inline("string"); /// Custom type for strings. pub const STRING_CUSTOM_TYPE: CustomType = - CustomType::new_simple(STRING_TYPE_NAME, PRELUDE_ID, TypeBound::Eq); + CustomType::new_simple(STRING_TYPE_NAME, PRELUDE_ID, TypeBound::Copyable); /// String type. pub const STRING_TYPE: Type = Type::new_extension(STRING_CUSTOM_TYPE); @@ -259,7 +262,7 @@ pub const PRINT_OP_ID: OpName = OpName::new_inline("print"); /// The custom type for Errors. pub const ERROR_CUSTOM_TYPE: CustomType = - CustomType::new_simple(ERROR_TYPE_NAME, PRELUDE_ID, TypeBound::Eq); + CustomType::new_simple(ERROR_TYPE_NAME, PRELUDE_ID, TypeBound::Copyable); /// Unspecified opaque error type. pub const ERROR_TYPE: Type = Type::new_extension(ERROR_CUSTOM_TYPE); diff --git a/hugr-core/src/extension/type_def.rs b/hugr-core/src/extension/type_def.rs index 9e0c8753b..bd1e64ffc 100644 --- a/hugr-core/src/extension/type_def.rs +++ b/hugr-core/src/extension/type_def.rs @@ -190,7 +190,7 @@ mod test { ); assert_eq!(typ.least_upper_bound(), TypeBound::Copyable); let typ2 = Type::new_extension(def.instantiate([USIZE_T.into()]).unwrap()); - assert_eq!(typ2.least_upper_bound(), TypeBound::Eq); + assert_eq!(typ2.least_upper_bound(), TypeBound::Copyable); // And some bad arguments...firstly, wrong kind of TypeArg: assert_eq!( diff --git a/hugr-core/src/hugr/serialize/test.rs b/hugr-core/src/hugr/serialize/test.rs index 8285b88b4..e77167951 100644 --- a/hugr-core/src/hugr/serialize/test.rs +++ b/hugr-core/src/hugr/serialize/test.rs @@ -457,8 +457,8 @@ fn polyfunctype1() -> PolyFuncType { fn polyfunctype2() -> PolyFuncTypeRV { let tv0 = TypeRV::new_row_var_use(0, TypeBound::Any); - let tv1 = TypeRV::new_row_var_use(1, TypeBound::Eq); - let params = [TypeBound::Any, TypeBound::Eq].map(TypeParam::new_list); + let tv1 = TypeRV::new_row_var_use(1, TypeBound::Copyable); + let params = [TypeBound::Any, TypeBound::Copyable].map(TypeParam::new_list); let inputs = vec![ TypeRV::new_function(FuncValueType::new(tv0.clone(), tv1.clone())), tv0, @@ -474,7 +474,7 @@ fn polyfunctype2() -> PolyFuncTypeRV { #[case(Signature::new_endo(type_row![]).into())] #[case(polyfunctype1())] #[case(PolyFuncType::new([TypeParam::String], Signature::new_endo(type_row![Type::new_var_use(0, TypeBound::Copyable)])))] -#[case(PolyFuncType::new([TypeBound::Eq.into()], Signature::new_endo(type_row![Type::new_var_use(0, TypeBound::Eq)])))] +#[case(PolyFuncType::new([TypeBound::Copyable.into()], Signature::new_endo(type_row![Type::new_var_use(0, TypeBound::Copyable)])))] #[case(PolyFuncType::new([TypeParam::new_list(TypeBound::Any)], Signature::new_endo(type_row![])))] #[case(PolyFuncType::new([TypeParam::Tuple { params: [TypeBound::Any.into(), TypeParam::bounded_nat(2.try_into().unwrap())].into() }], Signature::new_endo(type_row![])))] #[case(PolyFuncType::new( @@ -487,7 +487,7 @@ fn roundtrip_polyfunctype_fixedlen(#[case] poly_func_type: PolyFuncType) { #[rstest] #[case(FuncValueType::new_endo(type_row![]).into())] #[case(PolyFuncTypeRV::new([TypeParam::String], FuncValueType::new_endo(type_row![Type::new_var_use(0, TypeBound::Copyable)])))] -#[case(PolyFuncTypeRV::new([TypeBound::Eq.into()], FuncValueType::new_endo(type_row![Type::new_var_use(0, TypeBound::Eq)])))] +#[case(PolyFuncTypeRV::new([TypeBound::Copyable.into()], FuncValueType::new_endo(type_row![Type::new_var_use(0, TypeBound::Copyable)])))] #[case(PolyFuncTypeRV::new([TypeParam::new_list(TypeBound::Any)], FuncValueType::new_endo(type_row![])))] #[case(PolyFuncTypeRV::new([TypeParam::Tuple { params: [TypeBound::Any.into(), TypeParam::bounded_nat(2.try_into().unwrap())].into() }], FuncValueType::new_endo(type_row![])))] #[case(PolyFuncTypeRV::new( @@ -506,7 +506,7 @@ fn roundtrip_polyfunctype_varlen(#[case] poly_func_type: PolyFuncTypeRV) { #[case(ops::AliasDecl { name: "aliasdecl".into(), bound: TypeBound::Any})] #[case(ops::Const::new(Value::false_val()))] #[case(ops::Const::new(Value::function(crate::builder::test::simple_dfg_hugr()).unwrap()))] -#[case(ops::Input::new(type_row![Type::new_var_use(3,TypeBound::Eq)]))] +#[case(ops::Input::new(type_row![Type::new_var_use(3,TypeBound::Copyable)]))] #[case(ops::Output::new(vec![Type::new_function(FuncValueType::new_endo(type_row![]))]))] #[case(ops::Call::try_new(polyfunctype1(), [TypeArg::BoundedNat{n: 1}, TypeArg::Extensions{ es: ExtensionSet::singleton(&PRELUDE_ID)} ], &EMPTY_REG).unwrap())] #[case(ops::CallIndirect { signature : Signature::new_endo(type_row![BOOL_T]) })] diff --git a/hugr-core/src/ops/constant.rs b/hugr-core/src/ops/constant.rs index f2954c476..59a79f8f2 100644 --- a/hugr-core/src/ops/constant.rs +++ b/hugr-core/src/ops/constant.rs @@ -714,15 +714,15 @@ mod test { "my_type", vec![TypeArg::BoundedNat { n: 8 }], ex_id.clone(), - TypeBound::Eq, + TypeBound::Copyable, ); let json_const: Value = CustomSerialized::new(typ_int.clone(), 6.into(), ex_id.clone()).into(); let classic_t = Type::new_extension(typ_int.clone()); - assert_matches!(classic_t.least_upper_bound(), TypeBound::Eq); + assert_matches!(classic_t.least_upper_bound(), TypeBound::Copyable); assert_eq!(json_const.get_type(), classic_t); - let typ_qb = CustomType::new("my_type", vec![], ex_id, TypeBound::Eq); + let typ_qb = CustomType::new("my_type", vec![], ex_id, TypeBound::Copyable); let t = Type::new_extension(typ_qb.clone()); assert_ne!(json_const.get_type(), t); } diff --git a/hugr-core/src/std_extensions/arithmetic/int_types.rs b/hugr-core/src/std_extensions/arithmetic/int_types.rs index 5ff2abea3..49a4cb868 100644 --- a/hugr-core/src/std_extensions/arithmetic/int_types.rs +++ b/hugr-core/src/std_extensions/arithmetic/int_types.rs @@ -24,7 +24,12 @@ pub const INT_TYPE_ID: TypeName = TypeName::new_inline("int"); /// the operation, the semantic interpretation may be unsigned integer, signed /// integer or bit string. pub fn int_custom_type(width_arg: impl Into) -> CustomType { - CustomType::new(INT_TYPE_ID, [width_arg.into()], EXTENSION_ID, TypeBound::Eq) + CustomType::new( + INT_TYPE_ID, + [width_arg.into()], + EXTENSION_ID, + TypeBound::Copyable, + ) } /// Integer type of a given bit width (specified by the TypeArg). @@ -187,7 +192,7 @@ pub fn extension() -> Extension { INT_TYPE_ID, vec![LOG_WIDTH_TYPE_PARAM], "integral value of a given bit width".to_owned(), - TypeBound::Eq.into(), + TypeBound::Copyable.into(), ) .unwrap(); diff --git a/hugr-core/src/std_extensions/ptr.rs b/hugr-core/src/std_extensions/ptr.rs index 3073e4cea..774cd6376 100644 --- a/hugr-core/src/std_extensions/ptr.rs +++ b/hugr-core/src/std_extensions/ptr.rs @@ -88,7 +88,7 @@ fn extension() -> Extension { PTR_TYPE_ID, TYPE_PARAMS.into(), "Standard extension pointer type.".into(), - TypeDefBound::Explicit(TypeBound::Eq), + TypeDefBound::Explicit(TypeBound::Copyable), ) .unwrap(); PtrOpDef::load_all_ops(&mut extension).unwrap(); @@ -109,7 +109,7 @@ lazy_static! { /// integer or bit string. pub fn ptr_custom_type(ty: impl Into) -> CustomType { let ty = ty.into(); - CustomType::new(PTR_TYPE_ID, [ty.into()], EXTENSION_ID, TypeBound::Eq) + CustomType::new(PTR_TYPE_ID, [ty.into()], EXTENSION_ID, TypeBound::Copyable) } /// Integer type of a given bit width (specified by the TypeArg). diff --git a/hugr-core/src/types.rs b/hugr-core/src/types.rs index 21d06048c..287175828 100644 --- a/hugr-core/src/types.rs +++ b/hugr-core/src/types.rs @@ -78,11 +78,8 @@ impl EdgeKind { #[cfg_attr(test, derive(Arbitrary))] /// Bounds on the valid operations on a type in a HUGR program. pub enum TypeBound { - /// The equality operation is valid on this type. - #[serde(rename = "E")] - Eq, /// The type can be copied in the program. - #[serde(rename = "C")] + #[serde(rename = "C", alias = "E")] // alias to read in legacy Eq variants Copyable, /// No bound on the type. #[serde(rename = "A")] @@ -105,13 +102,13 @@ impl TypeBound { /// Report if this bound contains another. pub const fn contains(&self, other: TypeBound) -> bool { use TypeBound::*; - matches!((self, other), (Any, _) | (_, Eq) | (Copyable, Copyable)) + matches!((self, other), (Any, _) | (_, Copyable)) } } /// Calculate the least upper bound for an iterator of bounds pub(crate) fn least_upper_bound(mut tags: impl Iterator) -> TypeBound { - tags.fold_while(TypeBound::Eq, |acc, new| { + tags.fold_while(TypeBound::Copyable, |acc, new| { if acc == TypeBound::Any || new == TypeBound::Any { Done(TypeBound::Any) } else { @@ -247,7 +244,7 @@ impl TypeEnum { TypeEnum::Function(_) => TypeBound::Copyable, TypeEnum::Variable(_, b) => *b, TypeEnum::RowVar(b) => b.bound(), - TypeEnum::Sum(SumType::Unit { size: _ }) => TypeBound::Eq, + TypeEnum::Sum(SumType::Unit { size: _ }) => TypeBound::Copyable, TypeEnum::Sum(SumType::General { rows }) => least_upper_bound( rows.iter() .flat_map(TypeRowRV::iter) @@ -274,7 +271,7 @@ impl TypeEnum { /// # use hugr::type_row; /// /// let sum = Type::new_sum([type_row![], type_row![]]); -/// assert_eq!(sum.least_upper_bound(), TypeBound::Eq); +/// assert_eq!(sum.least_upper_bound(), TypeBound::Copyable); /// ``` /// /// ``` @@ -316,7 +313,10 @@ impl TypeBase { /// An empty `TypeRow` or `TypeRowRV`. Provided here for convenience pub const EMPTY_TYPEROW: TypeRowBase = TypeRowBase::::new(); /// Unit type (empty tuple). - pub const UNIT: Self = Self(TypeEnum::Sum(SumType::Unit { size: 1 }), TypeBound::Eq); + pub const UNIT: Self = Self( + TypeEnum::Sum(SumType::Unit { size: 1 }), + TypeBound::Copyable, + ); const EMPTY_TYPEROW_REF: &'static TypeRowBase = &Self::EMPTY_TYPEROW; @@ -364,7 +364,7 @@ impl TypeBase { /// New UnitSum with empty Tuple variants pub const fn new_unit_sum(size: u8) -> Self { // should be the only way to avoid going through SumType::new - Self(TypeEnum::Sum(SumType::new_unary(size)), TypeBound::Eq) + Self(TypeEnum::Sum(SumType::new_unary(size)), TypeBound::Copyable) } /// New use (occurrence) of the type variable with specified index. @@ -620,7 +620,7 @@ pub(crate) mod test { "my_extension".try_into().unwrap(), TypeBound::Copyable, )), - Type::new_alias(AliasDecl::new("my_alias", TypeBound::Eq)), + Type::new_alias(AliasDecl::new("my_alias", TypeBound::Copyable)), ]); assert_eq!( &t.to_string(), diff --git a/hugr-core/src/types/poly_func.rs b/hugr-core/src/types/poly_func.rs index a8bd1b45b..4f6df034b 100644 --- a/hugr-core/src/types/poly_func.rs +++ b/hugr-core/src/types/poly_func.rs @@ -357,7 +357,7 @@ pub(crate) mod test { fn test_bound_covariance() -> Result<(), SignatureError> { decl_accepts_rejects_var( TypeBound::Copyable.into(), - &[TypeBound::Copyable.into(), TypeBound::Eq.into()], + &[TypeBound::Copyable.into()], &[TypeBound::Any.into()], )?; @@ -366,7 +366,7 @@ pub(crate) mod test { }; decl_accepts_rejects_var( list_of_tys(TypeBound::Copyable), - &[list_of_tys(TypeBound::Copyable), list_of_tys(TypeBound::Eq)], + &[list_of_tys(TypeBound::Copyable)], &[list_of_tys(TypeBound::Any)], )?; diff --git a/hugr-core/src/types/type_param.rs b/hugr-core/src/types/type_param.rs index cd5cb9d43..b1df98750 100644 --- a/hugr-core/src/types/type_param.rs +++ b/hugr-core/src/types/type_param.rs @@ -450,21 +450,21 @@ mod test { check_type_arg(&arg, param) } // Simple cases: a TypeArg::Type is a TypeParam::Type but singleton sequences are lists - check(USIZE_T, &TypeBound::Eq.into()).unwrap(); - let seq_param = TypeParam::new_list(TypeBound::Eq); + check(USIZE_T, &TypeBound::Copyable.into()).unwrap(); + let seq_param = TypeParam::new_list(TypeBound::Copyable); check(USIZE_T, &seq_param).unwrap_err(); check_seq(&[USIZE_T], &TypeBound::Any.into()).unwrap_err(); // Into a list of type, we can fit a single row var - check(rowvar(0, TypeBound::Eq), &seq_param).unwrap(); + check(rowvar(0, TypeBound::Copyable), &seq_param).unwrap(); // or a list of (types or row vars) check(vec![], &seq_param).unwrap(); - check_seq(&[rowvar(0, TypeBound::Eq)], &seq_param).unwrap(); + check_seq(&[rowvar(0, TypeBound::Copyable)], &seq_param).unwrap(); check_seq( &[ rowvar(1, TypeBound::Any), USIZE_T.into(), - rowvar(0, TypeBound::Eq), + rowvar(0, TypeBound::Copyable), ], &TypeParam::new_list(TypeBound::Any), ) @@ -474,7 +474,7 @@ mod test { &[ rowvar(1, TypeBound::Any), USIZE_T.into(), - rowvar(0, TypeBound::Eq), + rowvar(0, TypeBound::Copyable), ], &seq_param, ) @@ -502,7 +502,7 @@ mod test { // TypeParam::Tuples require a TypeArg::Seq of the same number of elems let usize_and_ty = TypeParam::Tuple { - params: vec![TypeParam::max_nat(), TypeBound::Eq.into()], + params: vec![TypeParam::max_nat(), TypeBound::Copyable.into()], }; check(vec![5.into(), USIZE_T.into()], &usize_and_ty).unwrap(); check(vec![USIZE_T.into(), 5.into()], &usize_and_ty).unwrap_err(); // Wrong way around diff --git a/hugr-py/src/hugr/serialization/tys.py b/hugr-py/src/hugr/serialization/tys.py index 1ec033bc6..707f1ed96 100644 --- a/hugr-py/src/hugr/serialization/tys.py +++ b/hugr-py/src/hugr/serialization/tys.py @@ -381,18 +381,17 @@ def deserialize(self) -> tys.PolyFuncType: class TypeBound(Enum): - Eq = "E" Copyable = "C" Any = "A" @staticmethod def join(*bs: TypeBound) -> TypeBound: """Computes the least upper bound for a sequence of bounds.""" - res = TypeBound.Eq + res = TypeBound.Copyable for b in bs: if b == TypeBound.Any: return TypeBound.Any - if res == TypeBound.Eq: + if res == TypeBound.Copyable: res = b return res diff --git a/hugr-py/src/hugr/std/int.py b/hugr-py/src/hugr/std/int.py index a6a560cb0..67e7137d8 100644 --- a/hugr-py/src/hugr/std/int.py +++ b/hugr-py/src/hugr/std/int.py @@ -32,7 +32,7 @@ def int_t(width: int) -> tys.Opaque: extension="arithmetic.int.types", id="int", args=[tys.BoundedNatArg(n=width)], - bound=tys.TypeBound.Eq, + bound=tys.TypeBound.Copyable, ) diff --git a/hugr-py/tests/test_hugr_build.py b/hugr-py/tests/test_hugr_build.py index bf327c9f6..b02cde251 100644 --- a/hugr-py/tests/test_hugr_build.py +++ b/hugr-py/tests/test_hugr_build.py @@ -280,6 +280,6 @@ def test_lift() -> None: def test_alias() -> None: mod = Module() _dfn = mod.add_alias_defn("my_int", INT_T) - _dcl = mod.add_alias_decl("my_bool", tys.TypeBound.Eq) + _dcl = mod.add_alias_decl("my_bool", tys.TypeBound.Copyable) validate(mod.hugr) diff --git a/specification/hugr.md b/specification/hugr.md index 1800aa601..763e10700 100644 --- a/specification/hugr.md +++ b/specification/hugr.md @@ -787,24 +787,20 @@ indices after the list of node indices? ## Type System -There are three classes of type: `AnyType` $\supset$ `CopyableType` $\supset$ `EqType`. Types in these classes are distinguished by the operations possible on (runtime) values of those types: +There are two classes of type: `AnyType` $\supset$ `CopyableType`. Types in these +classes are distinguished by whether the runtime values of those types can be implicitly +copied or discarded (multiple or 0 links from on output port respectively): - For the broadest class (`AnyType`), the only operation supported is the identity operation (aka no-op, or `lift` - see [Extension Tracking](#extension-tracking) below). Specifically, we do not require it to be possible to copy or discard all values, hence the requirement that outports of linear type must have exactly one edge. (That is, a type not known to be in the copyable subset). All incoming ports must have exactly one edge. In fully qubit-counted contexts programs take in a number of qubits as input and return the same number, with no discarding. -- The next class is `CopyableType`, i.e. types holding ordinary classical +- The smaller class is `CopyableType`, i.e. types holding ordinary classical data, where values can be copied (and discarded, the 0-ary copy). This allows multiple (or 0) outgoing edges from an outport; also these types can be sent down `Const` edges. Note: dataflow inputs (`Value`, `Const` and `Function`) always require a single connection. -- The final class is `EqType`: these are copyable types with a well-defined - notion of equality between values. (While *some* notion of equality is defined on - any type with a binary representation, that if the bits are equal then the value is, the converse is not necessarily true - values that are indistinguishable can have different bit representations.) - -For example, a `float` type (defined in an extension) would be a `CopyableType`, but not an `EqType`. - **Rows** The `#` is a *row* which is a sequence of zero or more types. Types in the row can optionally be given names in metadata i.e. this does not affect behaviour of the HUGR. When writing literal types, we use `#` to distinguish between tuples and rows, e.g. `(int<1>,int<2>)` is a tuple while `Sum(#(int<1>),#(int<2>))` contains two rows. The Hugr defines a number of type constructors, that can be instantiated into types by providing some collection of types as arguments. The constructors are given in the following grammar: @@ -825,9 +821,7 @@ Tuples are represented as Sum types with a single variant. The type `(int<1>,int 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). - -Sums are `CopyableType` (respectively, `EqType`) if all their components are; they are also fixed-size if their components are. +Sums are `CopyableType` if all their components are; they are also fixed-size if their components are. ### Polymorphism @@ -836,7 +830,7 @@ While function *values* passed around the graph at runtime have types that are m such declarations may include (bind) any number of type parameters, of kinds as follows: ```haskell -TypeParam ::= Type(Any|Copyable|Eq) +TypeParam ::= Type(Any|Copyable) | BoundedUSize(u64|) -- note optional bound | Extensions | List(TypeParam) -- homogeneous, any sized diff --git a/specification/schema/hugr_schema_live.json b/specification/schema/hugr_schema_live.json index bd0e59f60..f3db83a57 100644 --- a/specification/schema/hugr_schema_live.json +++ b/specification/schema/hugr_schema_live.json @@ -1659,7 +1659,6 @@ }, "TypeBound": { "enum": [ - "E", "C", "A" ], diff --git a/specification/schema/hugr_schema_strict_live.json b/specification/schema/hugr_schema_strict_live.json index f2373efe9..1a9de7e23 100644 --- a/specification/schema/hugr_schema_strict_live.json +++ b/specification/schema/hugr_schema_strict_live.json @@ -1659,7 +1659,6 @@ }, "TypeBound": { "enum": [ - "E", "C", "A" ], diff --git a/specification/schema/testing_hugr_schema_live.json b/specification/schema/testing_hugr_schema_live.json index aa61a5549..b64d79048 100644 --- a/specification/schema/testing_hugr_schema_live.json +++ b/specification/schema/testing_hugr_schema_live.json @@ -1736,7 +1736,6 @@ }, "TypeBound": { "enum": [ - "E", "C", "A" ], diff --git a/specification/schema/testing_hugr_schema_strict_live.json b/specification/schema/testing_hugr_schema_strict_live.json index db1ea9fd7..0d07bf374 100644 --- a/specification/schema/testing_hugr_schema_strict_live.json +++ b/specification/schema/testing_hugr_schema_strict_live.json @@ -1736,7 +1736,6 @@ }, "TypeBound": { "enum": [ - "E", "C", "A" ],