Two missing representation-polymorphism checks for inferred patterns
I've spotted two problematic uses of tcInfer
where we aren't careful with representation-polymorphism:
-
GHC.Tc.Gen.Path.tcInferPat
in which we calltc_lpat
without providing a guarantee thatexp_ty
is anExpSigmaTypeFRR
. -
GHC.Tc.Gen.Bind.tcLhs (PatBind ..)
in which we calltcLetPat
with no assurance thatexp_ty
is anExpSigmaTypeFRR
.
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?