From dd094b37c210192fe4969e376be60a5efe2b9522 Mon Sep 17 00:00:00 2001 From: Leon Schoorl Date: Fri, 27 Jan 2023 13:24:56 +0100 Subject: [PATCH] Make sure caseCon only works on matching data constructors Fixes #2376 --- .../Clash/Normalize/Transformations/Case.hs | 2 +- tests/Main.hs | 1 + .../Issues/T2376_unsafeCoerce_Dict.hs | 37 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/shouldwork/Issues/T2376_unsafeCoerce_Dict.hs diff --git a/clash-lib/src/Clash/Normalize/Transformations/Case.hs b/clash-lib/src/Clash/Normalize/Transformations/Case.hs index c2c14293cb..ef9f7d7555 100644 --- a/clash-lib/src/Clash/Normalize/Transformations/Case.hs +++ b/clash-lib/src/Clash/Normalize/Transformations/Case.hs @@ -229,7 +229,7 @@ caseCon' ctx@(TransformContext is0 _) e@(Case subj ty alts) = do _ -> changed (TyApp (Prim NP.undefined) ty) where -- Check whether the pattern matches the data constructor - equalCon (DataPat dcPat _ _) = dcTag dc == dcTag dcPat + equalCon (DataPat dcPat _ _) = dcUniq dc == dcUniq dcPat equalCon _ = False -- Decide whether the applied arguments of the data constructor should diff --git a/tests/Main.hs b/tests/Main.hs index d6fccc46a8..ef6424b84f 100755 --- a/tests/Main.hs +++ b/tests/Main.hs @@ -634,6 +634,7 @@ runClashTest = defaultMain $ clashTestRoot , runTest "T2342A" def{hdlSim=[]} , runTest "T2342B" def{hdlSim=[]} , runTest "T2360" def{hdlSim=[],clashFlags=["-fclash-force-undefined=0"]} + , runTest "T2376_unsafeCoerce_Dict" def{hdlTargets=[VHDL],hdlSim=[]} ] <> if compiledWith == Cabal then -- This tests fails without environment files present, which are only diff --git a/tests/shouldwork/Issues/T2376_unsafeCoerce_Dict.hs b/tests/shouldwork/Issues/T2376_unsafeCoerce_Dict.hs new file mode 100644 index 0000000000..1d0887072c --- /dev/null +++ b/tests/shouldwork/Issues/T2376_unsafeCoerce_Dict.hs @@ -0,0 +1,37 @@ +module T2376_unsafeCoerce_Dict where + +import Clash.Prelude +import Data.Constraint +import Data.Proxy +import Unsafe.Coerce + +data T depth = T (BitVector depth) deriving (Generic) + +instance (1 <= CLog 2 depth, KnownNat depth) => NFDataX (T depth) + +-- | if (2 <= n) holds, then (1 <= CLog 2 n) also holds. +oneLeCLog2n :: forall n . (2 <= n) => Proxy n -> Dict (1 <= CLog 2 n) +oneLeCLog2n Proxy = unsafeCoerce (Dict :: Dict ()) + +f :: + forall dom depth. + ( HiddenClockResetEnable dom + , KnownNat depth + , 2 <= depth ) => + Proxy depth -> + Signal dom Bool -> + Signal dom Bool +f Proxy = + case oneLeCLog2n (Proxy @depth) of + Dict -> mealy go (T 0) + + where + go :: T depth -> Bool -> (T depth, Bool) + go (T n) True = (T (n + 1), False) + go (T n) False = (T (n - 1), True) +{-# NOINLINE f #-} + +topEntity clk rst ena = + withClockResetEnable clk rst ena $ + f @System @2 Proxy +{-# NOINLINE topEntity #-}