Opened 2 years ago

Closed 7 months ago

#7643 closed bug (fixed)

Kind application error

Reported by: gmainland Owned by: simonpj
Priority: normal Milestone: 7.10.1
Component: Compiler (Type checker) Version: 7.6.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case: typecheck/should_compile/T7643
Blocked By: Blocking:
Related Tickets: #7354, #8355 Differential Revisions:

Description

Compiling the attached program with -dcore-lint fails. This failure is a reduced version of code taken from the primitive package, version 0.5.0.1.

To see the failure:

ghc -dcore-lint --make Main.hs

The failure does not occur with GHC 7.4.

Attachments (1)

Main.hs (1.1 KB) - added by gmainland 2 years ago.

Download all attachments as: .zip

Change History (10)

Changed 2 years ago by gmainland

comment:1 Changed 2 years ago by shachaf

I reduced the test case a bit:

{-# LANGUAGE MagicHash, TypeFamilies #-}

module T7643 where

import GHC.Exts

type family T
type instance T = RealWorld

foo :: () -> State# T
foo _ = unsafeCoerce# realWorld#

The unsafeCoerce#ed type actually matches -- but GHC has a problem with State# RealWorld ~ State# T (this isn't specific to State# or RealWorld -- unboxed tuples etc. work too. The issue is with the kinds).

This seems to be a variety of #7354, but it's still broken in HEAD because of the kind issue.

comment:2 Changed 2 years ago by simonpj

  • difficulty set to Unknown

There really is an underlying issue here, about how inference interacts with sub-kinding. Sigh.

It is shown up here becuase you are doing unsafeCoerce# on an unlifted type, which is a deeply dangerous thing to do. Better to do it on a lifted type.

Try using this definition of setIntByteArray#, which actually uses one fewer unsafeCoerce# calls:

setIntByteArray# :: MutableByteArray# s -> Int# -> Int# -> Int -> State# s -> State# s
setIntByteArray# arr# i# n# (I# x#) s#  =
    case unsafeCoerce# (internal (setIntArray# arr# i# n# x#)) s# of
      (# s1#, _ #) -> s1#

That makes the attached Main.hs compile fine.

Don't close the ticket though. The underlying problem (dark corner though it is) remains.

Simon

comment:3 Changed 2 years ago by gmainland

Just for reference...

This bug was tickled by a change introduced in revision 776368 of the
primitive library. This revision added the following method to the
Data.Primitive.Types.Prim type class:

setByteArray# :: MutableByteArray# s -> Int# -> Int# -> a -> State# s -> State# s

Instances for primitive types define this method using FFI imports. For example,
the instance for Int# uses the following FFI import:

foreign import ccall unsafe "primitive-memops.h hsprimitive_memset_Word"
  setIntArray# :: MutableByteArray# s -> Int# -> Int# -> Int# -> IO ()

Because the FFI import is in IO, it needs to be cast from MutableByteArray# s -> Int# -> Int# -> Int# -> IO ()
to MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> (# State# s, () #).
This is currently done as follows:

setByteArray# arr# i# n# (I# x#) s# =
    case internal (setIntArray# arr# i# n# x#) (unsafeCoerce# s#) of
        { (# s1#, _ #) -> unsafeCoerce# s1# }

For reference, internal is defined like this:

class Monad m => PrimMonad m where
  -- | State token type
  type PrimState m

  -- | Execute a primitive operation
  primitive :: (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a

  -- | Expose the internal structure of the monad
  internal :: m a -> State# (PrimState m) -> (# State# (PrimState m), a #)
instance PrimMonad IO where
  type PrimState IO = RealWorld
  primitive = IO
  internal (IO p) = p
  {-# INLINE primitive #-}
  {-# INLINE internal #-}

Indeed, Simon's fix keeps us safely in the land of kind *.

comment:4 Changed 2 years ago by igloo

  • Milestone set to 7.8.1
  • Owner set to simonpj

comment:5 Changed 22 months ago by hvr

#8355 has been marked as duplicate of this ticket

comment:6 Changed 14 months ago by thoughtpolice

  • Milestone changed from 7.8.3 to 7.10.1

Moving to 7.10.1

comment:7 Changed 8 months ago by thomie

The example from the description, as well as the simpler testcase from comment:1, both compile fine with ghc 7.8.1 and higher:

$ ghc-7.8.1 -dcore-lint -package primitive --make Main.hs

(without -package primitive I'm getting "undefined reference to hsprimitive_memset_Word" errors)

A regression test should probably be added.

comment:8 Changed 7 months ago by Richard Eisenberg <eir@…>

In 63d2adaef999258d874a760591e9c9ec3d75aeaf/ghc:

Test #7643 in typecheck/should_compile/T7643.

comment:9 Changed 7 months ago by goldfire

  • Resolution set to fixed
  • Status changed from new to closed
  • Test Case set to typecheck/should_compile/T7643
Note: See TracTickets for help on using tickets.