Opened 11 years ago

Closed 8 years ago

#3008 closed bug (fixed)

Strange behavior when using newtyped version of IO monad in FFI import declarations

Reported by: waern Owned by: igloo
Priority: normal Milestone: 7.4.1
Component: Compiler (FFI) Version: 6.10.1
Keywords: FFI Cc: david.waern@…
Operating System: Linux Architecture: x86_64 (amd64)
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


Take a look at these two modules:


module A (GL) where

import Control.Monad
import Control.Monad.Trans

newtype GL a = GL (IO a) deriving (Functor, Monad, MonadIO)


module B where

import A

foreign import CALLCONV unsafe "glFlush" flush :: GL ()

Now, compile them with optimizations:

[david@alonzo temp]$ $HOME/ghc-6.10.1/bin/ghc A.hs B.hs -XGeneralizedNewtypeDeriving -XForeignFunctionInterface -DCALLCONV=ccall -XCPP -O
compilation IS NOT required
compilation IS NOT required
A.o:(.text+0x8e): undefined reference to `mtlzm1zi1zi0zi2_ControlziMonadziTrans_ZCDMonadIO_con_info'
A.o:(.text+0x237): undefined reference to `__stginit_mtlzm1zi1zi0zi2_ControlziMonadziTrans_'
B.o:(.text+0x1e): undefined reference to `glFlush'
/home/david/ghc-6.10.1//lib/ghc-6.10.1/libHSrts.a(Main.o): In function `real_main':
Main.c:(.text+0x12): undefined reference to `__stginit_ZCMain'
Main.c:(.text+0x26): undefined reference to `ZCMain_main_closure'
collect2: ld returnerade avslutningsstatus 1

It's OK - we pass the typechecking phase.

Now, see what happens when we compile without -O:

[david@alonzo temp]$ rm -f *.hi *.o
[david@alonzo temp]$ $HOME/ghc-6.10.1/bin/ghc A.hs B.hs -XGeneralizedNewtypeDeriving -XForeignFunctionInterface -DCALLCONV=ccall -XCPP

    Unacceptable result type in foreign declaration: GL ()
    When checking declaration:
        foreign import ccall unsafe "static  &glFlush" flush :: GL ()

Putting everything into one single module makes the type error go away completely (that is, also when compiling without -O).

Something strange must be going on.

Change History (14)

comment:1 Changed 11 years ago by waern

Please disregard the COMPILATION IS NOT REQUIRED lines in the first console output. I just ran the exact same command twice.

comment:2 Changed 11 years ago by simonpj

difficulty: Unknown

Excellent report.

The real culprit is in the FFI spec: see

Until that thread is resolved, you can work around this bug by exporting GL(..). Indeed, if my proposal is accepted, you'll be forced to do that.


comment:3 Changed 11 years ago by igloo

Milestone: 6.12 branch

comment:4 Changed 11 years ago by simonpj

Milestone: 6.12 branch6.12.1

Let's try to resolve this for 6.21.1


comment:5 Changed 10 years ago by simonpj

Owner: set to chak

The bug in the FFI spec is fixed in the 2009 Haskell Prime iteration. Manuel says that now we need to

  • Fix GHC to refuse to transparently marshal opaque newtypes
  • Fix the FFI libraries not to expect GHC to do so

Moreover he generously says "I'm happy to apply those changes, but it won't be right now, as I have a backlog of things to get through."

So I'll assign this ticket to you, Manuel. Thanks.


comment:6 Changed 10 years ago by igloo

Type of failure: None/Unknown

comment:7 Changed 9 years ago by igloo


comment:8 Changed 9 years ago by igloo


comment:9 Changed 9 years ago by simonmar

Component: CompilerCompiler (FFI)

comment:10 Changed 8 years ago by igloo

Owner: changed from chak to igloo

comment:11 Changed 8 years ago by igloo


comment:12 Changed 8 years ago by igloo@…

commit 4027a7ddea293c539626b17b6b434bd4f0860f80

Author: Ian Lynagh <>
Date:   Sun Sep 11 20:53:18 2011 +0100

    When checking FFI types are IO, don't look through abstract newtypes; #3008

 compiler/typecheck/TcForeign.lhs |   53 +++++++++++++++++++++++++++++++++----
 1 files changed, 47 insertions(+), 6 deletions(-)

comment:13 Changed 8 years ago by igloo@…

commit 5b988961338f73af5790bfd365ca79c858249cea

Author: Ian Lynagh <>
Date:   Fri Sep 30 21:57:53 2011 +0100

    Handle newtypes and type functions correctly in FFI types; fixes #3008
    You can now use type functions in FFI types.
    Newtypes are now only looked through if the constructor is in scope.

 compiler/deSugar/DsCCall.lhs     |    4 +-
 compiler/deSugar/DsForeign.lhs   |   82 +++++++++++---------
 compiler/deSugar/DsMeta.hs       |    2 +-
 compiler/hsSyn/Convert.lhs       |    4 +-
 compiler/hsSyn/HsDecls.lhs       |   32 +++++++-
 compiler/hsSyn/HsUtils.lhs       |    2 +-
 compiler/parser/RdrHsSyn.lhs     |    6 +-
 compiler/rename/RnNames.lhs      |    2 +-
 compiler/rename/RnSource.lhs     |    8 +-
 compiler/typecheck/TcForeign.lhs |  160 +++++++++++++++++++++++++-------------
 compiler/typecheck/TcHsSyn.lhs   |    4 +-
 compiler/typecheck/TcType.lhs    |   50 ++++--------
 compiler/types/FamInstEnv.lhs    |    2 +-
 utils/ghctags/Main.hs            |    2 +-
 14 files changed, 214 insertions(+), 146 deletions(-)

comment:14 Changed 8 years ago by igloo

Resolution: fixed
Status: newclosed


Note: See TracTickets for help on using tickets.