Skip to content

Assertion failure with TypeData + dataToTag#

(Originally spun off from !9960 (comment 481426))

If you compile the following program with GHC 9.6 when built with assertions enabled + -O:

{-# LANGUAGE TypeData, MagicHash #-}
module B where

import GHC.Exts

type data T a b where
  MkT :: T a a

f :: T Int Bool -> Char
f x = case dataToTag# x of
         0# -> 'a'
         _ -> 'b'

Then it will trigger an assertion failure:

$ ~/Software/ghc3/_build/stage1/bin/ghc -O Bug.hs
[1 of 1] Compiling B                ( Bug.hs, Bug.o )

<no location info>: error:
    ASSERT failed!
  CallStack (from HasCallStack):
    assert, called at compiler/GHC/Core/DataCon.hs:1677:23 in ghc:GHC.Core.DataCon

The problem is the transformation:

Note [caseRules for dataToTag]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See also Note [dataToTag# magic].

We want to transform
  case dataToTag x of
    DEFAULT -> e1
    1# -> e2
into
  case x of
    DEFAULT -> e1
    (:) _ _ -> e2

which can be disabled with:

diff --git a/compiler/GHC/Core/Opt/ConstantFold.hs b/compiler/GHC/Core/Opt/ConstantFold.hs
index 7ace3124e9..ebf038c05c 100644
--- a/compiler/GHC/Core/Opt/ConstantFold.hs
+++ b/compiler/GHC/Core/Opt/ConstantFold.hs
@@ -55,7 +55,7 @@ import GHC.Core.TyCo.Compare( eqType )
 import GHC.Core.TyCon
    ( tyConDataCons_maybe, isAlgTyCon, isEnumerationTyCon
    , isNewTyCon, tyConDataCons
-   , tyConFamilySize )
+   , tyConFamilySize, isTypeDataTyCon )
 import GHC.Core.Map.Expr ( eqCoreExpr )
 
 import GHC.Builtin.PrimOps ( PrimOp(..), tagToEnumKey )
@@ -3188,6 +3188,7 @@ caseRules _ (App (App (Var f) (Type ty)) v)       -- dataToTag x
   | Just DataToTagOp <- isPrimOpId_maybe f
   , Just (tc, _) <- tcSplitTyConApp_maybe ty
   , isAlgTyCon tc
+  , not (isTypeDataTyCon tc)
   = Just (v, tx_con_dtt ty
            , \v -> App (App (Var f) (Type ty)) (Var v))
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information