Skip to content

Extremely confused type error

Summary

Accidentally using an ArrayArray# operation with the wrong type leads to a truly bizarre error message referencing a type that has nothing to do with what's going on. The result is extremely delicate, depending on whether an import is qualified.

Steps to reproduce

dfeuer@squirrel:~/src> ghc-9.6 --version
The Glorious Glasgow Haskell Compilation System, version 9.6.0.20230111
{-# language CPP #-}
{-# language MagicHash #-}
{-# language UnboxedTuples #-}
{-# language RoleAnnotations #-}
{-# language UnliftedNewtypes #-}
{-# language KindSignatures #-}
{-# language DataKinds #-}

module ExtremeConfusion where

import Data.Coerce (coerce)
import GHC.Exts ( Int#, State#, ArrayArray#, MutableArrayArray#
                , UnliftedType)
import qualified GHC.Exts as Exts

newtype UnliftedArray# (a :: UnliftedType) = UnliftedArray# ArrayArray#
type role UnliftedArray# representational

newtype MutableUnliftedArray# s (a :: UnliftedType) = MutableUnliftedArray# (MutableArrayArray# s)
type role MutableUnliftedArray# nominal representational

newUnliftedArray# :: Int# -> a -> State# s -> (# State# s, MutableUnliftedArray# s a #)
newUnliftedArray# sz a s = coerce (Exts.newArray# sz a s)

This gives me the error

ExtremeConfusion.hs:23:28: error: [GHC-10283]
    • Couldn't match representation of type ‘a’
                               with that of ‘Exts.ByteArray#’
        arising from a use of ‘coerce’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          newUnliftedArray# :: forall (a :: UnliftedType) s.
                               Int# -> a -> State# s -> (# State# s, MutableUnliftedArray# s a #)
        at ExtremeConfusion.hs:22:1-87
    • In the expression: coerce (Exts.newArray# sz a s)
      In an equation for ‘newUnliftedArray#’:
          newUnliftedArray# sz a s = coerce (Exts.newArray# sz a s)
    • Relevant bindings include
        a :: a (bound at ExtremeConfusion.hs:23:22)
        newUnliftedArray# :: Int#
                             -> a -> State# s -> (# State# s, MutableUnliftedArray# s a #)
          (bound at ExtremeConfusion.hs:23:1)
   |
23 | newUnliftedArray# sz a s = coerce (Exts.newArray# sz a s)
   |                            ^^^^^^

Expected behavior

If I add newArray# to the list of imports from GHC.Exts and use it unqualified, I get a much nicer message:

ExtremeConfusion.hs:23:28: error: [GHC-18872]
    • Couldn't match representation of type: MutableArrayArray# s
                               with that of: GHC.Prim.MutableArray# s a
        arising from a use of ‘coerce’
        The data constructor ‘GHC.ArrayArray.MutableArrayArray#’
          of newtype ‘MutableArrayArray#’ is not in scope
    • In the expression: coerce (newArray# sz a s)
      In an equation for ‘newUnliftedArray#’:
          newUnliftedArray# sz a s = coerce (newArray# sz a s)
    • Relevant bindings include
        s :: State# s (bound at ExtremeConfusion.hs:23:24)
        a :: a (bound at ExtremeConfusion.hs:23:22)
        newUnliftedArray# :: Int#
                             -> a -> State# s -> (# State# s, MutableUnliftedArray# s a #)
          (bound at ExtremeConfusion.hs:23:1)
   |
23 | newUnliftedArray# sz a s = coerce (newArray# sz a s)
   |                            ^^^^^^

I would love to get this message regardless. If that's not doable, I suspect the situation can at least be ameliorated by using Any instead of ByteArray# in the definition of ArrayArray#.

Environment

  • GHC version used: 9.6

Optional:

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