Skip to content

GHC 9.2.1 typechecking regression with RankNTypes and TemplateHaskell

While porting some code over to use GHC 9.2.1, I noticed a typechecking regression that doesn't appear to be explained in the 9.2.1 release notes. Here is a minimal example:

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
module Bug where

data Foo = MkFoo (forall a. a -> a)

worksOnAllGHCs1 :: Foo
worksOnAllGHCs1 = MkFoo (\x -> x)

worksOnAllGHCs2 :: Foo
worksOnAllGHCs2 = MkFoo $ \x -> x

worksOnAllGHCs3 :: Foo
worksOnAllGHCs3 = $([| MkFoo |]) (\x -> x)

doesn'tWorkOnGHC9'2 :: Foo
doesn'tWorkOnGHC9'2 = $([| MkFoo |]) $ \x -> x

All four of these top-level functions will typecheck on GHC 9.0.2 and earlier. On GHC 9.2.1 and HEAD, worksOnAllGHCs{1,2,3} functions will typecheck, but the doesn'tWorkOnGHC9'2 function will not typecheck:

$ ghc-9.2.1 Bug.hs
[1 of 1] Compiling Bug              ( Bug.hs, Bug.o, Bug.dyn_o )

Bug.hs:17:24: error:
    • Couldn't match type: forall a. a -> a
                     with: p0 -> p0
      Expected: (p0 -> p0) -> Foo
        Actual: (forall a. a -> a) -> Foo
    • In the first argument of ‘($)’, namely ‘(MkFoo)’
      In the expression: (MkFoo) $ \ x -> x
      In an equation for ‘doesn'tWorkOnGHC9'2’:
          doesn'tWorkOnGHC9'2 = (MkFoo) $ \ x -> x
   |
17 | doesn'tWorkOnGHC9'2 = $([| MkFoo |]) $ \x -> x
   |                        ^^^^^^^^^^^^^

I'm unclear why using a Template Haskell splice would affect typechecking like this, so I believe this is a bug.

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