A nice pattern synonym record field became naughty in GHC 9.6
Consider the following:
pattern N1 :: forall a. () => forall. () => a -> Any
pattern N1 { fld1 } <- ( unsafeCoerce -> fld1 )
where N1 = unsafeCoerce
pattern N2 :: forall. () => forall a. () => a -> Any
pattern N2 { fld2 } <- ( unsafeCoerce -> fld2 )
where N2 = unsafeCoerce
test1, test2 :: forall a. Any -> a
test1 = fld1
test2 = fld2
We should accept test1
, and reject test2
because we have an existential variable escaping its scope (fld2
is a "naughty record selector").
This is indeed what happens on GHC 9.4. However, on GHC 9.6, test1
is rejected as it considers fld1
to also be a naughty record selector.
This regression showed up when compiling the cleff
package, which contains the following:
pattern Any :: forall a. a -> Any
pattern Any {fromAny} <- (unsafeCoerce -> fromAny)
where Any = unsafeCoerce
src/Cleff/Internal/Monad.hs:46:26: error: [GHC-55876]
• Cannot use record selector ‘fromAny’ as a function due to escaped type variables
• In the first argument of ‘($)’, namely ‘fromAny’
In the expression:
fromAny $ Vec.lookup (unHandlerPtr (Rec.index @e re)) mem
In an equation for ‘readEnv’:
readEnv (Env _ re mem)
= fromAny $ Vec.lookup (unHandlerPtr (Rec.index @e re)) mem
Suggested fix: Use pattern-matching syntax instead
|
46 | readEnv (Env _ re mem) = fromAny $ Vec.lookup (unHandlerPtr (Rec.index @e re)) mem
|