diff --git a/specification/hugr.md b/specification/hugr.md index 4a96e7a97..25a6eedac 100644 --- a/specification/hugr.md +++ b/specification/hugr.md @@ -544,7 +544,7 @@ may be a `FuncDefn`, `TailLoop`, `DFG`, `Case` or `DFB` node. #### `ErrorType` - There is some type of errors, perhaps just a string, or - `Tuple(Int,String)` with some errorcode, that is returned along with + `Tuple(USize,String)` with some errorcode, that is returned along with the fact that the graph/program panicked. #### Catch @@ -837,7 +837,7 @@ resources: types: - name: QubitVector # Opaque types can take type arguments, with specified names - params: [["size", Int]] + params: [["size", USize]] operations: - name: measure description: "measure a qubit" @@ -865,9 +865,9 @@ resources: - name: MatMul description: "Multiply matrices of statically-known size" params: # per-node values passed to type-scheme-interpreter and used in signature - - i: Int - - j: Int - - k: Int + - i: USize + - j: USize + - k: USize signature: inputs: [["a", Array(Array(F64))], ["b", Array(Array(F64))]] outputs: [[null, Array(Array(F64))]] @@ -876,7 +876,7 @@ resources: - name: max_float description: "Variable number of inputs" params: - - n: Int + - n: USize signature: # Where an element of a signature has three subelements, the third is the number of repeats inputs: [[null, F64, n]] # (defaulting to 1 if omitted) @@ -885,8 +885,8 @@ resources: description: "Concatenate two arrays. Resource provides a compute_signature implementation." params: - t: Type # Classic or Quantum - - i: Int - - j: Int + - i: USize + - j: USize # inputs could be: Array(t), Array(t) # outputs would be, in principle: Array(t) # - but default type scheme interpreter does not support such addition @@ -896,8 +896,8 @@ resources: params: - r: ResourceSet signature: - inputs: [[null, Graph[r](Int -> Int)], ["arg", Int]] - outputs: [[null, Int]] + inputs: [[null, Graph[r](USize -> USize)], ["arg", USize]] + outputs: [[null, USize]] resources: r # Indicates that running this operation also invokes resources r lowering: file: "graph_op_hugr.bin" @@ -908,7 +908,7 @@ The declaration of the `params` uses a language that is a distinct, simplified form of the [Type System](#type-system) - writing terminals that appear in the YAML in quotes, the value of each member of `params` is given by the following production: ``` -TypeParam ::= "Type" | "ClassicType" | Int | "List"(TypeParam) +TypeParam ::= "Type" | "ClassicType" | USize | "List"(TypeParam) ``` **Implementation note** Reading this format into Rust is made easy by `serde` and @@ -1000,7 +1000,7 @@ Container(T) ::= Tuple(#(T)) | Array(T) | NewType(Name, T) | Sum (#(T)) -ClassicType ::= int +ClassicType ::= USize | Var(X) | String | Graph[R](#, #) @@ -1019,15 +1019,14 @@ sent down Static edges. Function signatures are made up of *rows* (\#), which consist of an arbitrary number of SimpleTypes, plus a resource spec. -ClassicTypes such as `int` (where `N` is the bit-width) are fixed-size, as is -Qubit. +The `USize` type represents 64-bit unsigned integers. + +ClassicTypes such as `USize` are fixed-size, as is Qubit. `Sum` is a disjoint union tagged by unsigned int; `Tuple`s have statically-known number and type of elements, as does `Array` (where N is a static constant). These types are also fixed-size if their components are. -For integer types, the width is provided in the type, and signedness is left unspecified to be interpreted by operations. The width is allowed to be 2^i for i in the range [0,7], so the allowed integer types are [I1, I2, I4, ... , I128]. - Container types are defined in terms of statically-known element types. Besides `Array`, `Sum` and `Tuple`, these also include the variable-sized types: `Graph`. `NewType` diff --git a/src/builder.rs b/src/builder.rs index f1193ef06..a7ccbd5c6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -96,7 +96,7 @@ mod test { use super::{DataflowSubContainer, HugrBuilder}; pub(super) const NAT: SimpleType = SimpleType::Classic(ClassicType::i64()); - pub(super) const BIT: SimpleType = SimpleType::Classic(ClassicType::bit()); + pub(super) const BIT: SimpleType = SimpleType::Classic(ClassicType::usize()); pub(super) const QB: SimpleType = SimpleType::Qubit; /// Wire up inputs of a Dataflow container to the outputs. diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index d0de055a9..5bd05a614 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -110,9 +110,9 @@ mod test { #[test] fn basic_loop() -> Result<(), BuildError> { let build_result: Result = { - let mut loop_b = TailLoopBuilder::new(vec![], vec![BIT], vec![ClassicType::i64()])?; + let mut loop_b = TailLoopBuilder::new(vec![], vec![BIT], vec![ClassicType::usize()])?; let [i1] = loop_b.input_wires_arr(); - let const_wire = loop_b.add_load_const(Const::i64(1)?)?; + let const_wire = loop_b.add_load_const(Const::usize(1)?)?; let break_wire = loop_b.make_break(loop_b.loop_signature()?.clone(), [const_wire])?; loop_b.set_outputs(break_wire, [i1])?; @@ -135,7 +135,7 @@ mod test { let [b1] = fbuild.input_wires_arr(); let loop_id = { let mut loop_b = fbuild.tail_loop_builder( - vec![(ClassicType::bit(), b1)], + vec![(ClassicType::usize(), b1)], vec![], classic_row![ClassicType::i64()], )?; @@ -160,7 +160,7 @@ mod test { let mut branch_1 = conditional_b.case_builder(1)?; let [_b1] = branch_1.input_wires_arr(); - let wire = branch_1.add_load_const(Const::i64(2)?)?; + let wire = branch_1.add_load_const(Const::usize(2)?)?; let break_wire = branch_1.make_break(signature, [wire])?; branch_1.finish_with_outputs([break_wire])?; diff --git a/src/extensions/arithmetic/int_types.rs b/src/extensions/arithmetic/int_types.rs index 2f43d4b9e..d7bfe321b 100644 --- a/src/extensions/arithmetic/int_types.rs +++ b/src/extensions/arithmetic/int_types.rs @@ -70,6 +70,8 @@ pub fn resource() -> Resource { #[cfg(test)] mod test { + use cool_asserts::assert_matches; + use super::*; #[test] @@ -79,4 +81,25 @@ mod test { assert_eq!(r.types().count(), 1); assert_eq!(r.operations().count(), 0); } + + #[test] + fn test_int_widths() { + let type_arg_32 = TypeArg::USize(32); + assert_matches!(get_width(&type_arg_32), Ok(32)); + + let type_arg_33 = TypeArg::USize(33); + assert_matches!( + get_width(&type_arg_33), + Err(SignatureError::TypeArgMismatch(_)) + ); + + let type_arg_128 = TypeArg::USize(128); + assert_matches!(get_width(&type_arg_128), Ok(128)); + + let type_arg_256 = TypeArg::USize(256); + assert_matches!( + get_width(&type_arg_256), + Err(SignatureError::TypeArgMismatch(_)) + ); + } } diff --git a/src/hugr/rewrite/simple_replace.rs b/src/hugr/rewrite/simple_replace.rs index cd8b7a804..6b941b76c 100644 --- a/src/hugr/rewrite/simple_replace.rs +++ b/src/hugr/rewrite/simple_replace.rs @@ -509,8 +509,9 @@ mod test { #[test] fn test_replace_after_copy() { - let one_bit: Vec = vec![ClassicType::bit().into()]; - let two_bit: Vec = vec![ClassicType::bit().into(), ClassicType::bit().into()]; + let one_bit: Vec = vec![ClassicType::usize().into()]; + let two_bit: Vec = + vec![ClassicType::usize().into(), ClassicType::usize().into()]; let mut builder = DFGBuilder::new(AbstractSignature::new_df(one_bit.clone(), one_bit.clone())).unwrap(); diff --git a/src/hugr/serialize.rs b/src/hugr/serialize.rs index 7a414d0e1..2ac4c74f9 100644 --- a/src/hugr/serialize.rs +++ b/src/hugr/serialize.rs @@ -303,13 +303,13 @@ pub mod test { match (inputs == 0, outputs == 0) { (false, false) => DFG { signature: AbstractSignature::new_df( - vec![ClassicType::bit().into(); inputs - 1], - vec![ClassicType::bit().into(); outputs - 1], + vec![ClassicType::usize().into(); inputs - 1], + vec![ClassicType::usize().into(); outputs - 1], ), } .into(), - (true, false) => Input::new(vec![ClassicType::bit().into(); outputs - 1]).into(), - (false, true) => Output::new(vec![ClassicType::bit().into(); inputs - 1]).into(), + (true, false) => Input::new(vec![ClassicType::usize().into(); outputs - 1]).into(), + (false, true) => Output::new(vec![ClassicType::usize().into(); inputs - 1]).into(), (true, true) => Module.into(), } } @@ -433,7 +433,7 @@ pub mod test { #[test] fn dfg_roundtrip() -> Result<(), Box> { - let tp: Vec = vec![ClassicType::bit().into(); 2]; + let tp: Vec = vec![ClassicType::usize().into(); 2]; let mut dfg = DFGBuilder::new(AbstractSignature::new_df(tp.clone(), tp))?; let mut params: [_; 2] = dfg.input_wires_arr(); for p in params.iter_mut() { diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index 03a5b5f33..e4e721de6 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -755,7 +755,7 @@ mod test { use crate::{type_row, Node}; const NAT: SimpleType = SimpleType::Classic(ClassicType::i64()); - const B: SimpleType = SimpleType::Classic(ClassicType::bit()); + const B: SimpleType = SimpleType::Classic(ClassicType::usize()); const Q: SimpleType = SimpleType::Qubit; /// Creates a hugr with a single function definition that copies a bit `copies` times. @@ -791,7 +791,7 @@ mod test { .add_op_with_parent( parent, LeafOp::Noop { - ty: ClassicType::bit().into(), + ty: ClassicType::usize().into(), }, ) .unwrap(); @@ -878,7 +878,7 @@ mod test { #[test] fn leaf_root() { let leaf_op: OpType = LeafOp::Noop { - ty: HashableType::Int(32).into(), + ty: HashableType::USize.into(), } .into(); @@ -968,7 +968,7 @@ mod test { b.replace_op( output, NodeType::pure(LeafOp::Noop { - ty: ClassicType::bit().into(), + ty: ClassicType::usize().into(), }), ); assert_matches!( @@ -1147,11 +1147,11 @@ mod test { }) ); // Second input of Xor from a constant - let cst = h.add_op_with_parent(h.root(), ops::Const::int::<1>(1).unwrap())?; + let cst = h.add_op_with_parent(h.root(), ops::Const::usize(1).unwrap())?; let lcst = h.add_op_with_parent( h.root(), ops::LoadConstant { - datatype: ClassicType::int::<1>(), + datatype: ClassicType::usize(), }, )?; h.connect(cst, 0, lcst, 0)?; diff --git a/src/macros.rs b/src/macros.rs index eb97ce04c..9dfb67d78 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -44,7 +44,7 @@ pub(crate) use impl_box_clone; /// ``` /// # use hugr::macros::type_row; /// # use hugr::types::{AbstractSignature, ClassicType, SimpleType, SimpleRow}; -/// const B: SimpleType = SimpleType::Classic(ClassicType::bit()); +/// const B: SimpleType = SimpleType::Classic(ClassicType::usize()); /// const QB: SimpleType = SimpleType::Qubit; /// let static_row: SimpleRow = type_row![B, QB]; /// let dynamic_row: SimpleRow = vec![B, B, B].into(); @@ -93,8 +93,8 @@ macro_rules! type_row { /// ``` /// # use hugr::macros::classic_row; /// # use hugr::types::{ClassicType, Signature, ClassicRow}; -/// const B: ClassicType = ClassicType::bit(); -/// const I: ClassicType = ClassicType::int::<2>(); +/// const B: ClassicType = ClassicType::usize(); +/// const I: ClassicType = ClassicType::usize(); /// let static_row: ClassicRow = classic_row![B, B]; /// let dynamic_row: ClassicRow = vec![B, B, I].into(); /// diff --git a/src/ops/constant.rs b/src/ops/constant.rs index 35f7e1a40..7497547be 100644 --- a/src/ops/constant.rs +++ b/src/ops/constant.rs @@ -78,19 +78,14 @@ impl Const { Self::simple_predicate(0, 2) } - /// Fixed width integer - pub fn int(value: HugrIntValueStore) -> Result { + /// Size + pub fn usize(value: u64) -> Result { Self::new( ConstValue::Hashable(HashableValue::Int(value)), - ClassicType::int::(), + ClassicType::usize(), ) } - /// 64-bit integer - pub fn i64(value: i64) -> Result { - Self::int::<64>(value as HugrIntValueStore) - } - /// Tuple of values pub fn new_tuple(items: impl IntoIterator) -> Self { let (values, types): (Vec, Vec) = items @@ -123,11 +118,6 @@ impl OpTrait for Const { } } -pub(crate) type HugrIntValueStore = u128; -pub(crate) type HugrIntWidthStore = u8; -pub(crate) const HUGR_MAX_INT_WIDTH: HugrIntWidthStore = - HugrIntValueStore::BITS as HugrIntWidthStore; - /// Value constants. (This could be "ClassicValue" to parallel [HashableValue]) #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] #[non_exhaustive] @@ -335,7 +325,7 @@ mod test { types::custom::test::{CLASSIC_CUST, CLASSIC_T}, types::{simple::Container, type_param::TypeArg}, types::{AbstractSignature, ClassicType, CustomType, SimpleRow, SimpleType, TypeTag}, - values::{ConstIntError, ConstTypeError, CustomCheckFail, HashableValue, ValueOfType}, + values::{ConstTypeError, CustomCheckFail, HashableValue, ValueOfType}, }; fn custom_value(f: f64) -> ConstValue { @@ -387,13 +377,9 @@ mod test { #[test] fn test_constant_values() { - const T_INT: ClassicType = ClassicType::int::<64>(); + const T_INT: ClassicType = ClassicType::usize(); const V_INT: ConstValue = ConstValue::Hashable(HashableValue::Int(257)); V_INT.check_type(&T_INT).unwrap(); - assert_eq!( - V_INT.check_type(&ClassicType::int::<8>()), - Err(ConstTypeError::Int(ConstIntError::IntTooLarge(8, 257))) - ); custom_value(17.4).check_type(&CLASSIC_T).unwrap(); assert_matches!( V_INT.check_type(&CLASSIC_T), diff --git a/src/ops/custom.rs b/src/ops/custom.rs index b4f4a8472..a829b1dab 100644 --- a/src/ops/custom.rs +++ b/src/ops/custom.rs @@ -265,12 +265,12 @@ mod test { "res".into(), "op", "desc".into(), - vec![TypeArg::Type(HashableType::Int(1).into())], + vec![TypeArg::Type(HashableType::USize.into())], None, ); let op: ExternalOp = op.into(); assert_eq!(op.name(), "res.op"); assert_eq!(op.description(), "desc"); - assert_eq!(op.args(), &[TypeArg::Type(HashableType::Int(1).into())]); + assert_eq!(op.args(), &[TypeArg::Type(HashableType::USize.into())]); } } diff --git a/src/ops/leaf.rs b/src/ops/leaf.rs index 1ce75f3b6..c72bd82e4 100644 --- a/src/ops/leaf.rs +++ b/src/ops/leaf.rs @@ -152,7 +152,7 @@ impl OpTrait for LeafOp { // Static signatures. The `TypeRow`s in the `AbstractSignature` use a // copy-on-write strategy, so we can avoid unnecessary allocations. const Q: SimpleType = SimpleType::Qubit; - const B: SimpleType = SimpleType::Classic(ClassicType::bit()); + const B: SimpleType = SimpleType::Classic(ClassicType::usize()); match self { LeafOp::Noop { ty: typ } => { diff --git a/src/ops/validate.rs b/src/ops/validate.rs index 064a93bfc..c1466a70d 100644 --- a/src/ops/validate.rs +++ b/src/ops/validate.rs @@ -464,7 +464,7 @@ mod test { #[test] fn test_validate_io_nodes() { - const B: SimpleType = SimpleType::Classic(ClassicType::bit()); + const B: SimpleType = SimpleType::Classic(ClassicType::usize()); let in_types = type_row![B]; let out_types = type_row![B, B]; @@ -472,7 +472,7 @@ mod test { let input_node: OpType = ops::Input::new(in_types.clone()).into(); let output_node = ops::Output::new(out_types.clone()).into(); let leaf_node = LeafOp::Noop { - ty: ClassicType::bit().into(), + ty: ClassicType::usize().into(), } .into(); diff --git a/src/types/simple.rs b/src/types/simple.rs index 63d885c92..0013c7e3c 100644 --- a/src/types/simple.rs +++ b/src/types/simple.rs @@ -1,10 +1,10 @@ //! Dataflow types -use std::fmt::{self, Display, Formatter, Write}; +use std::fmt::{self, Display, Formatter}; use super::type_row::{TypeRow, TypeRowElem}; use super::{custom::CustomType, AbstractSignature}; -use crate::{classic_row, ops::constant::HugrIntWidthStore}; +use crate::classic_row; use itertools::Itertools; use serde_repr::{Deserialize_repr, Serialize_repr}; use smol_str::SmolStr; @@ -195,8 +195,8 @@ pub enum HashableType { /// TODO of course this is not necessarily hashable, or even classic, /// depending on how it is instantiated... Variable(SmolStr), - /// An arbitrary size integer. - Int(HugrIntWidthStore), + /// A 64-bit unsigned integer. + USize, /// An arbitrary length string. String, /// A container (all of whose elements can be hashed) @@ -218,22 +218,16 @@ impl ClassicType { ClassicType::Graph(Box::new(signature)) } - /// Returns a new integer type with the given number of bits. + /// Returns a new 64-bit size type. #[inline] - pub const fn int() -> Self { - Self::Hashable(HashableType::Int(N)) + pub const fn usize() -> Self { + Self::Hashable(HashableType::USize) } /// Returns a new 64-bit integer type. #[inline] pub const fn i64() -> Self { - Self::int::<64>() - } - - /// Returns a new 1-bit integer type. - #[inline] - pub const fn bit() -> Self { - Self::int::<1>() + Self::usize() } /// New unit type, defined as an empty Tuple. @@ -295,10 +289,7 @@ impl Display for HashableType { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { HashableType::Variable(x) => f.write_str(x), - HashableType::Int(i) => { - f.write_char('I')?; - f.write_str(&i.to_string()) - } + HashableType::USize => f.write_str("USize"), HashableType::String => f.write_str("String"), HashableType::Container(c) => c.fmt(f), } @@ -485,8 +476,8 @@ mod test { /// [CLASSIC_T]: crate::types::custom::test::CLASSIC_T fn graph_type() -> ClassicType { ClassicType::Graph(Box::new(AbstractSignature::new( - vec![HashableType::Int(64).into()], - vec![HashableType::Int(64).into()], + vec![HashableType::USize.into()], + vec![HashableType::USize.into()], vec![], ))) } @@ -509,7 +500,7 @@ mod test { ); let hash = vec![ - SimpleType::Classic(ClassicType::Hashable(HashableType::Int(8))), + SimpleType::Classic(ClassicType::Hashable(HashableType::USize)), SimpleType::Classic(ClassicType::Hashable(HashableType::String)), ]; let ty = SimpleType::new_tuple(hash); @@ -533,7 +524,7 @@ mod test { SimpleType::Classic(ClassicType::Container(Container::Sum(_))) ); - let hash: TypeRow = vec![HashableType::Int(4), HashableType::String].into(); + let hash: TypeRow = vec![HashableType::USize, HashableType::String].into(); let ty = SimpleType::new_sum(hash.map_into()); assert_matches!( ty, diff --git a/src/types/simple/serialize.rs b/src/types/simple/serialize.rs index 470388b43..008fb92c4 100644 --- a/src/types/simple/serialize.rs +++ b/src/types/simple/serialize.rs @@ -17,16 +17,13 @@ use super::SimpleType; use super::super::AbstractSignature; -use crate::ops::constant::HugrIntWidthStore; use crate::types::type_row::TypeRowElem; #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] #[serde(tag = "t")] pub(crate) enum SerSimpleType { Q, - I { - width: HugrIntWidthStore, - }, + I, S, G { signature: Box, @@ -103,7 +100,7 @@ impl From for SerSimpleType { fn from(value: HashableType) -> Self { match value { HashableType::Variable(s) => SerSimpleType::Var { name: s }, - HashableType::Int(w) => SerSimpleType::I { width: w }, + HashableType::USize => SerSimpleType::I, HashableType::String => SerSimpleType::S, HashableType::Container(c) => c.into(), } @@ -156,7 +153,7 @@ impl From for SimpleType { fn from(value: SerSimpleType) -> Self { match value { SerSimpleType::Q => SimpleType::Qubit, - SerSimpleType::I { width } => HashableType::Int(width).into(), + SerSimpleType::I => HashableType::USize.into(), SerSimpleType::S => HashableType::String.into(), SerSimpleType::G { signature } => ClassicType::Graph(Box::new(*signature)).into(), SerSimpleType::Tuple { row: inner, c } => { @@ -213,20 +210,20 @@ mod test { // A Simple tuple let t = SimpleType::new_tuple(vec![ SimpleType::Qubit, - SimpleType::from(HashableType::Int(64)), + SimpleType::from(HashableType::USize), ]); assert_eq!(ser_roundtrip(&t), t); // A Classic sum let t = SimpleType::new_sum(vec![ - SimpleType::Classic(ClassicType::Hashable(HashableType::Int(4))), + SimpleType::Classic(ClassicType::Hashable(HashableType::USize)), SimpleType::Classic(CLASSIC_T), ]); assert_eq!(ser_roundtrip(&t), t); // A Hashable list let t = SimpleType::Classic(ClassicType::Hashable(HashableType::Container( - Container::Array(Box::new(HashableType::Int(8)), 3), + Container::Array(Box::new(HashableType::USize), 3), ))); assert_eq!(ser_roundtrip(&t), t); } @@ -236,7 +233,7 @@ mod test { // This list should be represented as a HashableType::Container. let malformed = SimpleType::Qontainer(Container::Array( Box::new(SimpleType::Classic(ClassicType::Hashable( - HashableType::Int(8), + HashableType::USize, ))), 6, )); diff --git a/src/values.rs b/src/values.rs index e5071c6ea..9113e81b9 100644 --- a/src/values.rs +++ b/src/values.rs @@ -5,12 +5,8 @@ use thiserror::Error; -use crate::ops::constant::{HugrIntWidthStore, HUGR_MAX_INT_WIDTH}; use crate::types::{ClassicType, Container, CustomType, HashableType, PrimType}; -use crate::{ - ops::constant::{ConstValue, HugrIntValueStore}, - types::TypeRow, -}; +use crate::{ops::constant::ConstValue, types::TypeRow}; /// A constant value/instance of a [HashableType]. Note there is no /// equivalent of [HashableType::Variable]; we can't have instances of that. @@ -18,8 +14,8 @@ use crate::{ pub enum HashableValue { /// A string, i.e. corresponding to [HashableType::String] String(String), - /// An integer, i.e. an instance of all [HashableType::Int]s of sufficient width - Int(HugrIntValueStore), + /// A 64-bit integer + Int(u64), /// A container of other hashable values Container(ContainerValue), } @@ -61,9 +57,9 @@ impl ValueOfType for HashableValue { return Ok(()); }; } - HashableValue::Int(value) => { - if let HashableType::Int(width) = ty { - return check_int_fits_in_width(*value, *width).map_err(ConstTypeError::Int); + HashableValue::Int(_) => { + if let HashableType::USize = ty { + return Ok(()); }; } HashableValue::Container(vals) => { @@ -180,55 +176,6 @@ pub(crate) fn map_container_type( } } -use lazy_static::lazy_static; - -use std::collections::HashSet; - -/// An error in fitting an integer constant into its size -#[derive(Clone, Debug, PartialEq, Eq, Error)] -pub enum ConstIntError { - /// The value exceeds the max value of its `I` type - /// E.g. checking 300 against I8 - #[error("Const int {1} too large for type I{0}")] - IntTooLarge(HugrIntWidthStore, HugrIntValueStore), - /// Width (n) of an `I` type doesn't fit into a HugrIntWidthStore - #[error("Int type too large: I{0}")] - IntWidthTooLarge(HugrIntWidthStore), - /// The width of an integer type wasn't a power of 2 - #[error("The int type I{0} is invalid, because {0} is not a power of 2")] - IntWidthInvalid(HugrIntWidthStore), -} - -lazy_static! { - static ref VALID_WIDTHS: HashSet = - HashSet::from_iter((0..8).map(|a| HugrIntWidthStore::pow(2, a))); -} - -/// Per the spec, valid widths for integers are 2^n for all n in [0,7] -fn check_int_fits_in_width( - value: HugrIntValueStore, - width: HugrIntWidthStore, -) -> Result<(), ConstIntError> { - if width > HUGR_MAX_INT_WIDTH { - return Err(ConstIntError::IntWidthTooLarge(width)); - } - - if VALID_WIDTHS.contains(&width) { - let max_value = if width == HUGR_MAX_INT_WIDTH { - HugrIntValueStore::MAX - } else { - HugrIntValueStore::pow(2, width as u32) - 1 - }; - if value <= max_value { - Ok(()) - } else { - Err(ConstIntError::IntTooLarge(width, value)) - } - } else { - Err(ConstIntError::IntWidthInvalid(width)) - } -} - /// Struct for custom type check fails. #[derive(Clone, Debug, PartialEq, Eq, Error)] pub enum CustomCheckFail { @@ -243,9 +190,6 @@ pub enum CustomCheckFail { /// Errors that arise from typechecking constants #[derive(Clone, Debug, PartialEq, Error)] pub enum ConstTypeError { - /// There was some problem fitting a const int into its declared size - #[error("Error with int constant")] - Int(#[from] ConstIntError), /// Found a Var type constructor when we're checking a const val #[error("Type of a const value can't be Var")] ConstCantBeVar, @@ -268,37 +212,4 @@ pub enum ConstTypeError { } #[cfg(test)] -mod test { - - use super::*; - use cool_asserts::assert_matches; - - #[test] - fn test_biggest_int() { - assert_matches!(check_int_fits_in_width(u128::MAX, 128), Ok(_)) - } - - #[test] - fn test_odd_widths_invalid() { - assert_matches!( - check_int_fits_in_width(0, 3), - Err(ConstIntError::IntWidthInvalid(_)) - ); - } - - #[test] - fn test_zero_width_invalid() { - assert_matches!( - check_int_fits_in_width(0, 0), - Err(ConstIntError::IntWidthInvalid(_)) - ); - } - - #[test] - fn test_width_too_large() { - assert_matches!( - check_int_fits_in_width(0, 130), - Err(ConstIntError::IntWidthTooLarge(_)) - ); - } -} +mod test {}