Skip to content

Two missing representation-polymorphism checks for inferred patterns

I've spotted two problematic uses of tcInfer where we aren't careful with representation-polymorphism:

  1. GHC.Tc.Gen.Path.tcInferPat in which we call tc_lpat without providing a guarantee that exp_ty is an ExpSigmaTypeFRR.
  2. GHC.Tc.Gen.Bind.tcLhs (PatBind ..) in which we call tcLetPat with no assurance that exp_ty is an ExpSigmaTypeFRR.

Here's a program that causes a crash with (1):

type R :: RuntimeRep
type family R where {}

type T :: TYPE R
type family T where {}

pattern S a = (a :: T)
panic! (the 'impossible' happened)
  GHC version 9.3.20220316:
        isUnliftedType
  T :: TYPE R
  Call stack:
      CallStack (from HasCallStack):
        callStackDoc, called at compiler\\GHC\\Utils\\Panic.hs:182:37 in ghc:GHC.Utils.Panic
        pprPanic, called at compiler\GHC\Core\Type.hs:2476:7 in ghc:GHC.Core.Type
        isUnliftedType, called at compiler\\GHC\\Tc\\TyCl\\PatSyn.hs:874:31 in ghc:GHC.Tc.TyCl.PatSyn

For (2), I haven't managed to get a panic from the following program (with the same type families as above)

(x :: T) = x

because we do get a representation-polymorphism error for a representation-polymorphic binder, but the typechecker does end up handling a pattern which does not have a fixed runtime representation, which is assuredly bad news.

I'm not sure how to go about fixing this. Perhaps InferResult could store whether it must be filled with a type with a fixed runtime representation, and when it comes time to filling one of these we check whether the type we are about to put in has a fixed runtime representation, and if not we perform a representation polymorphism check and cast the type using the coercion before filling? @rae @simonpj Any suggestions?

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