Skip to content

GHC 9.4: wrong promotion semantics

Summary

Under GHC 9.4, only one of the two seemingly equivalent codes is accepted and the other is rejected. Both codes are accepted by GHC 9.2.

I'm not sure if it is expected breaking change or regression, but I report it just in case.

Steps to reproduce

Compile the following code with GHC 9.4.2.

{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- {-# LANGUAGE TypeFamilies #-}

module Test where

import Control.Monad.Primitive -- primitive-0.7.4.0
import Data.Kind
import Data.Primitive.MutVar -- primitive-0.7.4.0

class Monad m => New a m where
  new :: m a

class Monad m => Add a m e | a -> e where
  add :: a -> e -> m ()

data T (m :: Type -> Type) = T

instance PrimMonad m => New (T m) m where
  new = return T

instance PrimMonad m => Add (T m) m Int where
  add _ _ = return ()

test1 :: forall m. PrimMonad m => m ()
test1 = do
  ref <- newMutVar (undefined :: T m)
  let g () = do
        t <- new
        add t (0 :: Int)
        writeMutVar ref t
  g ()

test2 :: forall m. PrimMonad m => m ()
test2 = do
  (ref :: MutVar (PrimState m) (T m)) <- newMutVar undefined
  let g () = do
        t <- new
        add t (0 :: Int)
        writeMutVar ref t
  g ()

GHC 9.2.3 accepts both test1 and test2. But GHC 9.4.2 only accepts test1 and rejects test2 with the following error:

src/Test.hs:44:9: error:
    • Could not deduce (Add (T m) m1 Int) arising from a use of ‘add’
      from the context: PrimMonad m
        bound by the type signature for:
                   test2 :: forall (m :: * -> *). PrimMonad m => m ()
        at src/Test.hs:39:1-38
      or from: (PrimState m1 ~ PrimState m, New (T m) m1, PrimMonad m1)
        bound by the inferred type of
                   g :: (PrimState m1 ~ PrimState m, New (T m) m1, PrimMonad m1) =>
                        () -> m1 ()
        at src/Test.hs:(42,7)-(45,25)
    • In a stmt of a 'do' block: add t (0 :: Int)
      In the expression:
        do t <- new
           add t (0 :: Int)
           writeMutVar ref t
      In an equation for ‘g’:
          g ()
            = do t <- new
                 add t (0 :: Int)
                 writeMutVar ref t
   |
44 |         add t (0 :: Int)
   |         ^^^

Also, the error disappears if I enable TypeFamilies extension.

Expected behavior

As ref <- newMutVar (undefined :: T m) and (ref :: MutVar (PrimState m) (T m)) <- newMutVar undefined seem equivalent to me, I think both should be accepted or both should be rejected.

Environment

  • GHC version used: 9.4.2

Optional:

  • Operating System: macOS Big Sur
  • System Architecture: aarch64
Edited by Simon Peyton Jones
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information