packages feed

clash-prelude 1.10.0 → 1.10.1

raw patch · 35 files changed

+1581/−33 lines, 35 filesdep +checked-literalsdep +processdep +temporarydep −data-binary-ieee754dep ~string-interpolatedep ~timePVP ok

version bump matches the API change (PVP)

Dependencies added: checked-literals, process, temporary

Dependencies removed: data-binary-ieee754

Dependency ranges changed: string-interpolate, time

API changes (from Hackage documentation)

+ Clash.Num.Erroring: instance (GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => Clash.Class.Num.SaturatingNum (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Overflowing: instance (GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => Clash.Class.Num.SaturatingNum (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Saturating: instance (GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => Clash.Class.Num.SaturatingNum (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Wrapping: instance (GHC.Enum.Bounded a, Clash.Class.Num.SaturatingNum a) => Clash.Class.Num.SaturatingNum (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Zeroing: instance (GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => Clash.Class.Num.SaturatingNum (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Num.Zeroing.Zeroing a)
+ Clash.Signal.Delayed.Internal: instance CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Signal.Delayed.Internal.DSignal dom delay a)
+ Clash.Signal.Delayed.Internal: instance CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Signal.Delayed.Internal.DSignal dom delay a)
+ Clash.Signal.Delayed.Internal: instance CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Signal.Delayed.Internal.DSignal dom delay a)
+ Clash.Signal.Delayed.Internal: instance CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Signal.Delayed.Internal.DSignal dom delay a)
+ Clash.Signal.Internal: instance CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Signal.Internal.Signal dom a)
+ Clash.Signal.Internal: instance CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit a => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Signal.Internal.Signal dom a)
+ Clash.Signal.Internal: instance CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Signal.Internal.Signal dom a)
+ Clash.Signal.Internal: instance CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den a => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Signal.Internal.Signal dom a)
+ Clash.Sized.BitVector: type BitPositiveLiteralError lit = OutOfBounds ('ShowType lit) (UnsignedBounds Bit 1)
+ Clash.Sized.BitVector: type BitVectorPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (UnsignedBounds (BitVector n) ((2 ^ n) - 1)) (CLog 2 (lit + 1)) n
+ Clash.Sized.Fixed: instance (Clash.Sized.Fixed.CheckFixedFrac (CheckedLiterals.Class.Rational.TypeNats.IsPowerOfTwo den) ('GHC.TypeError.Text str) den frac (Clash.Sized.Fixed.SFixed int frac), GHC.TypeError.Assert (Clash.Sized.Fixed.FitsNegativeSFixedRational num den int) (Clash.Sized.Fixed.SFixedNegativeRationalLiteralError ('GHC.TypeError.Text str) num den int)) => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Sized.Fixed.SFixed int frac)
+ Clash.Sized.Fixed: instance (Clash.Sized.Fixed.CheckFixedFrac (CheckedLiterals.Class.Rational.TypeNats.IsPowerOfTwo den) ('GHC.TypeError.Text str) den frac (Clash.Sized.Fixed.SFixed int frac), GHC.TypeError.Assert (Clash.Sized.Fixed.FitsPositiveSFixedRational num den int) (Clash.Sized.Fixed.SFixedPositiveRationalLiteralError ('GHC.TypeError.Text str) num den int)) => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Sized.Fixed.SFixed int frac)
+ Clash.Sized.Fixed: instance (GHC.TypeError.Assert (Data.Type.Bool.If (GHC.TypeNats.Div num den Data.Type.Ord.<=? 0) (GHC.TypeNats.Div num den Data.Type.Ord.<=? 0) (GHC.TypeLits.Extra.CLog 2 (GHC.TypeNats.Div num den GHC.TypeNats.+ 1) Data.Type.Ord.<=? int)) (Clash.Sized.Fixed.UFixedPositiveLiteralError ('GHC.TypeError.Text str) (GHC.TypeNats.Div num den) int), Clash.Sized.Fixed.CheckFixedFrac (CheckedLiterals.Class.Rational.TypeNats.IsPowerOfTwo den) ('GHC.TypeError.Text str) den frac (Clash.Sized.Fixed.UFixed int frac)) => CheckedLiterals.Class.Rational.CheckedPositiveRationalLiteral str num den (Clash.Sized.Fixed.UFixed int frac)
+ Clash.Sized.Fixed: instance Clash.Sized.Fixed.UFixedNegativeLiteralError ('GHC.TypeError.Text "-" 'GHC.TypeError.:<>: 'GHC.TypeError.ShowType lit) => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Sized.Fixed.UFixed int frac)
+ Clash.Sized.Fixed: instance Clash.Sized.Fixed.UFixedNegativeLiteralError ('GHC.TypeError.Text str) => CheckedLiterals.Class.Rational.CheckedNegativeRationalLiteral str num den (Clash.Sized.Fixed.UFixed int frac)
+ Clash.Sized.Fixed: instance GHC.TypeError.Assert (Data.Type.Bool.If (lit Data.Type.Ord.<=? 0) (lit Data.Type.Ord.<=? 0) ((GHC.TypeLits.Extra.CLog 2 (lit GHC.TypeNats.+ 1) GHC.TypeNats.+ 1) Data.Type.Ord.<=? int)) (Clash.Sized.Fixed.SFixedPositiveLiteralError ('GHC.TypeError.ShowType lit) lit int) => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Sized.Fixed.SFixed int frac)
+ Clash.Sized.Fixed: instance GHC.TypeError.Assert (Data.Type.Bool.If (lit Data.Type.Ord.<=? 0) (lit Data.Type.Ord.<=? 0) ((GHC.TypeLits.Extra.CLog 2 lit GHC.TypeNats.+ 1) Data.Type.Ord.<=? int)) (Clash.Sized.Fixed.SFixedNegativeLiteralError ('GHC.TypeError.Text "-" 'GHC.TypeError.:<>: 'GHC.TypeError.ShowType lit) lit int) => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Sized.Fixed.SFixed int frac)
+ Clash.Sized.Fixed: instance GHC.TypeError.Assert (Data.Type.Bool.If (lit Data.Type.Ord.<=? 0) (lit Data.Type.Ord.<=? 0) (GHC.TypeLits.Extra.CLog 2 (lit GHC.TypeNats.+ 1) Data.Type.Ord.<=? int)) (Clash.Sized.Fixed.UFixedPositiveLiteralError ('GHC.TypeError.ShowType lit) lit int) => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Sized.Fixed.UFixed int frac)
+ Clash.Sized.Fixed: type FixedPointNotEnoughFracError strLit den frac typ = NotExactlyRepresentableWithConstraint strLit typ (FractionalBitsNote (CLog 2 den)) (CLog 2 den) frac
+ Clash.Sized.Fixed: type FixedPointNotPow2Error strLit den typ = NotExactlyRepresentable strLit typ ('Text "The reduced denominator " ':<>: 'ShowType den ':<>: 'Text " is not a power of 2.")
+ Clash.Sized.Fixed: type SFixedNegativeLiteralError strLit lit int = PotentiallyOutOfBounds strLit (SignedIntegerBitsNote (CLog 2 lit + 1)) (CLog 2 lit + 1) int
+ Clash.Sized.Fixed: type SFixedNegativeRationalLiteralError strLit num den int = PotentiallyOutOfBounds strLit (SignedIntegerBitsNote (SFixedNegativeRationalRequiredIntBits num den)) (SFixedNegativeRationalRequiredIntBits num den) int
+ Clash.Sized.Fixed: type SFixedNegativeRationalRequiredIntBits (num :: Nat) (den :: Nat) = CLog 2 num + 1 - CLog 2 den
+ Clash.Sized.Fixed: type SFixedPositiveLiteralError strLit lit int = PotentiallyOutOfBounds strLit (SignedIntegerBitsNote (CLog 2 (lit + 1) + 1)) (CLog 2 (lit + 1) + 1) int
+ Clash.Sized.Fixed: type SFixedPositiveRationalLiteralError strLit num den int = PotentiallyOutOfBounds strLit (SignedIntegerBitsNote (SFixedPositiveRationalRequiredIntBits num den)) (SFixedPositiveRationalRequiredIntBits num den) int
+ Clash.Sized.Fixed: type SFixedPositiveRationalRequiredIntBits (num :: Nat) (den :: Nat) = CLog 2 (num + 1) + 1 - CLog 2 den
+ Clash.Sized.Fixed: type UFixedNegativeLiteralError strLit = OutOfBoundsBecause strLit ('Text "UFixed cannot represent negative numbers.")
+ Clash.Sized.Fixed: type UFixedPositiveLiteralError strLit lit int = PotentiallyOutOfBounds strLit (IntegerBitsNote (CLog 2 (lit + 1))) (CLog 2 (lit + 1)) int
+ Clash.Sized.Fixed: type family CheckFixedFrac (isPow2 :: Bool) (strLit :: ErrorMessage) (den :: Nat) (frac :: Nat) (typ :: Type) :: Constraint
+ Clash.Sized.Index: type IndexPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (UnsignedBounds (Index n) (n - 1)) (lit + 1) n
+ Clash.Sized.Internal.BitVector: instance CheckedLiterals.Class.Integer.NegativeUnsignedError lit (Clash.Sized.Internal.BitVector.BitVector n) ((2 GHC.TypeNats.^ n) GHC.TypeNats.- 1) => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Sized.Internal.BitVector.BitVector n)
+ Clash.Sized.Internal.BitVector: instance CheckedLiterals.Class.Integer.NegativeUnsignedError lit Clash.Sized.Internal.BitVector.Bit 1 => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit Clash.Sized.Internal.BitVector.Bit
+ Clash.Sized.Internal.BitVector: instance GHC.TypeError.Assert (Data.Type.Bool.If (lit Data.Type.Ord.<=? 0) (lit Data.Type.Ord.<=? 0) (GHC.TypeLits.Extra.CLog 2 (lit GHC.TypeNats.+ 1) Data.Type.Ord.<=? n)) (Clash.Sized.Internal.BitVector.BitVectorPositiveLiteralError lit n) => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Sized.Internal.BitVector.BitVector n)
+ Clash.Sized.Internal.BitVector: instance GHC.TypeError.Assert (lit Data.Type.Ord.<=? 1) (Clash.Sized.Internal.BitVector.BitPositiveLiteralError lit) => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit Clash.Sized.Internal.BitVector.Bit
+ Clash.Sized.Internal.BitVector: type BitPositiveLiteralError lit = OutOfBounds ('ShowType lit) (UnsignedBounds Bit 1)
+ Clash.Sized.Internal.BitVector: type BitVectorPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (UnsignedBounds (BitVector n) ((2 ^ n) - 1)) (CLog 2 (lit + 1)) n
+ Clash.Sized.Internal.CheckedLiterals: type AddConstraintFix required actual = 'Text "Possible fix: add a constraint: " ':<>: 'ShowType required ':<>: 'Text " <= " ':<>: 'ShowType actual ':<>: 'Text "."
+ Clash.Sized.Internal.CheckedLiterals: type CheckedLiteralUncheckedFix = 'Text "Possible fix: use 'uncheckedLiteral' from 'CheckedLiterals' to bypass this check."
+ Clash.Sized.Internal.CheckedLiterals: type FractionalBitsNote bits = 'Text "The fractional part needs at least " ':<>: 'ShowType bits ':<>: 'Text " bit(s)."
+ Clash.Sized.Internal.CheckedLiterals: type IntegerBitsNote bits = 'Text "Note: integer part needs at least " ':<>: 'ShowType bits ':<>: 'Text " bit(s)."
+ Clash.Sized.Internal.CheckedLiterals: type NotExactlyRepresentable strLit (typ :: Type) reason = TypeError ('Text "Literal " ':<>: strLit ':<>: 'Text " cannot be represented exactly by " ':<>: 'ShowType typ ':<>: 'Text "." ':$$: reason ':$$: CheckedLiteralUncheckedFix)
+ Clash.Sized.Internal.CheckedLiterals: type NotExactlyRepresentableWithConstraint strLit (typ :: Type) reason required actual = TypeError ('Text "Literal " ':<>: strLit ':<>: 'Text " cannot be represented exactly by " ':<>: 'ShowType typ ':<>: 'Text "." ':$$: reason ':$$: AddConstraintFix required actual ':$$: CheckedLiteralUncheckedFix)
+ Clash.Sized.Internal.CheckedLiterals: type OutOfBounds strLit details = TypeError ('Text "Literal " ':<>: strLit ':<>: 'Text " is out of bounds." ':$$: details ':$$: CheckedLiteralUncheckedFix)
+ Clash.Sized.Internal.CheckedLiterals: type OutOfBoundsBecause strLit reason = TypeError ('Text "Literal " ':<>: strLit ':<>: 'Text " is out of bounds, because " ':<>: reason ':$$: CheckedLiteralUncheckedFix)
+ Clash.Sized.Internal.CheckedLiterals: type PotentiallyOutOfBounds strLit details required actual = TypeError ('Text "Literal " ':<>: strLit ':<>: 'Text " is (potentially) out of bounds." ':$$: details ':$$: AddConstraintFix required actual ':$$: CheckedLiteralUncheckedFix)
+ Clash.Sized.Internal.CheckedLiterals: type SignedBounds (typ :: Type) minVal maxVal = 'ShowType typ ':<>: 'Text " has bounds: [-" ':<>: 'ShowType minVal ':<>: 'Text " .. " ':<>: 'ShowType maxVal ':<>: 'Text "]."
+ Clash.Sized.Internal.CheckedLiterals: type SignedIntegerBitsNote bits = 'Text "Note: integer part needs at least " ':<>: 'ShowType bits ':<>: 'Text " bit(s), including sign bit."
+ Clash.Sized.Internal.CheckedLiterals: type UnsignedBounds (typ :: Type) maxVal = 'ShowType typ ':<>: 'Text " has bounds: [0 .. " ':<>: 'ShowType maxVal ':<>: 'Text "]."
+ Clash.Sized.Internal.Index: instance CheckedLiterals.Class.Integer.NegativeUnsignedError lit (Clash.Sized.Internal.Index.Index n) (n GHC.TypeNats.- 1) => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Internal.Index: instance GHC.TypeError.Assert ((lit GHC.TypeNats.+ 1) Data.Type.Ord.<=? n) (Clash.Sized.Internal.Index.IndexPositiveLiteralError lit n) => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Internal.Index: type IndexPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (UnsignedBounds (Index n) (n - 1)) (lit + 1) n
+ Clash.Sized.Internal.Signed: instance GHC.TypeError.Assert (Data.Type.Bool.If (lit Data.Type.Ord.<=? 0) (lit Data.Type.Ord.<=? 0) ((GHC.TypeLits.Extra.CLog 2 (lit GHC.TypeNats.+ 1) GHC.TypeNats.+ 1) Data.Type.Ord.<=? n)) (Clash.Sized.Internal.Signed.SignedPositiveLiteralError lit n) => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Sized.Internal.Signed.Signed n)
+ Clash.Sized.Internal.Signed: instance GHC.TypeError.Assert (Data.Type.Bool.If (lit Data.Type.Ord.<=? 0) (lit Data.Type.Ord.<=? 0) ((GHC.TypeLits.Extra.CLog 2 lit GHC.TypeNats.+ 1) Data.Type.Ord.<=? n)) (Clash.Sized.Internal.Signed.SignedNegativeLiteralError lit n) => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Sized.Internal.Signed.Signed n)
+ Clash.Sized.Internal.Signed: type SignedNegativeLiteralError lit n = PotentiallyOutOfBounds ('Text "-" ':<>: 'ShowType lit) (SignedBounds (Signed n) (2 ^ (n - 1)) ((2 ^ (n - 1)) - 1)) (CLog 2 lit + 1) n
+ Clash.Sized.Internal.Signed: type SignedPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (SignedBounds (Signed n) (2 ^ (n - 1)) ((2 ^ (n - 1)) - 1)) (CLog 2 (lit + 1) + 1) n
+ Clash.Sized.Internal.Unsigned: instance CheckedLiterals.Class.Integer.NegativeUnsignedError lit (Clash.Sized.Internal.Unsigned.Unsigned n) ((2 GHC.TypeNats.^ n) GHC.TypeNats.- 1) => CheckedLiterals.Class.Integer.CheckedNegativeIntegerLiteral lit (Clash.Sized.Internal.Unsigned.Unsigned n)
+ Clash.Sized.Internal.Unsigned: instance GHC.TypeError.Assert (Data.Type.Bool.If (lit Data.Type.Ord.<=? 0) (lit Data.Type.Ord.<=? 0) (GHC.TypeLits.Extra.CLog 2 (lit GHC.TypeNats.+ 1) Data.Type.Ord.<=? n)) (Clash.Sized.Internal.Unsigned.UnsignedPositiveLiteralError lit n) => CheckedLiterals.Class.Integer.CheckedPositiveIntegerLiteral lit (Clash.Sized.Internal.Unsigned.Unsigned n)
+ Clash.Sized.Internal.Unsigned: type UnsignedPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (UnsignedBounds (Unsigned n) ((2 ^ n) - 1)) (CLog 2 (lit + 1)) n
+ Clash.Sized.Signed: type SignedNegativeLiteralError lit n = PotentiallyOutOfBounds ('Text "-" ':<>: 'ShowType lit) (SignedBounds (Signed n) (2 ^ (n - 1)) ((2 ^ (n - 1)) - 1)) (CLog 2 lit + 1) n
+ Clash.Sized.Signed: type SignedPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (SignedBounds (Signed n) (2 ^ (n - 1)) ((2 ^ (n - 1)) - 1)) (CLog 2 (lit + 1) + 1) n
+ Clash.Sized.Unsigned: type UnsignedPositiveLiteralError lit n = PotentiallyOutOfBounds ('ShowType lit) (UnsignedBounds (Unsigned n) ((2 ^ n) - 1)) (CLog 2 (lit + 1)) n

Files

CHANGELOG.md view
@@ -1,5 +1,72 @@ # Changelog for the Clash project +## 1.10.1 *Aug 27th, 2026*++Highlights:+ * Very significant performance improvements, further detailed below. We also created a site https://clash-lang.github.io/clash-benchmarks/ where we track performance improvements. These graphs are for the current `master` branch, not for released Clash versions.+ * We have added support for the `checked-literals` package. Numeric literals (e.g., `5` or `3.2`) can now be checked at compile time. That is, you'll get a compile error if the literal does not fit the target type -- even in polymorphic contexts! You can enable the checker by adding the following to your project's Cabal file:++    ```+    library+      [..]++      build-depends:+        [..]+        checked-literals++      ghc-options: -fplugin=CheckedLiterals+    ```++    See https://clash-lang.org/blog/2026-04-07-checked-literals/.++Performance:+* `clash` and `clashi` now use GHC-style RTS defaults through executable `-with-rtsopts` flags instead of linking RTS hooks. The existing unused hooks have been removed. **Existing users should set `-with-rtsopts` to `-K512M -H -I5 -T` if they use their own Clash executable. These flags has been shown to give a ~25% compilation speed up in larger designs.** If you used a Clash starter project to initialize your design, you should change:++    ```haskell+    executable clash+      [..]+    ```++    To:++    ```haskell+    executable clash+      [..]+      ghc-options: "-with-rtsopts=-K512M -H -I5 -T"+    ```++    in the cabal file. See [#3252](https://github.com/clash-lang/clash-compiler/issues/3252).+* Improved normalization performance for repeated top-down rewrite loops by avoiding full root restarts after every successful rewrite. This gives a ~17% performance improvements on larger designs [#3249](https://github.com/clash-lang/clash-compiler/issues/3249).+* Clash now converts GHC Core to its own Clash Core in parallel. For larger projects, this can shave off ~40% of load times. See [#3299](https://github.com/clash-lang/clash-compiler/issues/3299).+* Clash now prunes the binders it collects from top modules when loading from precompiled core. For larger projects, this can shave off 15% of package loading times. See [#3298](https://github.com/clash-lang/clash-compiler/issues/3298).+* `flattenCallTree` now caches intermediate results, reducing Clash normalization by 10% for realistic designs. Fixes #[3246](https://github.com/clash-lang/clash-compiler/issues/3246).++Added:+* `-fclash-debug-manifest-hash`. When enabled, Clash emits a `__debug_hash` object in `clash-manifest.json` listing the SHA256 of each input that feeds into the top-level `hash` (`tops`, `prim_map`, `clash_mod_date`, `call_graph`, `opts`). As the name implies, this should only be used to debug and should not be relied upon by tooling. See [#3280](https://github.com/clash-lang/clash-compiler/pull/3280).+* `SaturatingNum` instances for `Erroring`, `Overflowing`, `Saturating`, `Wrapping`, and `Zeroing`.++Changed:+* Replaced the deprecated `data-binary-ieee754` dependency with `castDoubleToWord64`, `castFloatToWord32`, `castWord32ToFloat`, and `castWord64ToDouble` from `GHC.Float`. See [#3174](https://github.com/clash-lang/clash-compiler/issues/3174).+* `flake.nix` now advertises the [clash-lang Cachix binary cache](https://clash-lang.cachix.org) via `nixConfig.extra-substituters`. Running `nix develop` will prompt you to trust the cache, avoiding having to build Clash from source. See [#3213](https://github.com/clash-lang/clash-compiler/issues/3213).++Fixed:+* Clash no longer crashes for self-recursive global binders in very specific circumstances. See [#3311](https://github.com/clash-lang/clash-compiler/issues/3311).+* Clash no longer crashes upon calling `sequenceA`/`traverse#` on a zero-sized `Vec`. See [#3290](https://github.com/clash-lang/clash-compiler/issues/3290).+* Clash no longer crashes when constant-folding partial primitives in the GHC evaluator. This covers `shiftL`/`shiftR`/`rotateL`/`rotateR` with negative shift amounts on `BitVector`/`Signed`/`Unsigned`, `(^)` with negative exponents, `chr` on out-of-range integers, and `quot`/`rem`/`div`/`mod` by zero on `Int`/`Word`/`Int{8,16,32,64}`/`Word{8,16,32,64}`. Such expressions now fold to `undefined` (rather than crashing the compiler). Fixes [#3234](https://github.com/clash-lang/clash-compiler/issues/3234).+* Clash no longer crashes with `mkVecNil: failed to instantiate Nil DC` when unfolding `traverse#` in very specific circumstances. See [#3291](https://github.com/clash-lang/clash-compiler/issues/3291).+* Clash no longer errors when two `-i` import paths refer to the same directory via different syntactic spellings (e.g. `-isrc -isrc/.`) and a data file lives in that directory. See [#3142](https://github.com/clash-lang/clash-compiler/issues/3142).+* Clash no longer produces an error when using `dataToTag` in combination with custom bit representations. See [#2724](https://github.com/clash-lang/clash-compiler/issues/2724).+* Clash no longer takes exponential time and memory normalizing `foldl`/`scanl`/`splitAt` over a vector when the result keeps the (co-recursively defined) vector spine alive, e.g. `snd (foldl const (z, s) (xs :: Vec n a))`. The evaluator's `zipWith` and `splitAt` reductions now share their arguments instead of duplicating the vector spine on every peel. See [#3308](https://github.com/clash-lang/clash-compiler/issues/3308).+* Clash now recognizes `~` when solving GADT arms. Fixes [#3232](https://github.com/clash-lang/clash-compiler/issues/3232).+* Clash will no longer generate duplicate `attribute` when they're both used for top entity ports and internal signals. See [#3218](https://github.com/clash-lang/clash-compiler/issues/3218). The VHDL backend now also reports a clearer error when a synthesis attribute is declared with conflicting types in the same design.+* Due to HDL standards, when the result of a top entity is read by another binder Clash is forced to introduce an internal indirection signal. Clash no longer attaches the top entity's `Annotate` synthesis attributes to that internal signal, preventing duplicate synthesis attributes in the generated HDL. See [#3224](https://github.com/clash-lang/clash-compiler/issues/3224).+* Errors in `Synthesize` port annotations (e.g. a `PortProduct` on a non-product port) are now reported before a design is normalized, instead of afterwards. This avoids waiting for a potentially long normalization only to get a trivial port error. See [#3305](https://github.com/clash-lang/clash-compiler/issues/3305).+* Run `bindConstantVar` after post-normalization `inlineCleanup`/`caseCon` so constant let-bindings exposed late are inlined before netlist generation [#3041](https://github.com/clash-lang/clash-compiler/issues/3041).+* The VHDL primitives for `integerToNaturalThrow` and `integerToNaturalClamp` no longer contain syntax errors. See [#3315](https://github.com/clash-lang/clash-compiler/pull/3315).+* The internal function `Clash.Util.Interpolate.i` in `clash-lib` no longer inserts an extra blank line after a paragraph that gets reflowed onto multiple lines. See [#2753](https://github.com/clash-lang/clash-compiler/issues/2753).+* `deriveAutoReg` no longer fails on GHC versions where `KnownNat` lives in `GHC.Internal.TypeNats` rather than `GHC.TypeNats`. See [#3100](https://github.com/clash-lang/clash-compiler/issues/3100).+* `makeTopEntity` now accounts for unary product types. See [#3066](https://github.com/clash-lang/clash-compiler/issues/3066).+ ## 1.10.0 *Apr 23rd, 2026*  Release highlight:
clash-prelude.cabal view
@@ -1,6 +1,6 @@ Cabal-version:        2.2 Name:                 clash-prelude-Version:              1.10.0+Version:              1.10.1 Synopsis:             Clash: a functional hardware description language - Prelude library Description:   Clash is a functional hardware description language that borrows both its@@ -277,6 +277,7 @@                       Clash.Sized.Vector.ToTuple.TH                        Clash.Sized.Internal.BitVector+                      Clash.Sized.Internal.CheckedLiterals                       Clash.Sized.Internal.Index                       Clash.Sized.Internal.Mod                       Clash.Sized.Internal.Signed@@ -328,7 +329,6 @@                       bytestring                >= 0.10.8  && < 0.13,                       constraints               >= 0.9     && < 1.0,                       containers                >= 0.4.0   && < 0.9,-                      data-binary-ieee754       >= 0.4.4   && < 0.6,                       data-default              >= 0.7     && < 0.9,                       deepseq                   >= 1.4.1.0 && < 1.6,                       distributive              >= 0.1     && < 1.0,@@ -342,18 +342,19 @@                       half                      >= 0.2.2.3 && < 1.0,                       infinite-list           ^>= 0.1,                       lens                      >= 4.10    && < 5.4,-                      QuickCheck                >= 2.7     && < 2.16,+                      QuickCheck                >= 2.7     && < 2.19,                       recursion-schemes         >= 5.1     && < 5.3,                       reflection                >= 2       && < 2.2,+                      checked-literals          >= 0.1.1   && < 0.2,                       singletons                >= 2.0     && < 3.1,-                      string-interpolate        ^>= 0.3,+                      string-interpolate        >= 0.3     && < 1.1,                       tagged                    >= 0.8     && < 0.9,                       template-haskell          >= 2.20.0.0 && < 2.24,                       th-abstraction            >= 0.3.0 && < 0.8.0,                       th-lift                   >= 0.7.0    && < 0.9,                       th-orphans                >= 0.13.1   && < 1.0,                       text                      >= 0.11.3.1 && < 2.2,-                      time                      >= 1.8     && < 1.15,+                      time                      >= 1.8     && < 1.17,                       transformers              >= 0.5.2.0 && < 0.7,                       type-errors               >= 0.2.0.0 && < 0.3,                       uniplate                  >= 1.6.12  && < 1.7,@@ -402,6 +403,7 @@   else     build-depends:       clash-prelude,+      checked-literals,        ghc-typelits-knownnat,       ghc-typelits-natnormalise,@@ -412,16 +414,19 @@       bytestring,       containers,       deepseq,-      hedgehog      >= 1.0.3    && < 1.6,+      hedgehog      >= 1.0.3    && < 1.8,       hint          >= 0.7      && < 0.10,       mmorph        >= 1.1.5    && < 1.3,+      process,       quickcheck-classes-base >= 0.6 && < 1.0,+      string-interpolate >=0.3.4.0,       tasty         >= 1.2      && < 1.6,       tasty-hedgehog >= 1.2.0,       tasty-hunit,       tasty-th,       tasty-quickcheck,       template-haskell,+      temporary,       text    Other-Modules:@@ -431,6 +436,15 @@                  Clash.Tests.BitVector                  Clash.Tests.BlockRam                  Clash.Tests.BlockRam.Blob+                 Clash.Tests.CheckedLiterals+                 Clash.Tests.CheckedLiterals.BitVector+                 Clash.Tests.CheckedLiterals.Common+                 Clash.Tests.CheckedLiterals.Fixed+                 Clash.Tests.CheckedLiterals.Index+                 Clash.Tests.CheckedLiterals.Signals+                 Clash.Tests.CheckedLiterals.Signed+                 Clash.Tests.CheckedLiterals.Unsigned+                 Clash.Tests.CheckedLiterals.Wrappers                  Clash.Tests.Clocks                  Clash.Tests.Counter                  Clash.Tests.DumpVCD@@ -461,6 +475,7 @@                   Hedgehog.Extra +                 Test.Tasty.AssertGhc                  Test.Tasty.HUnit.Extra                  Test.Tasty.Hedgehog.Extra                  Test.QuickCheck.Extra
src/Clash/Annotations/TH.hs view
@@ -255,6 +255,7 @@   = c >>= \case     Complete []  -> return $ Complete [PortName name]     Complete [PortName n2] -> return $ Complete [PortName (name ++ "_" ++ n2)]+    Complete [PortProduct "" ys] -> return $ Complete [PortProduct name ys]     Complete xs  -> return $ Complete [PortProduct name xs]     x            -> return x 
src/Clash/Class/AutoReg/Internal.hs view
@@ -341,7 +341,7 @@  constraintsWantedFor :: Name -> [Type] -> Q Cxt constraintsWantedFor clsNm tys-  | show clsNm == "GHC.TypeNats.KnownNat" = do+  | clsNm == ''KnownNat = do   -- KnownNat is special, you can't just lookup instances with reifyInstances.   -- So we just pass KnownNat constraints.   -- This will most likely require UndecidableInstances.
src/Clash/Class/BitPack/Internal.hs view
@@ -27,8 +27,8 @@  import Prelude                        hiding (map) -import Data.Binary.IEEE754            (doubleToWord, floatToWord, wordToDouble,-                                       wordToFloat)+import GHC.Float                      (castDoubleToWord64, castFloatToWord32,+                                       castWord32ToFloat, castWord64ToDouble)  import Data.Char                      (chr, ord) import Data.Complex                   (Complex)@@ -398,12 +398,12 @@   unpack = checkUnpackUndef unpackFloat#  packFloat# :: Float -> BitVector 32-packFloat# = fromIntegral . floatToWord+packFloat# = fromIntegral . castFloatToWord32 {-# OPAQUE packFloat# #-} {-# ANN packFloat# hasBlackBox #-}  unpackFloat# :: BitVector 32 -> Float-unpackFloat# (unsafeToNatural -> w) = wordToFloat (fromIntegral w)+unpackFloat# (unsafeToNatural -> w) = castWord32ToFloat (fromIntegral w) {-# OPAQUE unpackFloat# #-} {-# ANN unpackFloat# hasBlackBox #-} @@ -413,12 +413,12 @@   unpack = checkUnpackUndef unpackDouble#  packDouble# :: Double -> BitVector 64-packDouble# = fromIntegral . doubleToWord+packDouble# = fromIntegral . castDoubleToWord64 {-# OPAQUE packDouble# #-} {-# ANN packDouble# hasBlackBox #-}  unpackDouble# :: BitVector 64 -> Double-unpackDouble# (unsafeToNatural -> w) = wordToDouble (fromIntegral w)+unpackDouble# (unsafeToNatural -> w) = castWord64ToDouble (fromIntegral w) {-# OPAQUE unpackDouble# #-} {-# ANN unpackDouble# hasBlackBox #-} 
src/Clash/Num/Erroring.hs view
@@ -1,11 +1,12 @@-{--Copyright   : (C) 2021, QBayLogic B.V.+{-|+Copyright   : (C) 2021-2026, QBayLogic B.V. License     : BSD2 (see the file LICENSE) Maintainer  : QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}  module Clash.Num.Erroring   ( Erroring@@ -20,6 +21,14 @@ import Data.Functor.Compose (Compose(..)) import Data.Hashable (Hashable) import GHC.TypeLits (KnownNat, type (+))+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  ) import Test.QuickCheck (Arbitrary)  import Clash.Class.BitPack (BitPack)@@ -57,6 +66,22 @@ toErroring :: (SaturatingNum a) => a -> Erroring a toErroring = Erroring +instance+  (CheckedPositiveIntegerLiteral lit a) =>+  CheckedPositiveIntegerLiteral lit (Erroring a)++instance+  (CheckedNegativeIntegerLiteral lit a) =>+  CheckedNegativeIntegerLiteral lit (Erroring a)++instance+  (CheckedPositiveRationalLiteral str num den a) =>+  CheckedPositiveRationalLiteral str num den (Erroring a)++instance+  (CheckedNegativeRationalLiteral str num den a) =>+  CheckedNegativeRationalLiteral str num den (Erroring a)+ instance (Resize f) => Resize (Compose Erroring f) where   {-# INLINE resize #-}   resize@@ -110,6 +135,22 @@   -- is not in range (typically wrapping). It would be better if this also   -- threw an XException, but in a way which remained synthesizable.   fromInteger = coerce (fromInteger @a)++instance (Ord a, SaturatingNum a) => SaturatingNum (Erroring a) where+  {-# INLINE satAdd #-}+  satAdd mode (Erroring a) (Erroring b) = Erroring $ satAdd mode a b++  {-# INLINE satSub #-}+  satSub mode (Erroring a) (Erroring b) = Erroring $ satSub mode a b++  {-# INLINE satMul #-}+  satMul mode (Erroring a) (Erroring b) = Erroring $ satMul mode a b++  {-# INLINE satSucc #-}+  satSucc mode (Erroring a) = Erroring $ satSucc mode a++  {-# INLINE satPred #-}+  satPred mode (Erroring a) = Erroring $ satPred mode a  instance (Enum a, SaturatingNum a) => Enum (Erroring a) where   {-# INLINE succ #-}
src/Clash/Num/Overflowing.hs view
@@ -1,11 +1,13 @@ {-|-Copyright  :  (C) 2021-2022, QBayLogic B.V.+Copyright  :  (C) 2021-2026, QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} @@ -25,6 +27,14 @@ import Data.Hashable (Hashable) import GHC.Generics (Generic) import GHC.TypeLits (KnownNat, type (+))+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  )  import Clash.Class.BitPack (BitPack(..)) import Clash.Class.Num (SaturationMode(SatWrap, SatZero), SaturatingNum(..))@@ -55,6 +65,22 @@ clearOverflow :: Overflowing a -> Overflowing a clearOverflow x = x { hasOverflowed = False } +instance+  (CheckedPositiveIntegerLiteral lit a) =>+  CheckedPositiveIntegerLiteral lit (Overflowing a)++instance+  (CheckedNegativeIntegerLiteral lit a) =>+  CheckedNegativeIntegerLiteral lit (Overflowing a)++instance+  (CheckedPositiveRationalLiteral str num den a) =>+  CheckedPositiveRationalLiteral str num den (Overflowing a)++instance+  (CheckedNegativeRationalLiteral str num den a) =>+  CheckedNegativeRationalLiteral str num den (Overflowing a)+ instance (Eq a) => Eq (Overflowing a) where   {-# INLINE (==) #-}   (==) = (==) `on` fromOverflowing@@ -138,6 +164,75 @@ instance (Bounded a) => Bounded (Overflowing a) where   minBound = Overflowing minBound False   maxBound = Overflowing maxBound False++-- | NOTE: Usage of this instance might introduce redundant circuitry+-- for the overflow check (depending on the utilized 'SaturationMode'+-- or inner type), which is not guaranteed to be optimized away at a+-- later synthesis stage.+--+-- The 'hasOverflowed' flag still will be set even when the 'SaturatingNum'+-- operation has prevented the overflow:+-- @hasOverflowed (satSucc SatBound maxBound) == True@+instance (Ord a, SaturatingNum a) => SaturatingNum (Overflowing a) where+  {-# INLINE satAdd #-}+  satAdd mode (Overflowing x a) (Overflowing y b)+    | y > 0+    , x > satSub SatWrap maxBound y+    = withOverflow True++    | y < 0+    , x < satSub SatWrap minBound y+    = withOverflow True++    | otherwise+    = withOverflow (a || b)+   where+    withOverflow =+      let r = satAdd mode x y+       in seq r $ Overflowing r++  {-# INLINE satSub #-}+  satSub mode (Overflowing x a) (Overflowing y b)+    | y < 0+    , x > satAdd SatWrap maxBound y+    = withOverflow True++    | y > 0+    , x < satAdd SatWrap minBound y+    = withOverflow True++    | otherwise+    = withOverflow (a || b)+   where+    withOverflow =+      let r = satSub mode x y+       in seq r $ Overflowing r++  {-# INLINE satMul #-}+  satMul mode (Overflowing x a) (Overflowing y b)+    | x /= 0+    , y /= 0+    , satMul SatZero x y == 0+    = withOverflow True++    | otherwise+    = withOverflow (a || b)+   where+    withOverflow =+      let r = satMul mode x y+       in seq r $ Overflowing r++  {-# INLINE satSucc #-}+  satSucc mode (Overflowing x a) =+    let xSucc = satSucc mode x+     in seq xSucc+      $ Overflowing xSucc (a || x == maxBound)++  {-# INLINE satPred #-}+  satPred mode (Overflowing x a) =+    let xPred = satPred mode x+     in seq xPred+      $ Overflowing (satPred mode x) (a || x == minBound)  instance (Enum a, Eq a, SaturatingNum a) => Enum (Overflowing a) where   succ (Overflowing x a)
src/Clash/Num/Saturating.hs view
@@ -1,11 +1,12 @@-{--Copyright   : (C) 2021, QBayLogic B.V.+{-|+Copyright   : (C) 2021-2026, QBayLogic B.V. License     : BSD2 (see the file LICENSE) Maintainer  : QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}  module Clash.Num.Saturating   ( Saturating@@ -20,6 +21,14 @@ import Data.Functor.Compose (Compose(..)) import Data.Hashable (Hashable) import GHC.TypeLits (KnownNat, type (+))+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  ) import Test.QuickCheck (Arbitrary)  import Clash.Class.BitPack (BitPack)@@ -57,6 +66,22 @@ toSaturating :: (SaturatingNum a) => a -> Saturating a toSaturating = Saturating +instance+  (CheckedPositiveIntegerLiteral lit a) =>+  CheckedPositiveIntegerLiteral lit (Saturating a)++instance+  (CheckedNegativeIntegerLiteral lit a) =>+  CheckedNegativeIntegerLiteral lit (Saturating a)++instance+  (CheckedPositiveRationalLiteral str num den a) =>+  CheckedPositiveRationalLiteral str num den (Saturating a)++instance+  (CheckedNegativeRationalLiteral str num den a) =>+  CheckedNegativeRationalLiteral str num den (Saturating a)+ instance (Resize f) => Resize (Compose Saturating f) where   {-# INLINE resize #-}   resize@@ -109,6 +134,22 @@   -- is not in range (typically wrapping). It would be better if this also   -- saturated, but in a way which remained synthesizable.   fromInteger = coerce (fromInteger @a)++instance (Ord a, SaturatingNum a) => SaturatingNum (Saturating a) where+  {-# INLINE satAdd #-}+  satAdd mode (Saturating a) (Saturating b) = Saturating $ satAdd mode a b++  {-# INLINE satSub #-}+  satSub mode (Saturating a) (Saturating b) = Saturating $ satSub mode a b++  {-# INLINE satMul #-}+  satMul mode (Saturating a) (Saturating b) = Saturating $ satMul mode a b++  {-# INLINE satSucc #-}+  satSucc mode (Saturating a) = Saturating $ satSucc mode a++  {-# INLINE satPred #-}+  satPred mode (Saturating a) = Saturating $ satPred mode a  instance (Enum a, SaturatingNum a) => Enum (Saturating a) where   {-# INLINE succ #-}
src/Clash/Num/Wrapping.hs view
@@ -6,6 +6,7 @@  {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}  module Clash.Num.Wrapping   ( Wrapping(..)@@ -19,6 +20,14 @@ import Data.Functor.Compose (Compose(..)) import Data.Hashable (Hashable) import GHC.TypeLits (KnownNat, type (+))+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  ) import Test.QuickCheck (Arbitrary)  import Clash.Class.BitPack (BitPack)@@ -56,6 +65,22 @@ toWrapping :: (SaturatingNum a) => a -> Wrapping a toWrapping = Wrapping +instance+  (CheckedPositiveIntegerLiteral lit a) =>+  CheckedPositiveIntegerLiteral lit (Wrapping a)++instance+  (CheckedNegativeIntegerLiteral lit a) =>+  CheckedNegativeIntegerLiteral lit (Wrapping a)++instance+  (CheckedPositiveRationalLiteral str num den a) =>+  CheckedPositiveRationalLiteral str num den (Wrapping a)++instance+  (CheckedNegativeRationalLiteral str num den a) =>+  CheckedNegativeRationalLiteral str num den (Wrapping a)+ instance (Resize f) => Resize (Compose Wrapping f) where   {-# INLINE resize #-}   resize@@ -107,6 +132,22 @@   -- is not in range (typically wrapping). It would be better if this also   -- definitely wrapped, but in a way which remained synthesizable.   fromInteger = coerce (fromInteger @a)++instance (Bounded a, SaturatingNum a) => SaturatingNum (Wrapping a) where+  {-# INLINE satAdd #-}+  satAdd mode (Wrapping a) (Wrapping b) = Wrapping $ satAdd mode a b++  {-# INLINE satSub #-}+  satSub mode (Wrapping a) (Wrapping b) = Wrapping $ satSub mode a b++  {-# INLINE satMul #-}+  satMul mode (Wrapping a) (Wrapping b) = Wrapping $ satMul mode a b++  {-# INLINE satSucc #-}+  satSucc mode (Wrapping a) = Wrapping $ satSucc mode a++  {-# INLINE satPred #-}+  satPred mode (Wrapping a) = Wrapping $ satPred mode a  instance (Enum a, SaturatingNum a) => Enum (Wrapping a) where   {-# INLINE succ #-}
src/Clash/Num/Zeroing.hs view
@@ -1,11 +1,12 @@-{--Copyright   : (C) 2021, QBayLogic B.V.+{-|+Copyright   : (C) 2021-2026, QBayLogic B.V. License     : BSD2 (see the file LICENSE) Maintainer  : QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}  module Clash.Num.Zeroing   ( Zeroing@@ -20,6 +21,14 @@ import Data.Functor.Compose (Compose(..)) import Data.Hashable (Hashable) import GHC.TypeLits (KnownNat, type (+))+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  ) import Test.QuickCheck (Arbitrary)  import Clash.Class.BitPack (BitPack)@@ -56,6 +65,22 @@ toZeroing :: (SaturatingNum a) => a -> Zeroing a toZeroing = Zeroing +instance+  (CheckedPositiveIntegerLiteral lit a) =>+  CheckedPositiveIntegerLiteral lit (Zeroing a)++instance+  (CheckedNegativeIntegerLiteral lit a) =>+  CheckedNegativeIntegerLiteral lit (Zeroing a)++instance+  (CheckedPositiveRationalLiteral str num den a) =>+  CheckedPositiveRationalLiteral str num den (Zeroing a)++instance+  (CheckedNegativeRationalLiteral str num den a) =>+  CheckedNegativeRationalLiteral str num den (Zeroing a)+ instance (Resize f) => Resize (Compose Zeroing f) where   {-# INLINE resize #-}   resize@@ -108,6 +133,22 @@   -- is not in range (typically wrapping). It would be better if this also   -- returned zero, but in a way which remained synthesizable.   fromInteger = coerce (fromInteger @a)++instance (Ord a, SaturatingNum a) => SaturatingNum (Zeroing a) where+  {-# INLINE satAdd #-}+  satAdd mode (Zeroing a) (Zeroing b) = Zeroing $ satAdd mode a b++  {-# INLINE satSub #-}+  satSub mode (Zeroing a) (Zeroing b) = Zeroing $ satSub mode a b++  {-# INLINE satMul #-}+  satMul mode (Zeroing a) (Zeroing b) = Zeroing $ satMul mode a b++  {-# INLINE satSucc #-}+  satSucc mode (Zeroing a) = Zeroing $ satSucc mode a++  {-# INLINE satPred #-}+  satPred mode (Zeroing a) = Zeroing $ satPred mode a  instance (Enum a, SaturatingNum a) => Enum (Zeroing a) where   {-# INLINE succ #-}
src/Clash/Signal/Delayed/Internal.hs view
@@ -7,6 +7,7 @@   Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com> -} {-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -38,6 +39,14 @@ import Data.Default               (Default(..)) import GHC.TypeLits               (Nat, type (+)) import Language.Haskell.TH.Syntax (Lift)+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  ) import Test.QuickCheck            (Arbitrary, CoArbitrary)  import Clash.Promoted.Nat         (SNat)@@ -106,6 +115,22 @@             }   deriving ( Show, Default, Functor, Applicative, Num, Fractional            , Foldable, Traversable, Arbitrary, CoArbitrary, Lift )++instance+  (CheckedPositiveIntegerLiteral lit a) =>+  CheckedPositiveIntegerLiteral lit (DSignal dom delay a)++instance+  (CheckedNegativeIntegerLiteral lit a) =>+  CheckedNegativeIntegerLiteral lit (DSignal dom delay a)++instance+  (CheckedPositiveRationalLiteral str num den a) =>+  CheckedPositiveRationalLiteral str num den (DSignal dom delay a)++instance+  (CheckedNegativeRationalLiteral str num den a) =>+  CheckedNegativeRationalLiteral str num den (DSignal dom delay a)  -- | Create a 'DSignal' from a list --
src/Clash/Signal/Internal.hs view
@@ -15,6 +15,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RoleAnnotations #-}@@ -210,6 +211,14 @@ import Language.Haskell.TH.Syntax -- (Lift (..), Q, Dec) import Language.Haskell.TH.Compat import Numeric.Natural            (Natural)+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  ) import System.IO.Unsafe           (unsafeInterleaveIO, unsafePerformIO) import Test.QuickCheck            (Arbitrary (..), CoArbitrary(..), Property,                                    property)@@ -915,6 +924,22 @@   abs         = fmap abs   signum      = fmap signum   fromInteger = signal# . fromInteger++instance+  (CheckedPositiveIntegerLiteral lit a) =>+  CheckedPositiveIntegerLiteral lit (Signal dom a)++instance+  (CheckedNegativeIntegerLiteral lit a) =>+  CheckedNegativeIntegerLiteral lit (Signal dom a)++instance+  (CheckedPositiveRationalLiteral str num den a) =>+  CheckedPositiveRationalLiteral str num den (Signal dom a)++instance+  (CheckedNegativeRationalLiteral str num den a) =>+  CheckedNegativeRationalLiteral str num den (Signal dom a)  instance Bounded a => Bounded (Signal dom a) where   minBound = pure minBound
src/Clash/Sized/BitVector.hs view
@@ -34,6 +34,9 @@   , (.<<+)     -- ** Pattern matching   , bitPattern+    -- * Type-level error messages+  , BitPositiveLiteralError+  , BitVectorPositiveLiteralError   ) where 
src/Clash/Sized/Fixed.hs view
@@ -68,6 +68,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NegativeLiterals #-}@@ -106,6 +107,20 @@   , NumFixedC, ENumFixedC, FracFixedC, ResizeFC, DivideC     -- * Proxy   , asRepProxy, asIntProxy+    -- * Type-level error messages+  , UFixedPositiveLiteralError+  , UFixedNegativeLiteralError+  , SFixedPositiveLiteralError+  , SFixedNegativeLiteralError+  , SFixedPositiveRationalRequiredIntBits+  , SFixedNegativeRationalRequiredIntBits+  , SFixedPositiveRationalLiteralError+  , SFixedNegativeRationalLiteralError+  , FitsPositiveSFixedRational+  , FitsNegativeSFixedRational+  , CheckFixedFrac+  , FixedPointNotPow2Error+  , FixedPointNotEnoughFracError   ) where @@ -115,14 +130,27 @@ import Data.Data                  (Data) import Data.Default               (Default (..)) import Data.Either                (isLeft)-import Data.Kind                  (Type)+import Data.Kind                  (Constraint, Type) import Text.Read                  (Read(..)) import Data.List                  (find) import Data.Proxy                 (Proxy (..)) import Data.Ratio                 ((%), denominator, numerator)+import Data.Type.Bool             (If) import Data.Typeable              (Typeable, TypeRep, typeRep, typeOf)-import GHC.TypeLits               (KnownNat, Nat, type (+), natVal)-import GHC.TypeLits.Extra         (Max)+import GHC.TypeError+  ( Assert+  , ErrorMessage (ShowType, Text, (:<>:))+  )+import GHC.TypeLits+  ( Div+  , KnownNat+  , Nat+  , natVal+  , type (+)+  , type (-)+  , type (<=?)+  )+import GHC.TypeLits.Extra         (CLog, Max) import Language.Haskell.TH        (Q, appT, conT, litT, mkName,                                    numTyLit, sigE) import Language.Haskell.TH.Syntax (Lift(..))@@ -141,7 +169,25 @@ import Clash.Class.BitPack.BitReduction (reduceAnd, reduceOr) import Clash.Sized.BitVector      (BitVector, (++#)) import Clash.Sized.Signed         (Signed)+import Clash.Sized.Internal.CheckedLiterals+  ( FractionalBitsNote+  , IntegerBitsNote+  , NotExactlyRepresentable+  , NotExactlyRepresentableWithConstraint+  , OutOfBoundsBecause+  , PotentiallyOutOfBounds+  , SignedIntegerBitsNote+  ) import Clash.Sized.Unsigned       (Unsigned)+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )+import CheckedLiterals.Class.Rational+  ( CheckedNegativeRationalLiteral+  , CheckedPositiveRationalLiteral+  )+import CheckedLiterals.Class.Rational.TypeNats (IsPowerOfTwo) import Clash.XException   (ShowX (..), NFDataX (..), isX, errorX, showsPrecXWith, fromJustX) @@ -223,6 +269,21 @@ -- -5.0 type SFixed = Fixed Signed +type SFixedPositiveRationalRequiredIntBits (num :: Nat) (den :: Nat) =+  CLog 2 (num + 1) + 1 - CLog 2 den++type SFixedNegativeRationalRequiredIntBits (num :: Nat) (den :: Nat) =+  CLog 2 num + 1 - CLog 2 den++type family FitsPositiveSFixedRational (num :: Nat) (den :: Nat) (int :: Nat) :: Bool where+  FitsPositiveSFixedRational 0 den int = 'True+  FitsPositiveSFixedRational num den int =+    SFixedPositiveRationalRequiredIntBits num den <=? int++type family FitsNegativeSFixedRational (num :: Nat) (den :: Nat) (int :: Nat) :: Bool where+  FitsNegativeSFixedRational num den int =+    SFixedNegativeRationalRequiredIntBits num den <=? int+ -- | Unsigned 'Fixed'-point number, with @int@ integer bits and @frac@ -- fractional bits --@@ -253,6 +314,126 @@ -- >>> (1 :: UFixed 3 4) `sub` (3 :: UFixed 3 4) :: UFixed 4 4 -- 14.0 type UFixed = Fixed Unsigned++type UFixedPositiveLiteralError strLit lit int =+  PotentiallyOutOfBounds+    strLit+    (IntegerBitsNote (CLog 2 (lit + 1)))+    (CLog 2 (lit + 1))+    int++instance+  ( Assert+      (If (lit <=? 0) (lit <=? 0) (CLog 2 (lit + 1) <=? int))+      (UFixedPositiveLiteralError (ShowType lit) lit int)+  ) =>+  CheckedPositiveIntegerLiteral lit (UFixed int frac)++type UFixedNegativeLiteralError strLit =+  OutOfBoundsBecause+    strLit+    ('Text "UFixed cannot represent negative numbers.")++instance+  (UFixedNegativeLiteralError ('Text "-" ':<>: 'ShowType lit)) =>+  CheckedNegativeIntegerLiteral lit (UFixed int frac)++type FixedPointNotPow2Error strLit den typ =+  NotExactlyRepresentable+    strLit+    typ+    ( 'Text "The reduced denominator "+        ':<>: 'ShowType den+        ':<>: 'Text " is not a power of 2."+    )++type FixedPointNotEnoughFracError strLit den frac typ =+  NotExactlyRepresentableWithConstraint+    strLit+    typ+    (FractionalBitsNote (CLog 2 den))+    (CLog 2 den)+    frac++type family+  CheckFixedFrac (isPow2 :: Bool) (strLit :: ErrorMessage) (den :: Nat) (frac :: Nat) (typ :: Type) ::+    Constraint+  where+  CheckFixedFrac 'False strLit den frac typ = FixedPointNotPow2Error strLit den typ+  CheckFixedFrac 'True strLit den frac typ =+    Assert+      (CLog 2 den <=? frac)+      (FixedPointNotEnoughFracError strLit den frac typ)++instance+  ( Assert+      (If (Div num den <=? 0) (Div num den <=? 0) (CLog 2 (Div num den + 1) <=? int))+      (UFixedPositiveLiteralError ('Text str) (Div num den) int)+  , CheckFixedFrac (IsPowerOfTwo den) ('Text str) den frac (UFixed int frac)+  ) =>+  CheckedPositiveRationalLiteral str num den (UFixed int frac)++instance+  (UFixedNegativeLiteralError ('Text str)) =>+  CheckedNegativeRationalLiteral str num den (UFixed int frac)++type SFixedPositiveLiteralError strLit lit int =+  PotentiallyOutOfBounds+    strLit+    (SignedIntegerBitsNote (CLog 2 (lit + 1) + 1))+    (CLog 2 (lit + 1) + 1)+    int++instance+  ( Assert+      (If (lit <=? 0) (lit <=? 0) (CLog 2 (lit + 1) + 1 <=? int))+      (SFixedPositiveLiteralError (ShowType lit) lit int)+  ) =>+  CheckedPositiveIntegerLiteral lit (SFixed int frac)++type SFixedNegativeLiteralError strLit lit int =+  PotentiallyOutOfBounds+    strLit+    (SignedIntegerBitsNote (CLog 2 lit + 1))+    (CLog 2 lit + 1)+    int++type SFixedPositiveRationalLiteralError strLit num den int =+  PotentiallyOutOfBounds+    strLit+    (SignedIntegerBitsNote (SFixedPositiveRationalRequiredIntBits num den))+    (SFixedPositiveRationalRequiredIntBits num den)+    int++type SFixedNegativeRationalLiteralError strLit num den int =+  PotentiallyOutOfBounds+    strLit+    (SignedIntegerBitsNote (SFixedNegativeRationalRequiredIntBits num den))+    (SFixedNegativeRationalRequiredIntBits num den)+    int++instance+  ( Assert+      (If (lit <=? 0) (lit <=? 0) (CLog 2 lit + 1 <=? int))+      (SFixedNegativeLiteralError ('Text "-" ':<>: 'ShowType lit) lit int)+  ) =>+  CheckedNegativeIntegerLiteral lit (SFixed int frac)++instance+  ( CheckFixedFrac (IsPowerOfTwo den) ('Text str) den frac (SFixed int frac)+  , Assert+      (FitsPositiveSFixedRational num den int)+      (SFixedPositiveRationalLiteralError ('Text str) num den int)+  ) =>+  CheckedPositiveRationalLiteral str num den (SFixed int frac)++instance+  ( CheckFixedFrac (IsPowerOfTwo den) ('Text str) den frac (SFixed int frac)+  , Assert+      (FitsNegativeSFixedRational num den int)+      (SFixedNegativeRationalLiteralError ('Text str) num den int)+  ) =>+  CheckedNegativeRationalLiteral str num den (SFixed int frac)  {-# INLINE sf #-} -- | Treat a 'Signed' integer as a @Signed@ 'Fixed'-@point@ integer
src/Clash/Sized/Index.hs view
@@ -13,7 +13,10 @@ {-# OPTIONS_HADDOCK show-extensions #-}  module Clash.Sized.Index-  (Index, bv2i, fromSNat)+  ( Index, bv2i, fromSNat+    -- * Type-level error messages+  , IndexPositiveLiteralError+  ) where  import GHC.TypeLits (KnownNat, type (^))
src/Clash/Sized/Internal/BitVector.hs view
@@ -11,6 +11,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RoleAnnotations #-}@@ -30,6 +31,8 @@     -- ** Construction   , high   , low+    -- ** Type-level error messages+  , BitPositiveLiteralError     -- ** Type classes     -- *** Eq   , eq##@@ -127,6 +130,8 @@   , truncateB#     -- *** QuickCheck   , shrinkSizedUnsigned+    -- ** Type-level error messages+  , BitVectorPositiveLiteralError   -- ** Other   , undefError   , checkUnpackUndef@@ -143,6 +148,7 @@ import Data.Default               (Default (..)) import Data.Either                (isLeft) import Data.Proxy                 (Proxy (..))+import Data.Type.Bool             (If) import Data.Typeable              (Typeable, typeOf) import GHC.Generics               (Generic) import Data.Maybe                 (fromMaybe)@@ -156,9 +162,20 @@   (Natural (..), naturalFromWord, naturalShiftL, naturalShiftR, naturalToWord) import GHC.Natural                (naturalToInteger) import GHC.Stack                  (withFrozenCallStack)-import GHC.TypeLits               (KnownNat, Nat, type (+), type (-))+import GHC.TypeError+  ( Assert+  , ErrorMessage (ShowType)+  )+import GHC.TypeLits+  ( KnownNat+  , Nat+  , type (+)+  , type (-)+  , type (<=?)+  , type (^)+  ) import GHC.TypeNats               (natVal)-import GHC.TypeLits.Extra         (Max)+import GHC.TypeLits.Extra         (CLog, Max) import Language.Haskell.TH   (Lit (..), ExpQ, Type(ConT, AppT, LitT), Exp(VarE, AppE, SigE, LitE),    TyLit(NumTyLit), Pat, Q, appT, conT, litE, litP, litT, mkName, numTyLit,@@ -178,10 +195,20 @@ import Clash.Promoted.Nat   (SNat (..), SNatLE (..), compareSNat, snatToInteger, snatToNum, natToNum) import Clash.Sized.Internal (formatRange)+import Clash.Sized.Internal.CheckedLiterals+  ( OutOfBounds+  , PotentiallyOutOfBounds+  , UnsignedBounds+  ) import Clash.XException   (ShowX (..), NFDataX (..), errorX, isX, showsPrecXWith, rwhnfX, XException(..))  import Clash.Sized.Internal.Mod+import CheckedLiterals.Class.Integer+  ( NegativeUnsignedError+  , CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  )  import {-# SOURCE #-} qualified Clash.Sized.Vector         as V import {-# SOURCE #-} qualified Clash.Sized.Internal.Index as I@@ -390,6 +417,17 @@   countLeadingZeros b  = if eq## b low then 1 else 0   countTrailingZeros b = if eq## b low then 1 else 0 +type BitPositiveLiteralError lit =+  OutOfBounds ('ShowType lit) (UnsignedBounds Bit 1)++instance+  (Assert (lit <=? 1) (BitPositiveLiteralError lit)) =>+  CheckedPositiveIntegerLiteral lit Bit++instance+  (NegativeUnsignedError lit Bit 1) =>+  CheckedNegativeIntegerLiteral lit Bit+ and##, or##, xor## :: Bit -> Bit -> Bit and## (Bit m1 v1) (Bit m2 v2) = Bit mask (v1 .&. v2 .&. complement mask)   where mask = (m1.&.v2 .|. m1.&.m2 .|. m2.&.v1)@@ -855,6 +893,24 @@   finiteBitSize       = size#   countLeadingZeros   = fromInteger . I.toInteger# . countLeadingZerosBV   countTrailingZeros  = fromInteger . I.toInteger# . countTrailingZerosBV++type BitVectorPositiveLiteralError lit n =+  PotentiallyOutOfBounds+    ('ShowType lit)+    (UnsignedBounds (BitVector n) ((2 ^ n) - 1))+    (CLog 2 (lit + 1))+    n++instance+  ( Assert+      (If (lit <=? 0) (lit <=? 0) (CLog 2 (lit + 1) <=? n))+      (BitVectorPositiveLiteralError lit n)+  ) =>+  CheckedPositiveIntegerLiteral lit (BitVector n)++instance+  (NegativeUnsignedError lit (BitVector n) ((2 ^ n) - 1)) =>+  CheckedNegativeIntegerLiteral lit (BitVector n)  countLeadingZerosBV :: KnownNat n => BitVector n -> I.Index (n+1) countLeadingZerosBV = V.foldr (\l r -> if eq## l low then 1 + r else 0) 0 . V.bv2v
+ src/Clash/Sized/Internal/CheckedLiterals.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE NoStarIsType #-}+{-# LANGUAGE TypeOperators #-}++module Clash.Sized.Internal.CheckedLiterals where++import Data.Kind (Type)+import GHC.TypeError+  ( ErrorMessage (ShowType, Text, (:$$:), (:<>:))+  , TypeError+  )++type CheckedLiteralUncheckedFix =+  'Text "Possible fix: use 'uncheckedLiteral' from 'CheckedLiterals' to bypass this check."++type AddConstraintFix required actual =+  'Text "Possible fix: add a constraint: "+    ':<>: 'ShowType required+    ':<>: 'Text " <= "+    ':<>: 'ShowType actual+    ':<>: 'Text "."++type UnsignedBounds (typ :: Type) maxVal =+  'ShowType typ+    ':<>: 'Text " has bounds: [0 .. "+    ':<>: 'ShowType maxVal+    ':<>: 'Text "]."++type SignedBounds (typ :: Type) minVal maxVal =+  'ShowType typ+    ':<>: 'Text " has bounds: [-"+    ':<>: 'ShowType minVal+    ':<>: 'Text " .. "+    ':<>: 'ShowType maxVal+    ':<>: 'Text "]."++type IntegerBitsNote bits =+  'Text "Note: integer part needs at least "+    ':<>: 'ShowType bits+    ':<>: 'Text " bit(s)."++type SignedIntegerBitsNote bits =+  'Text "Note: integer part needs at least "+    ':<>: 'ShowType bits+    ':<>: 'Text " bit(s), including sign bit."++type FractionalBitsNote bits =+  'Text "The fractional part needs at least "+    ':<>: 'ShowType bits+    ':<>: 'Text " bit(s)."++type OutOfBounds strLit details =+  TypeError+    ( 'Text "Literal "+        ':<>: strLit+        ':<>: 'Text " is out of bounds."+        ':$$: details+        ':$$: CheckedLiteralUncheckedFix+    )++type PotentiallyOutOfBounds strLit details required actual =+  TypeError+    ( 'Text "Literal "+        ':<>: strLit+        ':<>: 'Text " is (potentially) out of bounds."+        ':$$: details+        ':$$: AddConstraintFix required actual+        ':$$: CheckedLiteralUncheckedFix+    )++type OutOfBoundsBecause strLit reason =+  TypeError+    ( 'Text "Literal "+        ':<>: strLit+        ':<>: 'Text " is out of bounds, because "+        ':<>: reason+        ':$$: CheckedLiteralUncheckedFix+    )++type NotExactlyRepresentable strLit (typ :: Type) reason =+  TypeError+    ( 'Text "Literal "+        ':<>: strLit+        ':<>: 'Text " cannot be represented exactly by "+        ':<>: 'ShowType typ+        ':<>: 'Text "."+        ':$$: reason+        ':$$: CheckedLiteralUncheckedFix+    )++type NotExactlyRepresentableWithConstraint strLit (typ :: Type) reason required actual =+  TypeError+    ( 'Text "Literal "+        ':<>: strLit+        ':<>: 'Text " cannot be represented exactly by "+        ':<>: 'ShowType typ+        ':<>: 'Text "."+        ':$$: reason+        ':$$: AddConstraintFix required actual+        ':$$: CheckedLiteralUncheckedFix+    )
src/Clash/Sized/Internal/Index.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TemplateHaskell #-}@@ -68,6 +69,8 @@   , toInteger#     -- ** Resize   , resize#+    -- * Type-level error messages+  , IndexPositiveLiteralError   ) where @@ -88,8 +91,20 @@ import GHC.Natural                (Natural, naturalFromInteger) import GHC.Natural                (naturalToInteger) import GHC.Stack                  (HasCallStack)-import GHC.TypeLits               (KnownNat, Nat, type (+), type (-),-                                   type (*), type (<=), natVal)+import GHC.TypeError+  ( Assert+  , ErrorMessage (ShowType)+  )+import GHC.TypeLits+  ( KnownNat+  , Nat+  , natVal+  , type (+)+  , type (-)+  , type (*)+  , type (<=)+  , type (<=?)+  ) import GHC.TypeLits.Extra         (CLogWZ) import Test.QuickCheck.Arbitrary  (Arbitrary (..), CoArbitrary (..),                                    arbitraryBoundedIntegral,@@ -103,9 +118,18 @@ import Clash.Class.Resize         (Resize (..)) import Clash.Class.BitPack.BitIndex (replaceBit) import Clash.Sized.Internal       (formatRange)+import Clash.Sized.Internal.CheckedLiterals+  ( PotentiallyOutOfBounds+  , UnsignedBounds+  ) import {-# SOURCE #-} Clash.Sized.Internal.BitVector (BitVector (BV), high, low, undefError) import qualified Clash.Sized.Internal.BitVector as BV import Clash.Promoted.Nat         (SNat(..), UNat(..), toUNat, snatToNum, natToInteger)+import CheckedLiterals.Class.Integer+  ( NegativeUnsignedError+  , CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  ) import Clash.XException   (ShowX (..), NFDataX (..), errorX, showsPrecXWith, rwhnfX, seqX) @@ -287,6 +311,24 @@   abs         = id   signum i    = if i == 0 then 0 else 1   fromInteger = fromInteger#++type IndexPositiveLiteralError lit n =+  PotentiallyOutOfBounds+    ('ShowType lit)+    (UnsignedBounds (Index n) (n - 1))+    (lit + 1)+    n++instance+  ( Assert+      (lit + 1 <=? n)+      (IndexPositiveLiteralError lit n)+  ) =>+  CheckedPositiveIntegerLiteral lit (Index n)++instance+  (NegativeUnsignedError lit (Index n) (n - 1)) =>+  CheckedNegativeIntegerLiteral lit (Index n)  (+#),(-#),(*#) :: KnownNat n => Index n -> Index n -> Index n {-# OPAQUE (+#) #-}
src/Clash/Sized/Internal/Signed.hs view
@@ -8,6 +8,7 @@  {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RoleAnnotations #-}@@ -81,6 +82,9 @@   , truncateB#     -- ** SaturatingNum   , minBoundSym#+    -- * Type-level error messages+  , SignedPositiveLiteralError+  , SignedNegativeLiteralError   ) where @@ -92,13 +96,26 @@ import Data.Data                      (Data) import Data.Default                   (Default (..)) import Data.Proxy                     (Proxy (..))+import Data.Type.Bool                 (If) import Text.Read                      (Read (..), ReadPrec) import Text.Printf                    (PrintfArg (..), printf) import GHC.Generics                   (Generic) import GHC.Natural                    (naturalFromInteger, naturalToInteger) -import GHC.TypeLits                   (KnownNat, Nat, type (+), natVal)-import GHC.TypeLits.Extra             (Max)+import GHC.TypeError+  ( Assert+  , ErrorMessage (ShowType, Text, (:<>:))+  )+import GHC.TypeLits+  ( KnownNat+  , Nat+  , natVal+  , type (+)+  , type (-)+  , type (<=?)+  , type (^)+  )+import GHC.TypeLits.Extra             (CLog, Max) import Data.Ix                        (Ix(..)) import Language.Haskell.TH            (appT, conT, litT, numTyLit, sigE) import Language.Haskell.TH.Syntax     (Lift(..))@@ -118,7 +135,15 @@ import Clash.Class.BitPack.BitReduction (reduceAnd, reduceOr) import Clash.Promoted.Nat             (natToNatural) import Clash.Sized.Internal.BitVector (BitVector (BV), Bit, (++#), high, low, undefError)+import Clash.Sized.Internal.CheckedLiterals+  ( PotentiallyOutOfBounds+  , SignedBounds+  ) import qualified Clash.Sized.Internal.BitVector as BV+import CheckedLiterals.Class.Integer+  ( CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  ) import Clash.XException   (ShowX (..), NFDataX (..), errorX, showsPrecXWith, rwhnfX) @@ -643,6 +668,34 @@   finiteBitSize        = size#   countLeadingZeros  s = countLeadingZeros  (pack# s)   countTrailingZeros s = countTrailingZeros (pack# s)++type SignedPositiveLiteralError lit n =+  PotentiallyOutOfBounds+    ('ShowType lit)+    (SignedBounds (Signed n) (2 ^ (n - 1)) ((2 ^ (n - 1)) - 1))+    (CLog 2 (lit + 1) + 1)+    n++instance+  ( Assert+      (If (lit <=? 0) (lit <=? 0) (CLog 2 (lit + 1) + 1 <=? n))+      (SignedPositiveLiteralError lit n)+  ) =>+  CheckedPositiveIntegerLiteral lit (Signed n)++type SignedNegativeLiteralError lit n =+  PotentiallyOutOfBounds+    ('Text "-" ':<>: 'ShowType lit)+    (SignedBounds (Signed n) (2 ^ (n - 1)) ((2 ^ (n - 1)) - 1))+    (CLog 2 lit + 1)+    n++instance+  ( Assert+      (If (lit <=? 0) (lit <=? 0) (CLog 2 lit + 1 <=? n))+      (SignedNegativeLiteralError lit n)+  ) =>+  CheckedNegativeIntegerLiteral lit (Signed n)  instance Resize Signed where   resize       = resize#
src/Clash/Sized/Internal/Unsigned.hs view
@@ -8,6 +8,7 @@  {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RoleAnnotations #-}@@ -79,6 +80,8 @@   , unsigned8toWord8   , unsigned16toWord16   , unsigned32toWord32+    -- * Type-level error messages+  , UnsignedPositiveLiteralError   ) where @@ -90,6 +93,7 @@ import Data.Data                      (Data) import Data.Default                   (Default (..)) import Data.Proxy                     (Proxy (..))+import Data.Type.Bool                 (If) import Text.Read                      (Read (..), ReadPrec) import Text.Printf                    (PrintfArg (..), printf) import GHC.Exts                       (wordToWord8#, wordToWord16#, wordToWord32#)@@ -100,9 +104,20 @@ import GHC.Num.Natural   (Natural (..), naturalShiftL, naturalShiftR, naturalToWord) import GHC.Natural                    (naturalToInteger)-import GHC.TypeLits                   (KnownNat, Nat, type (+))+import GHC.TypeError+  ( Assert+  , ErrorMessage (ShowType)+  )+import GHC.TypeLits+  ( KnownNat+  , Nat+  , type (+)+  , type (-)+  , type (<=?)+  , type (^)+  ) import GHC.TypeNats                   (natVal)-import GHC.TypeLits.Extra             (Max)+import GHC.TypeLits.Extra             (CLog, Max) import GHC.Word                       (Word (..), Word8 (..), Word16 (..), Word32 (..)) import Data.Ix                        (Ix(..)) import Language.Haskell.TH            (appT, conT, litT, numTyLit, sigE)@@ -123,8 +138,17 @@ import Clash.Class.BitPack.BitReduction (reduceOr) import Clash.Promoted.Nat             (natToNum, natToNatural) import Clash.Sized.Internal.BitVector (BitVector (BV), Bit, high, low, undefError)+import Clash.Sized.Internal.CheckedLiterals+  ( PotentiallyOutOfBounds+  , UnsignedBounds+  ) import qualified Clash.Sized.Internal.BitVector as BV import Clash.Sized.Internal.Mod+import CheckedLiterals.Class.Integer+  ( NegativeUnsignedError+  , CheckedNegativeIntegerLiteral+  , CheckedPositiveIntegerLiteral+  ) import Clash.XException   (ShowX (..), NFDataX (..), errorX, showsPrecXWith, rwhnfX) @@ -544,6 +568,24 @@   finiteBitSize        = size#   countLeadingZeros  u = countLeadingZeros  (pack# u)   countTrailingZeros u = countTrailingZeros (pack# u)++type UnsignedPositiveLiteralError lit n =+  PotentiallyOutOfBounds+    ('ShowType lit)+    (UnsignedBounds (Unsigned n) ((2 ^ n) - 1))+    (CLog 2 (lit + 1))+    n++instance+  ( Assert+      (If (lit <=? 0) (lit <=? 0) (CLog 2 (lit + 1) <=? n))+      (UnsignedPositiveLiteralError lit n)+  ) =>+  CheckedPositiveIntegerLiteral lit (Unsigned n)++instance+  (NegativeUnsignedError lit (Unsigned n) ((2 ^ n) - 1)) =>+  CheckedNegativeIntegerLiteral lit (Unsigned n)  instance Resize Unsigned where   resize     = resize#
src/Clash/Sized/Signed.hs view
@@ -8,6 +8,9 @@  module Clash.Sized.Signed   ( Signed+    -- * Type-level error messages+  , SignedPositiveLiteralError+  , SignedNegativeLiteralError   ) where 
src/Clash/Sized/Unsigned.hs view
@@ -7,7 +7,10 @@ {-# LANGUAGE Trustworthy #-}  module Clash.Sized.Unsigned-  (Unsigned)+  ( Unsigned+    -- * Type-level error messages+  , UnsignedPositiveLiteralError+  ) where  import Clash.Sized.Internal.Unsigned
+ tests/Clash/Tests/CheckedLiterals.hs view
@@ -0,0 +1,28 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++module Clash.Tests.CheckedLiterals (tests) where++import Test.Tasty (TestTree, testGroup)++import qualified Clash.Tests.CheckedLiterals.BitVector+import qualified Clash.Tests.CheckedLiterals.Fixed+import qualified Clash.Tests.CheckedLiterals.Index+import qualified Clash.Tests.CheckedLiterals.Signals+import qualified Clash.Tests.CheckedLiterals.Signed+import qualified Clash.Tests.CheckedLiterals.Unsigned+import qualified Clash.Tests.CheckedLiterals.Wrappers++tests :: TestTree+tests = testGroup "CheckedLiterals"+  [ Clash.Tests.CheckedLiterals.BitVector.tests+  , Clash.Tests.CheckedLiterals.Unsigned.tests+  , Clash.Tests.CheckedLiterals.Signed.tests+  , Clash.Tests.CheckedLiterals.Index.tests+  , Clash.Tests.CheckedLiterals.Fixed.tests+  , Clash.Tests.CheckedLiterals.Wrappers.tests+  , Clash.Tests.CheckedLiterals.Signals.tests+  ]
+ tests/Clash/Tests/CheckedLiterals/BitVector.hs view
@@ -0,0 +1,54 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++module Clash.Tests.CheckedLiterals.BitVector (tests) where++import Prelude++import Test.Tasty (TestTree, testGroup)+import Clash.Tests.CheckedLiterals.Common (toTestCases)++bvMod :: String+bvMod = "Clash.Sized.BitVector"++bitTests :: TestTree+bitTests = testGroup "Bit" $ toTestCases+  [ (bvMod, "Bit", "0",  [])+  , (bvMod, "Bit", "1",  [])+  , (bvMod, "Bit", "-1", ["Literal -1 is out of bounds.", "Bit has bounds: [0 .. 1]."])+  , (bvMod, "Bit", "2",  ["Literal 2 is out of bounds.", "Bit has bounds: [0 .. 1]."])+  ]++bitVectorTests :: TestTree+bitVectorTests = testGroup "BitVector" $ toTestCases+  [ (bvMod, "BitVector 0", "0",                            [])+  , (bvMod, "BitVector 0", "-1",                           ["Literal -1 is out of bounds.", "BitVector 0 has bounds: [0 .. 0]."])+  , (bvMod, "BitVector 0", "1",                            ["Literal 1 is (potentially) out of bounds.", "BitVector 0 has bounds: [0 .. 0]."])+  , (bvMod, "BitVector 1", "0",                            [])+  , (bvMod, "BitVector 1", "-1",                           ["Literal -1 is out of bounds.", "BitVector 1 has bounds: [0 .. 1]."])+  , (bvMod, "BitVector 1", "1",                            [])+  , (bvMod, "BitVector 1", "2",                            ["Literal 2 is (potentially) out of bounds.", "BitVector 1 has bounds: [0 .. 1]."])+  , (bvMod, "BitVector 2", "0",                            [])+  , (bvMod, "BitVector 2", "-1",                           ["Literal -1 is out of bounds.", "BitVector 2 has bounds: [0 .. 3]."])+  , (bvMod, "BitVector 2", "1",                            [])+  , (bvMod, "BitVector 2", "2",                            [])+  , (bvMod, "BitVector 2", "3",                            [])+  , (bvMod, "BitVector 2", "4",                            ["Literal 4 is (potentially) out of bounds.", "BitVector 2 has bounds: [0 .. 3]."])+  , (bvMod, "(KnownNat n) => BitVector n", "0",            [])+  , (bvMod, "(KnownNat n) => BitVector n", "1",            ["Literal 1 is (potentially) out of bounds.", "BitVector n has bounds: [0 .. (2 ^ n) - 1]", "Possible fix: add a constraint: 1 <= n."])+  , (bvMod, "(KnownNat n) => BitVector n", "-1",           ["Literal -1 is out of bounds.", "BitVector n has bounds: [0 .. (2 ^ n) - 1]."])+  , (bvMod, "(KnownNat n, 1 <= n) => BitVector n", "0",    [])+  , (bvMod, "(KnownNat n, 1 <= n) => BitVector n", "1",    [])+  , (bvMod, "(KnownNat n, 1 <= n) => BitVector n", "-1",   ["Literal -1 is out of bounds.", "BitVector n has bounds: [0 .. (2 ^ n) - 1]."])+  , (bvMod, "(KnownNat n, 2 <= n) => BitVector n", "0",    [])+  , (bvMod, "(KnownNat n, 2 <= n) => BitVector n", "1",    [])+  , (bvMod, "(KnownNat n, 2 <= n) => BitVector n", "-1",   ["Literal -1 is out of bounds.", "BitVector n has bounds: [0 .. (2 ^ n) - 1]."])+  , (bvMod, "(KnownNat n, 7 <= n) => BitVector n", "255",  ["Literal 255 is (potentially) out of bounds.", "BitVector n has bounds: [0 .. (2 ^ n) - 1].", "Possible fix: add a constraint: 8 <= n."])+  , (bvMod, "(KnownNat n, 8 <= n) => BitVector n", "256",  ["Literal 256 is (potentially) out of bounds.", "BitVector n has bounds: [0 .. (2 ^ n) - 1].", "Possible fix: add a constraint: 9 <= n."])+  ]++tests :: TestTree+tests = testGroup "BitVector" [bitTests, bitVectorTests]
+ tests/Clash/Tests/CheckedLiterals/Common.hs view
@@ -0,0 +1,46 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE QuasiQuotes #-}++module Clash.Tests.CheckedLiterals.Common where++import Data.List (intercalate)+import Data.String.Interpolate (__i)+import Test.Tasty (TestTree)+import Test.Tasty.AssertGhc (Expected (..), testCaseGhc)++-- | First tuple element may list several modules separated by @", "@; each one+-- gets its own @import@ line in the generated snippet. This lets a test case+-- reference types that live in different modules (e.g. a @Clash.Num.*@ wrapper+-- around a @Clash.Sized.*@ type).+toTestCases :: [(String, String, String, [String])] -> [TestTree]+toTestCases = map toTestCase++toTestCase :: (String, String, String, [String]) -> TestTree+toTestCase (moduleNames, typeName, literal, expectedErrors) =+  testCaseGhc+    ((if null expectedErrors then "OK , " else "NOK, ") ++ typeName ++ ", " ++ literal)+    [__i|+      import Prelude+      #{imports}+      import GHC.TypeNats+      test :: #{typeName}+      test = #{literal}+    |]+    ( if null expectedErrors+        then ExpectSuccess+        else ExpectFailure expectedErrors+    )+ where+  imports = intercalate "\n" ["import " ++ m | m <- splitOnCommaSpace moduleNames]++  splitOnCommaSpace :: String -> [String]+  splitOnCommaSpace s = case break (== ',') s of+    (x, "")       -> [x]+    (x, ',':' ':r) -> x : splitOnCommaSpace r+    (x, ',':r)    -> x : splitOnCommaSpace r+    (x, _)        -> [x]
+ tests/Clash/Tests/CheckedLiterals/Fixed.hs view
@@ -0,0 +1,143 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++module Clash.Tests.CheckedLiterals.Fixed (tests) where++import Prelude++import Test.Tasty (TestTree, testGroup)+import Clash.Tests.CheckedLiterals.Common (toTestCases)++fMod :: String+fMod = "Clash.Sized.Fixed"++integerTests :: TestTree+integerTests = testGroup "Integer" $ toTestCases+  [ (fMod, "(KnownNat f) => UFixed 0 f", "0",                      [])+  , (fMod, "(KnownNat f) => UFixed 0 f", "-1",                     ["Literal -1 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f) => UFixed 0 f", "1",                      ["Literal 1 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s)."])+  , (fMod, "(KnownNat f) => UFixed 1 f", "0",                      [])+  , (fMod, "(KnownNat f) => UFixed 1 f", "-1",                     ["Literal -1 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f) => UFixed 1 f", "1",                      [])+  , (fMod, "(KnownNat f) => UFixed 1 f", "2",                      ["Literal 2 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s)."])+  , (fMod, "(KnownNat f) => UFixed 2 f", "0",                      [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "-1",                     ["Literal -1 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f) => UFixed 2 f", "1",                      [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "2",                      [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "3",                      [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "4",                      ["Literal 4 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s)."])+  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "0",          [])+  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "1",          ["Literal 1 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s).", "Possible fix: add a constraint: 1 <= n."])+  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "-1",         ["Literal -1 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => UFixed n f", "0",  [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => UFixed n f", "1",  [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => UFixed n f", "-1", ["Literal -1 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => UFixed n f", "0",  [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => UFixed n f", "1",  [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => UFixed n f", "-1", ["Literal -1 is out of bounds, because UFixed cannot represent negative numbers."])++  , (fMod, "(KnownNat f) => SFixed 0 f", "0",                      [])+  , (fMod, "(KnownNat f) => SFixed 0 f", "-1",                     ["Literal -1 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 0 f", "1",                      ["Literal 1 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 1 f", "0",                      [])+  , (fMod, "(KnownNat f) => SFixed 1 f", "-1",                     [])+  , (fMod, "(KnownNat f) => SFixed 1 f", "1",                      ["Literal 1 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 1 f", "2",                      ["Literal 2 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 2 f", "0",                      [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "-1",                     [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "-2",                     [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "-3",                     ["Literal -3 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 2 f", "1",                      [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "2",                      ["Literal 2 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 2 f", "4",                      ["Literal 4 is (potentially) out of bounds.", "Note: integer part needs at least 4 bit(s), including sign bit."])+  , (fMod, "(KnownNat f, KnownNat n) => SFixed n f", "0",          [])+  , (fMod, "(KnownNat f, KnownNat n) => SFixed n f", "1",          ["Literal 1 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit.", "Possible fix: add a constraint: 2 <= n."])+  , (fMod, "(KnownNat f, KnownNat n) => SFixed n f", "-1",         ["Literal -1 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit.", "Possible fix: add a constraint: 1 <= n."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => SFixed n f", "0",  [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => SFixed n f", "1",  ["Literal 1 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit.", "Possible fix: add a constraint: 2 <= n."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => SFixed n f", "-1", [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => SFixed n f", "0",  [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => SFixed n f", "1",  [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => SFixed n f", "-1", [])+  ]++rationalTests :: TestTree+rationalTests = testGroup "Rational" $ toTestCases+  [ (fMod, "(KnownNat f) => UFixed 0 f", "0.0",                              [])+  , (fMod, "(KnownNat f) => UFixed 0 f", "-1.0",                             ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f) => UFixed 0 f", "1.0",                              ["Literal 1.0 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s)."])+  , (fMod, "(KnownNat f) => UFixed 1 f", "0.0",                              [])+  , (fMod, "(KnownNat f) => UFixed 1 f", "-1.0",                             ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f) => UFixed 1 f", "1.0",                              [])+  , (fMod, "(KnownNat f) => UFixed 1 f", "2.0",                              ["Literal 2.0 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s)."])+  , (fMod, "(KnownNat f) => UFixed 2 f", "0.0",                              [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "-1.0",                             ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f) => UFixed 2 f", "1.0",                              [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "2.0",                              [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "3.0",                              [])+  , (fMod, "(KnownNat f) => UFixed 2 f", "4.0",                              ["Literal 4.0 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s)."])+  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "0.0",                  [])+  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "1.0",                  ["Literal 1.0 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s).", "Possible fix: add a constraint: 1 <= n."])+  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "-1.0",                 ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => UFixed n f", "0.0",          [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => UFixed n f", "1.0",          [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => UFixed n f", "-1.0",         ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => UFixed n f", "0.0",          [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => UFixed n f", "1.0",          [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => UFixed n f", "-1.0",         ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])++  , (fMod, "(KnownNat f) => SFixed 0 f", "0.0",                              [])+  , (fMod, "(KnownNat f) => SFixed 0 f", "-1.0",                             ["Literal -1.0 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 0 f", "1.0",                              ["Literal 1.0 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 1 f", "0.0",                              [])+  , (fMod, "(KnownNat f) => SFixed 1 f", "-1.0",                             [])+  , (fMod, "(KnownNat f) => SFixed 1 f", "1.0",                              ["Literal 1.0 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 1 f", "2.0",                              ["Literal 2.0 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 2 f", "0.0",                              [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "-1.0",                             [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "-2.0",                             [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "-3.0",                             ["Literal -3.0 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 2 f", "1.0",                              [])+  , (fMod, "(KnownNat f) => SFixed 2 f", "2.0",                              ["Literal 2.0 is (potentially) out of bounds.", "Note: integer part needs at least 3 bit(s), including sign bit."])+  , (fMod, "(KnownNat f) => SFixed 2 f", "4.0",                              ["Literal 4.0 is (potentially) out of bounds.", "Note: integer part needs at least 4 bit(s), including sign bit."])+  , (fMod, "(KnownNat f, KnownNat n) => SFixed n f", "0.0",                  [])+  , (fMod, "(KnownNat f, KnownNat n) => SFixed n f", "1.0",                  ["Literal 1.0 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit.", "Possible fix: add a constraint: 2 <= n."])+  , (fMod, "(KnownNat f, KnownNat n) => SFixed n f", "-1.0",                 ["Literal -1.0 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit.", "Possible fix: add a constraint: 1 <= n."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => SFixed n f", "0.0",          [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => SFixed n f", "1.0",          ["Literal 1.0 is (potentially) out of bounds.", "Note: integer part needs at least 2 bit(s), including sign bit.", "Possible fix: add a constraint: 2 <= n."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n) => SFixed n f", "-1.0",         [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => SFixed n f", "0.0",          [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => SFixed n f", "1.0",          [])+  , (fMod, "(KnownNat f, KnownNat n, 2 <= n) => SFixed n f", "-1.0",         [])++  , (fMod, "UFixed 0 0", "0.5",                                              ["Literal 0.5 cannot be represented exactly by Fixed", "The fractional part needs at least 1 bit(s)."])+  , (fMod, "UFixed 0 1", "0.5",                                              [])+  , (fMod, "UFixed 0 1", "0.75",                                             ["Literal 0.75 cannot be represented exactly by Fixed", "The fractional part needs at least 2 bit(s)."])+  , (fMod, "UFixed 0 1", "0.1",                                              ["Literal 0.1 cannot be represented exactly by", "The reduced denominator 10 is not a power of 2."])+  , (fMod, "(KnownNat f, 1 <= f) => UFixed 0 f", "0.5",                      [])+  , (fMod, "(KnownNat f, 1 <= f) => UFixed 0 f", "0.75",                     ["Literal 0.75 cannot be represented exactly by Fixed", "The fractional part needs at least 2 bit(s).", "Possible fix: add a constraint: 2 <= f."])+  , (fMod, "(KnownNat f, 2 <= f) => UFixed 0 f", "0.75",                     [])+  , (fMod, "(KnownNat f, 3 <= f) => UFixed 0 f", "0.75",                     [])++  , (fMod, "SFixed 0 0", "0.5",                                              ["Literal 0.5 cannot be represented exactly by Fixed", "The fractional part needs at least 1 bit(s)."])+  , (fMod, "SFixed 0 1", "0.5",                                              ["Literal 0.5 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit.", "Possible fix: add a constraint: 1 <= 0."])+  , (fMod, "SFixed 0 1", "0.75",                                             ["Literal 0.75 cannot be represented exactly by Fixed", "The fractional part needs at least 2 bit(s)."])+  , (fMod, "SFixed 0 1", "0.1",                                              ["Literal 0.1 cannot be represented exactly by", "The reduced denominator 10 is not a power of 2."])+  , (fMod, "(KnownNat f, 1 <= f) => SFixed 0 f", "0.5",                      ["Literal 0.5 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit.", "Possible fix: add a constraint: 1 <= 0."])+  , (fMod, "(KnownNat f, 1 <= f) => SFixed 0 f", "0.75",                     ["Literal 0.75 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit.", "Possible fix: add a constraint: 1 <= 0."])+  , (fMod, "(KnownNat f, 2 <= f) => SFixed 0 f", "0.75",                     ["Literal 0.75 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit.", "Possible fix: add a constraint: 1 <= 0."])+  , (fMod, "(KnownNat f, 3 <= f) => SFixed 0 f", "0.75",                     ["Literal 0.75 is (potentially) out of bounds.", "Note: integer part needs at least 1 bit(s), including sign bit.", "Possible fix: add a constraint: 1 <= 0."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n, 1 <= f) => SFixed n f", "0.5",  [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n, 1 <= f) => SFixed n f", "0.75", ["Literal 0.75 cannot be represented exactly by Fixed", "The fractional part needs at least 2 bit(s).", "Possible fix: add a constraint: 2 <= f."])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n, 2 <= f) => SFixed n f", "0.75", [])+  , (fMod, "(KnownNat f, KnownNat n, 1 <= n, 3 <= f) => SFixed n f", "0.75", [])++  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "255.0",                ["Literal 255.0 is (potentially) out of bounds.", "Note: integer part needs at least 8 bit(s).", "Possible fix: add a constraint: 8 <= n."])+  , (fMod, "(KnownNat f, KnownNat n) => UFixed n f", "256.0",                ["Literal 256.0 is (potentially) out of bounds.", "Note: integer part needs at least 9 bit(s).", "Possible fix: add a constraint: 9 <= n."])+  ]++tests :: TestTree+tests = testGroup "Fixed" [integerTests, rationalTests]
+ tests/Clash/Tests/CheckedLiterals/Index.hs view
@@ -0,0 +1,44 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++The type argument of 'Index' is the exclusive upper bound, not a bit width,+so @Index 4@ has bounds @[0 .. 3]@ (the same range as @Unsigned 2@). The+polymorphic bounds message therefore reads @Index n has bounds: [0 .. n - 1]@+rather than @[0 .. (2 ^ n) - 1]@.+-}++module Clash.Tests.CheckedLiterals.Index (tests) where++import Prelude++import Test.Tasty (TestTree, testGroup)+import Clash.Tests.CheckedLiterals.Common (toTestCases)++iMod :: String+iMod = "Clash.Sized.Index"++tests :: TestTree+tests = testGroup "Index" $ toTestCases+  [ (iMod, "Index 1", "0",                            [])+  , (iMod, "Index 1", "-1",                           ["Literal -1 is out of bounds.", "Index 1 has bounds: [0 .. 0]."])+  , (iMod, "Index 1", "1",                            ["Literal 1 is (potentially) out of bounds.", "Index 1 has bounds: [0 .. 0]."])+  , (iMod, "Index 2", "0",                            [])+  , (iMod, "Index 2", "-1",                           ["Literal -1 is out of bounds.", "Index 2 has bounds: [0 .. 1]."])+  , (iMod, "Index 2", "1",                            [])+  , (iMod, "Index 2", "2",                            ["Literal 2 is (potentially) out of bounds.", "Index 2 has bounds: [0 .. 1]."])+  , (iMod, "Index 4", "0",                            [])+  , (iMod, "Index 4", "-1",                           ["Literal -1 is out of bounds.", "Index 4 has bounds: [0 .. 3]."])+  , (iMod, "Index 4", "1",                            [])+  , (iMod, "Index 4", "3",                            [])+  , (iMod, "Index 4", "4",                            ["Literal 4 is (potentially) out of bounds.", "Index 4 has bounds: [0 .. 3]."])+  , (iMod, "(KnownNat n) => Index n", "0",            ["Literal 0 is (potentially) out of bounds.", "Index n has bounds: [0 .. n - 1].", "Possible fix: add a constraint: 1 <= n."])+  , (iMod, "(KnownNat n) => Index n", "1",            ["Literal 1 is (potentially) out of bounds.", "Index n has bounds: [0 .. n - 1]", "Possible fix: add a constraint: 2 <= n."])+  , (iMod, "(KnownNat n) => Index n", "-1",           ["Literal -1 is out of bounds.", "Index n has bounds: [0 .. n - 1]."])+  , (iMod, "(KnownNat n, 1 <= n) => Index n", "0",    [])+  , (iMod, "(KnownNat n, 2 <= n) => Index n", "1",    [])+  , (iMod, "(KnownNat n, 1 <= n) => Index n", "-1",   ["Literal -1 is out of bounds.", "Index n has bounds: [0 .. n - 1]."])+  , (iMod, "(KnownNat n, 3 <= n) => Index n", "2",    [])+  , (iMod, "(KnownNat n, 3 <= n) => Index n", "3",    ["Literal 3 is (potentially) out of bounds.", "Index n has bounds: [0 .. n - 1].", "Possible fix: add a constraint: 4 <= n."])+  ]
+ tests/Clash/Tests/CheckedLiterals/Signals.hs view
@@ -0,0 +1,42 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++Smoke tests for the passthrough @CheckedLiteral@ instances on 'Signal' and+'DSignal': they forward the check to the signal's element type.++The @toTestCases@ helper only injects one module import, so we rely on+'System' being re-exported from 'Clash.Signal' and 'Clash.Signal.Delayed'.+-}++module Clash.Tests.CheckedLiterals.Signals (tests) where++import Prelude++import Test.Tasty (TestTree, testGroup)+import Clash.Tests.CheckedLiterals.Common (toTestCases)++pMod :: String+pMod = "Clash.Prelude"++signalTests :: TestTree+signalTests = testGroup "Signal" $ toTestCases+  [ (pMod, "Signal System (Unsigned 2)", "3",  [])+  , (pMod, "Signal System (Unsigned 2)", "4",  ["Literal 4 is (potentially) out of bounds.", "Unsigned 2 has bounds: [0 .. 3]."])+  , (pMod, "Signal System (Signed 2)",   "-2", [])+  , (pMod, "Signal System (Signed 2)",   "2",  ["Signed 2 has bounds: [-2 .. 1]"])+  , (pMod, "Signal System (UFixed 1 2)", "0.75", [])+  , (pMod, "Signal System (UFixed 1 2)", "-1.0", ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])+  ]++dsignalTests :: TestTree+dsignalTests = testGroup "DSignal" $ toTestCases+  [ (pMod, "DSignal System 0 (Unsigned 2)", "3", [])+  , (pMod, "DSignal System 0 (Unsigned 2)", "4", ["Literal 4 is (potentially) out of bounds.", "Unsigned 2 has bounds: [0 .. 3]."])+  , (pMod, "DSignal System 0 (Signed 2)", "-2",  [])+  , (pMod, "DSignal System 0 (Signed 2)", "2",   ["Signed 2 has bounds: [-2 .. 1]"])+  ]++tests :: TestTree+tests = testGroup "Signals" [signalTests, dsignalTests]
+ tests/Clash/Tests/CheckedLiterals/Signed.hs view
@@ -0,0 +1,43 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++module Clash.Tests.CheckedLiterals.Signed (tests) where++import Prelude++import Test.Tasty (TestTree, testGroup)+import Clash.Tests.CheckedLiterals.Common (toTestCases)++sMod :: String+sMod = "Clash.Sized.Signed"++tests :: TestTree+tests = testGroup "Signed" $ toTestCases+  [ (sMod, "Signed 0", "0",                          [])+  , (sMod, "Signed 0", "-1",                         ["Literal -1 is (potentially) out of bounds."])+  , (sMod, "Signed 0", "1",                          ["Literal 1 is (potentially) out of bounds."])+  , (sMod, "Signed 1", "0",                          [])+  , (sMod, "Signed 1", "-1",                         [])+  , (sMod, "Signed 1", "1",                          ["Literal 1 is (potentially) out of bounds.", "Signed 1 has bounds: [-1 .. 0]"])+  , (sMod, "Signed 2", "0",                          [])+  , (sMod, "Signed 2", "-1",                         [])+  , (sMod, "Signed 2", "-2",                         [])+  , (sMod, "Signed 2", "-3",                         ["Literal -3 is (potentially) out of bounds.", "Signed 2 has bounds: [-2 .. 1]"])+  , (sMod, "Signed 2", "1",                          [])+  , (sMod, "Signed 2", "2",                          ["Signed 2 has bounds: [-2 .. 1]"])+  , (sMod, "(KnownNat n) => Signed n", "0",          [])+  , (sMod, "(KnownNat n) => Signed n", "1",          ["Signed n has bounds: [-2 ^ (n - 1) .. (2 ^ (n - 1)) - 1]", "Possible fix: add a constraint: 2 <= n."])+  , (sMod, "(KnownNat n) => Signed n", "-1",         ["Literal -1 is (potentially) out of bounds.", "Signed n has bounds: [-2 ^ (n - 1) .. (2 ^ (n - 1)) - 1]", "Possible fix: add a constraint: 1 <= n."])+  , (sMod, "(KnownNat n, 1 <= n) => Signed n", "0",  [])+  , (sMod, "(KnownNat n, 1 <= n) => Signed n", "1",  ["Signed n has bounds: [-2 ^ (n - 1) .. (2 ^ (n - 1)) - 1]", "Possible fix: add a constraint: 2 <= n."])+  , (sMod, "(KnownNat n, 1 <= n) => Signed n", "-1", [])+  , (sMod, "(KnownNat n, 2 <= n) => Signed n", "0",  [])+  , (sMod, "(KnownNat n, 2 <= n) => Signed n", "1",  [])+  , (sMod, "(KnownNat n, 2 <= n) => Signed n", "-1", [])+  , (sMod, "(KnownNat n, 3 <= n) => Signed n", "0",  [])+  , (sMod, "(KnownNat n, 3 <= n) => Signed n", "1",  [])+  , (sMod, "(KnownNat n, 3 <= n) => Signed n", "-1", [])+  ]
+ tests/Clash/Tests/CheckedLiterals/Unsigned.hs view
@@ -0,0 +1,43 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++module Clash.Tests.CheckedLiterals.Unsigned (tests) where++import Prelude++import Test.Tasty (TestTree, testGroup)+import Clash.Tests.CheckedLiterals.Common (toTestCases)++uMod :: String+uMod = "Clash.Sized.Unsigned"++tests :: TestTree+tests = testGroup "Unsigned" $ toTestCases+  [ (uMod, "Unsigned 0", "0",                           [])+  , (uMod, "Unsigned 0", "-1",                          ["Literal -1 is out of bounds.", "Unsigned 0 has bounds: [0 .. 0]."])+  , (uMod, "Unsigned 0", "1",                           ["Literal 1 is (potentially) out of bounds.", "Unsigned 0 has bounds: [0 .. 0]."])+  , (uMod, "Unsigned 1", "0",                           [])+  , (uMod, "Unsigned 1", "-1",                          ["Literal -1 is out of bounds.", "Unsigned 1 has bounds: [0 .. 1]."])+  , (uMod, "Unsigned 1", "1",                           [])+  , (uMod, "Unsigned 1", "2",                           ["Literal 2 is (potentially) out of bounds.", "Unsigned 1 has bounds: [0 .. 1]."])+  , (uMod, "Unsigned 2", "0",                           [])+  , (uMod, "Unsigned 2", "-1",                          ["Literal -1 is out of bounds.", "Unsigned 2 has bounds: [0 .. 3]."])+  , (uMod, "Unsigned 2", "1",                           [])+  , (uMod, "Unsigned 2", "2",                           [])+  , (uMod, "Unsigned 2", "3",                           [])+  , (uMod, "Unsigned 2", "4",                           ["Literal 4 is (potentially) out of bounds.", "Unsigned 2 has bounds: [0 .. 3]."])+  , (uMod, "(KnownNat n) => Unsigned n", "0",           [])+  , (uMod, "(KnownNat n) => Unsigned n", "1",           ["Literal 1 is (potentially) out of bounds.", "Unsigned n has bounds: [0 .. (2 ^ n) - 1]", "Possible fix: add a constraint: 1 <= n."])+  , (uMod, "(KnownNat n) => Unsigned n", "-1",          ["Literal -1 is out of bounds.", "Unsigned n has bounds: [0 .. (2 ^ n) - 1]."])+  , (uMod, "(KnownNat n, 1 <= n) => Unsigned n", "0",   [])+  , (uMod, "(KnownNat n, 1 <= n) => Unsigned n", "1",   [])+  , (uMod, "(KnownNat n, 1 <= n) => Unsigned n", "-1",  ["Literal -1 is out of bounds.", "Unsigned n has bounds: [0 .. (2 ^ n) - 1]."])+  , (uMod, "(KnownNat n, 2 <= n) => Unsigned n", "0",   [])+  , (uMod, "(KnownNat n, 2 <= n) => Unsigned n", "1",   [])+  , (uMod, "(KnownNat n, 2 <= n) => Unsigned n", "-1",  ["Literal -1 is out of bounds.", "Unsigned n has bounds: [0 .. (2 ^ n) - 1]."])+  , (uMod, "(KnownNat n, 7 <= n) => Unsigned n", "255", ["Literal 255 is (potentially) out of bounds.", "Unsigned n has bounds: [0 .. (2 ^ n) - 1].", "Possible fix: add a constraint: 8 <= n."])+  , (uMod, "(KnownNat n, 8 <= n) => Unsigned n", "256", ["Literal 256 is (potentially) out of bounds.", "Unsigned n has bounds: [0 .. (2 ^ n) - 1].", "Possible fix: add a constraint: 9 <= n."])+  ]
+ tests/Clash/Tests/CheckedLiterals/Wrappers.hs view
@@ -0,0 +1,43 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++Smoke tests for the passthrough @CheckedLiteral@ instances on the numeric+wrapper newtypes: they should forward the check to the underlying type —+good literals type-check, bad ones surface the underlying type's error.+-}++module Clash.Tests.CheckedLiterals.Wrappers (tests) where++import Prelude++import Test.Tasty (TestTree, testGroup)+import Clash.Tests.CheckedLiterals.Common (toTestCases)++wrapU, satS, ovU, zerS, errUF :: String+wrapU = "Clash.Num.Wrapping, Clash.Sized.Unsigned"+satS  = "Clash.Num.Saturating, Clash.Sized.Signed"+ovU   = "Clash.Num.Overflowing, Clash.Sized.Unsigned"+zerS  = "Clash.Num.Zeroing, Clash.Sized.Signed"+errUF = "Clash.Num.Erroring, Clash.Sized.Fixed"++tests :: TestTree+tests = testGroup "Wrappers" $ toTestCases+  [ (wrapU, "Wrapping (Unsigned 2)",   "3",    [])+  , (wrapU, "Wrapping (Unsigned 2)",   "4",    ["Literal 4 is (potentially) out of bounds.", "Unsigned 2 has bounds: [0 .. 3]."])+  , (wrapU, "Wrapping (Unsigned 2)",   "-1",   ["Literal -1 is out of bounds.", "Unsigned 2 has bounds: [0 .. 3]."])++  , (satS,  "Saturating (Signed 2)",   "-2",   [])+  , (satS,  "Saturating (Signed 2)",   "2",    ["Signed 2 has bounds: [-2 .. 1]"])++  , (ovU,   "Overflowing (Unsigned 2)", "3",   [])+  , (ovU,   "Overflowing (Unsigned 2)", "4",   ["Literal 4 is (potentially) out of bounds.", "Unsigned 2 has bounds: [0 .. 3]."])++  , (zerS,  "Zeroing (Signed 2)",      "-1",   [])+  , (zerS,  "Zeroing (Signed 2)",      "2",    ["Signed 2 has bounds: [-2 .. 1]"])++  , (errUF, "Erroring (UFixed 1 2)",   "0.75", [])+  , (errUF, "Erroring (UFixed 1 2)",   "-1.0", ["Literal -1.0 is out of bounds, because UFixed cannot represent negative numbers."])+  , (errUF, "Erroring (UFixed 1 2)",   "0.1",  ["Literal 0.1 cannot be represented exactly by", "The reduced denominator 10 is not a power of 2."])+  ]
tests/Clash/Tests/Laws/SaturatingNum.hs view
@@ -21,6 +21,7 @@ import Test.Tasty.HUnit.Extra  import Clash.Class.Num+import Clash.Num.Overflowing (Overflowing, toOverflowing) import Clash.Sized.Index (Index) import Clash.Sized.Signed (Signed) import Clash.Sized.Fixed (SFixed, UFixed)@@ -151,12 +152,21 @@ genIndex :: forall n. KnownNat n => Gen (Index n) genIndex = genBoundedIntegral +genOIndex :: forall n. KnownNat n => Gen (Overflowing (Index n))+genOIndex = toOverflowing <$> genIndex+ genUnsigned :: forall n. KnownNat n => Gen (Unsigned n) genUnsigned = genBoundedIntegral +genOUnsigned :: forall n. KnownNat n => Gen (Overflowing (Unsigned n))+genOUnsigned = toOverflowing <$> genUnsigned+ genSigned :: forall n. KnownNat n => Gen (Signed n) genSigned = genBoundedIntegral +genOSigned :: forall n. KnownNat n => Gen (Overflowing (Signed n))+genOSigned = toOverflowing <$> genSigned+ -- | Generates a bounded fractional with a bias towards extreme values: -- --      5%: minBound@@ -179,9 +189,15 @@ genSFixed :: forall a b. (KnownNat a, KnownNat b) => Gen (SFixed a b) genSFixed = genBoundedFractional +genOSFixed :: forall a b. (KnownNat a, KnownNat b) => Gen (Overflowing (SFixed a b))+genOSFixed = toOverflowing <$> genSFixed+ genUFixed :: forall a b. (KnownNat a, KnownNat b) => Gen (UFixed a b) genUFixed = genBoundedFractional +genOUFixed :: forall a b. (KnownNat a, KnownNat b) => Gen (Overflowing (UFixed a b))+genOUFixed = toOverflowing <$> genUFixed+ tests :: TestTree tests = testGroup "SaturatingNum"   [ testSaturationLaws True "Index 1" (genIndex @1)@@ -225,4 +241,20 @@   , testSaturationLaws False "UFixed 7 7" (genUFixed @7 @7)   , testSaturationLaws False "UFixed 121 121" (genUFixed @121 @121)   , testSaturationLaws False "UFixed 128 128" (genUFixed @128 @128)++  , testSaturationLaws True "Overflowing (Index 1)" (genOIndex @1)+  , testSaturationLaws True "Overflowing (Index 10)" (genOIndex @10)+  , testSaturationLaws True "Overflowing (Signed 0)" (genOSigned @0)+  , testSaturationLaws True "Overflowing (Signed 8)" (genOSigned @8)+  , testSaturationLaws True "Overflowing (Unsigned 0)" (genOUnsigned @0)+  , testSaturationLaws True "Overflowing (Unsigned 8)" (genOUnsigned @8)+  , testSaturationLaws False "Overflowing (UFixed 7 7)" (genOUFixed @7 @7)+  , testSaturationLaws False "Overflowing (SFixed 0 0)" (genOSFixed @0 @0)+  , testSaturationLaws False "Overflowing (SFixed 0 1)" (genOSFixed @0 @1)+  , testSaturationLaws False "Overflowing (SFixed 1 0)" (genOSFixed @1 @0)+  , testSaturationLaws False "Overflowing (SFixed 7 7)" (genOSFixed @7 @7)+  , testSaturationLaws False "Overflowing (UFixed 0 0)" (genOUFixed @0 @0)+  , testSaturationLaws False "Overflowing (UFixed 0 1)" (genOUFixed @0 @1)+  , testSaturationLaws False "Overflowing (UFixed 1 0)" (genOUFixed @1 @0)+  , testSaturationLaws False "Overflowing (UFixed 7 7)" (genOUFixed @7 @7)   ]
tests/Clash/Tests/TopEntityGeneration.hs view
@@ -73,7 +73,15 @@   , someOtherField :: "c" ::: Signal System ("wobble" ::: Int)   } +newtype N a = N a +data NewtypedRecord =+  NewtypedRecord+    { nrA :: "a" ::: Bool+    , nrB :: "b" ::: Bool+    }++ topEntity1 :: "in1" ::: Signal System Int            -> "in2" ::: Signal System Bool            -> "out" ::: Signal System Int@@ -261,6 +269,17 @@     ]     (PortName "out") +-- See https://github.com/clash-lang/clash-compiler/issues/3066+topEntity11 :: "o" ::: N NewtypedRecord+topEntity11 = undefined+makeTopEntity 'topEntity11++expectedTopEntity11 :: TopEntity+expectedTopEntity11 =+  Synthesize "topEntity11"+    []+    (PortProduct "o" [PortName "a", PortName "b"])+ topEntityFailure1   :: "int"     ::: Signal System Int   -> "tuple"   ::: ("tup1" ::: Signal System (BitVector 7), "tup2" ::: Signal System (BitVector 9))@@ -342,6 +361,9 @@       , testCase "topEntity10" $           $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntity10)           @?= Just expectedTopEntity10+      , testCase "topEntity11" $+          $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntity11)+          @?= Just expectedTopEntity11       ]     , testGroup "Expected failures"       [ testCase "topEntityFailure1" $
+ tests/Test/Tasty/AssertGhc.hs view
@@ -0,0 +1,127 @@+{-|+Copyright  :  (C) 2026, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++Compile-time assertion helpers for @checked-literals@ tests: spawns a+subprocess GHC on a generated module and checks whether it succeeds or+fails with the expected error substrings.++Ported from+<https://github.com/clash-lang/checked-literals/blob/main/tests/Test/Tasty/AssertGhc.hs>.+-}++{-# LANGUAGE CPP #-}++module Test.Tasty.AssertGhc where++import Prelude++import Data.List (isInfixOf)+import Data.Maybe (fromMaybe)+import System.Environment (lookupEnv)+import System.Exit+import System.IO+import System.IO.Temp+import System.Process+import Test.Tasty (TestTree, askOption)+import Test.Tasty.HUnit+import Test.Tasty.Options+import Text.Read (readMaybe)++data Expected = ExpectFailure [String] | ExpectSuccess++-- | Option to enable debug output of GHC error messages+newtype DebugGhc = DebugGhc Bool+  deriving (Show, Read)++instance IsOption DebugGhc where+  defaultValue = DebugGhc False+  parseValue = fmap DebugGhc . readMaybe+  optionName = return "debug-ghc"+  optionHelp = return "Print full GHC output for error test cases"+  optionCLParser = flagCLParser Nothing (DebugGhc True)++testCaseGhc :: String -> String -> Expected -> TestTree+testCaseGhc name source expected =+  askOption $ \(DebugGhc debugGhc) ->+    testCaseInfo name $ do+      debugOutput <- assertGhc source expected+      if debugGhc then return debugOutput else return ""++{- | Assert that a Haskell code snippet fails to compile with expected error messages+Returns the GHC output for display in test results if debug flag is set.++The subprocess GHC picks up @clash-prelude@ and @checked-literals@ via the+@.ghc.environment.*@ file that cabal drops next to the test binary. This means+the test binary must be run from (or below) the project root where cabal+generates the environment file; @cabal run clash-prelude:unittests@ satisfies+that.+-}+assertGhc :: String -> Expected -> IO String+assertGhc source expected = do+  -- XXX: This will pick the wrong GHC if the HC environment variable (as seen on CI)+  --      isn't set and the test suite is compiled with a GHC compiler other than the+  --      system's default.+  hc <- fromMaybe "ghc" <$> lookupEnv "HC"+  withSystemTempFile "ShouldError.hs" $ \tempFile tempHandle -> do+    -- Write source with proper Main module structure+    hPutStr tempHandle "module Main where\n"+    hPutStr tempHandle source+    hPutStr tempHandle "\nmain :: IO ()\nmain = return ()\n"+    hClose tempHandle+    (exitCode, _, stderrOutput) <-+      readProcessWithExitCode+        hc+        [ "-XCPP"+        , "-XDataKinds"+        , "-XTypeOperators"+        , "-XTypeApplications"+        , "-XTypeFamilies"+        , "-XFlexibleContexts"+        , "-XUndecidableInstances"+        , "-XNoStarIsType"+        , "-XViewPatterns"+        , "-XNoImplicitPrelude"+        , "-fno-code"+        , "-package", "clash-prelude"+        , "-package", "checked-literals"+        , "-fplugin=GHC.TypeLits.KnownNat.Solver"+        , "-fplugin=GHC.TypeLits.Normalise"+        , "-fplugin=GHC.TypeLits.Extra.Solver"+        , "-fplugin=CheckedLiterals"+        , tempFile+        ]+        ""+    case (exitCode, expected) of+      (ExitSuccess, ExpectSuccess) ->+        return ""+      (ExitSuccess, ExpectFailure _) ->+        assertFailure "Expected compilation to fail but it succeeded" >> return ""+      (ExitFailure _, ExpectSuccess) ->+        assertFailure ("Expected compilation to succeed but it failed with error:\n" ++ stderrOutput)+          >> return ""+      (ExitFailure _, ExpectFailure expectedErrors) ->+        let cleanedStderr = removeProblemChars stderrOutput+            cleanedExpected = map removeProblemChars expectedErrors+         in if all (`isInfixOf` cleanedStderr) cleanedExpected+              then return stderrOutput+              else do+                _ <-+                  assertFailure $+                    "Error message mismatch:\n"+                      ++ "Expected substrings: "+                      ++ show expectedErrors+                      ++ "\n"+                      ++ "Actual output:\n"+                      ++ stderrOutput+                return stderrOutput++{- | Remove problematic characters that vary depending on locale+The kind and amount of quotes in GHC error messages changes depending on+whether or not our locale supports unicode.+-}+removeProblemChars :: String -> String+removeProblemChars = filter (`notElem` problemChars)+ where+  problemChars = "\x2018\x2019`'"
tests/unittests.hs view
@@ -8,6 +8,7 @@ import qualified Clash.Tests.BitVector import qualified Clash.Tests.BlockRam import qualified Clash.Tests.BlockRam.Blob+import qualified Clash.Tests.CheckedLiterals import qualified Clash.Tests.Clocks import qualified Clash.Tests.Counter import qualified Clash.Tests.DerivingDataRepr@@ -42,6 +43,7 @@   , Clash.Tests.BitVector.tests   , Clash.Tests.BlockRam.Blob.tests   , Clash.Tests.BlockRam.tests+  , Clash.Tests.CheckedLiterals.tests   , Clash.Tests.Clocks.tests   , Clash.Tests.Counter.tests   , Clash.Tests.DerivingDataRepr.tests