[GHC] #14125: Bogus unacceptable type in foreign declaration.
GHC
ghc-devs at haskell.org
Wed Aug 16 06:11:36 UTC 2017
#14125: Bogus unacceptable type in foreign declaration.
-------------------------------------+-------------------------------------
Reporter: winter | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.2.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Description changed by winter:
Old description:
> I'm try to abstract FFI return type so that different errno scheme can
> work together, namely i create such a class:
>
> {{{
> class Integral (IOErrno r) => IOReturn r where
> -- | The errno type associated with 'r'
> data IOErrno r :: *
> -- | Is this return value indicate an error?
> isError :: Integral a => r a -> Bool
> -- | How can i get a errno then?
> getErrno :: Integral a => r a -> IO (IOErrno r)
> -- | Is this errno indicate interrupted blocking call?
> isInterrupt :: IOErrno r -> Bool
> -- | Is this errno indicate no data on a non-blocking device?
> isBlock :: IOErrno r -> Bool
> -- | OK, i want my return value if no errno.
> getReturn :: Integral a => r a -> a
> -- | Read the errno name for me.
> nameErrno :: IOErrno r -> IO String
> -- | Read the errno description for me.
> descErrno :: IOErrno r -> IO String
> }}}
>
> But when i'm try to defining instance for it, such as a standard unix
> like:
>
> {{{
> newtype UnixReturn a = UnixReturn a
> deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show,
> FiniteBits, Bits, Storable)
>
> instance IOReturn UnixReturn where
> newtype IOErrno UnixReturn = UnixErrno CInt
> deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real,
> Show, FiniteBits, Bits, Storable)
> isError (UnixReturn r) = r == (-1)
> isInterrupt e = e == eINTR
> isBlock e = e == eAGAIN || e == eWOULDBLOCK
> getErrno _ = get_errno
> getReturn (UnixReturn r) = r
> nameErrno = return . nameUnixErrno
> descErrno e = strerror e >>= peekCString
>
> eINTR = UnixErrno (CONST_EINTR)
> eWOULDBLOCK = UnixErrno (CONST_EWOULDBLOCK)
> ...
>
> foreign import ccall unsafe "string.h" strerror :: IOErrno UnixReturn ->
> IO CString
> foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO
> (IOErrno UnixReturn)
> }}}
>
> I got a error on GHC 8.2:
>
> {{{
> System/IO/Exception.hs:282:1: error:
> • Unacceptable argument type in foreign declaration:
> ‘IOErrno UnixReturn’ cannot be marshalled in a foreign call
> • When checking declaration:
> foreign import ccall unsafe "string.h" strerror
> :: IOErrno UnixReturn -> IO CString
> |
> 282 | foreign import ccall unsafe "string.h" strerror :: IOErrno
> UnixReturn -> IO CString
> |
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> System/IO/Exception.hs:283:1: error:
> • Unacceptable result type in foreign declaration:
> ‘IOErrno UnixReturn’ cannot be marshalled in a foreign call
> • When checking declaration:
> foreign import ccall unsafe "HsBase.h __hscore_get_errno"
> get_errno
> :: IO (IOErrno UnixReturn)
> |
> 283 | foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno
> :: IO (IOErrno UnixReturn)
> |
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> }}}
>
> And at every place i want mark my FFI return got this error too. e.g.
> following code compiles without problem on GHC < 8.2 (Note that the type
> and constructor are both available):
>
> {{{
>
> foreign import CALLCONV unsafe "HsNet.h recv"
> c_recv :: CInt -> Ptr Word8 -> CSize -> CInt -> IO (UnixReturn
> CSsize)
> }}}
>
> But on GHC 8.2 a `Unacceptable result type in foreign declaration` is
> emitted. And I think it's a regression.
New description:
I'm trying to abstract FFI return type so that different errno scheme can
work together, namely i create such a class:
{{{
class Integral (IOErrno r) => IOReturn r where
-- | The errno type associated with 'r'
data IOErrno r :: *
-- | Is this return value indicate an error?
isError :: Integral a => r a -> Bool
-- | How can i get a errno then?
getErrno :: Integral a => r a -> IO (IOErrno r)
-- | Is this errno indicate interrupted blocking call?
isInterrupt :: IOErrno r -> Bool
-- | Is this errno indicate no data on a non-blocking device?
isBlock :: IOErrno r -> Bool
-- | OK, i want my return value if no errno.
getReturn :: Integral a => r a -> a
-- | Read the errno name for me.
nameErrno :: IOErrno r -> IO String
-- | Read the errno description for me.
descErrno :: IOErrno r -> IO String
}}}
But when i'm try to defining instance for it, such as a standard unix
like:
{{{
newtype UnixReturn a = UnixReturn a
deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show,
FiniteBits, Bits, Storable)
instance IOReturn UnixReturn where
newtype IOErrno UnixReturn = UnixErrno CInt
deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show,
FiniteBits, Bits, Storable)
isError (UnixReturn r) = r == (-1)
isInterrupt e = e == eINTR
isBlock e = e == eAGAIN || e == eWOULDBLOCK
getErrno _ = get_errno
getReturn (UnixReturn r) = r
nameErrno = return . nameUnixErrno
descErrno e = strerror e >>= peekCString
eINTR = UnixErrno (CONST_EINTR)
eWOULDBLOCK = UnixErrno (CONST_EWOULDBLOCK)
...
foreign import ccall unsafe "string.h" strerror :: IOErrno UnixReturn ->
IO CString
foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno :: IO
(IOErrno UnixReturn)
}}}
I got a error on GHC 8.2:
{{{
System/IO/Exception.hs:282:1: error:
• Unacceptable argument type in foreign declaration:
‘IOErrno UnixReturn’ cannot be marshalled in a foreign call
• When checking declaration:
foreign import ccall unsafe "string.h" strerror
:: IOErrno UnixReturn -> IO CString
|
282 | foreign import ccall unsafe "string.h" strerror :: IOErrno
UnixReturn -> IO CString
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
System/IO/Exception.hs:283:1: error:
• Unacceptable result type in foreign declaration:
‘IOErrno UnixReturn’ cannot be marshalled in a foreign call
• When checking declaration:
foreign import ccall unsafe "HsBase.h __hscore_get_errno"
get_errno
:: IO (IOErrno UnixReturn)
|
283 | foreign import ccall unsafe "HsBase.h __hscore_get_errno" get_errno
:: IO (IOErrno UnixReturn)
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}}}
And at every place i want mark my FFI return got this error too. e.g.
following code compiles without problem on GHC < 8.2 (Note that the type
and constructor are both available):
{{{
foreign import CALLCONV unsafe "HsNet.h recv"
c_recv :: CInt -> Ptr Word8 -> CSize -> CInt -> IO (UnixReturn CSsize)
}}}
But on GHC 8.2 a `Unacceptable result type in foreign declaration` is
emitted. And I think it's a regression.
--
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14125#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list