Skip to content

LitRubbish representation confusion

Currently we have

data Literal = ... | LitRubbish [PrimRep]

literalType (LitRubbish preps) = mkForAllTy a Inferred (mkTyVarTy a)
  where
    a = mkTemplateTyVar (tYPE (primRepsToRuntimeRep preps))

When we want to make a rubbish literal of type ty we do roughly

    LitRubbish (typeMonoPrimRep ty) `App` Type ty

which should be a well-kinded application. But alas the round-trip through [PrimRep] loses information. consider make a rubbish literal of type (# State# RealWorld, Int #).

  • Its typeMonoPrimRep is [LiftedRep]. That is, it is represented by a single pointer.
  • But primRepsToRuntimeRep applied to a singleton returns just that singleton, so we get LiftedRep back.
  • So the rubblish literal has type forall (a :: LiftedRep). a
  • That is applied to (# State# RealWorld, Int #), which an ill-kinded application.

Here's a reproducer:

f1 :: (# State# RealWorld, Int, Int #) -> Bool -> Int
f1 x True  = 1
f` x False = f1 x True

Another bad consequence of using [PrimRep] in LitRubbish is that for this function

f2 :: (# State# RealWorld, Int #) -> Bool -> Int
f2 x True = 1
f2 x False = f x True

we have an absent x whose [PrimRep] is [LiftedRep]. (Because that argument will ultimately be represented by a singlt pointer.) But that currently triggers this code in GHC.Core.Opt.WorkWrap.Utils.mk_absent_let:

mk_absent_let opts arg
  -- The lifted case: Bind 'absentError' for a nice panic message if we are
  -- wrong (like we were in #11126). See (1) in Note [Absent fillers]
  | Just [LiftedRep] <- mb_mono_prim_reps
  , not (isStrictDmd (idDemandInfo arg)) -- See (2) in Note [Absent fillers]
  = Just (Let (NonRec arg panic_rhs))

Yikes! We generate

  ww :: (# State# RealWorld, Int #) = absentError "blah"

But that type is unlifted.

This is all wrong.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information