[GHC] #9197: FFI types should be usable in foreign import decls without revealing representations
GHC
ghc-devs at haskell.org
Wed Jun 11 22:40:31 UTC 2014
#9197: FFI types should be usable in foreign import decls without revealing
representations
------------------------------------+-------------------------------------
Reporter: duncan | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (FFI) | Version: 7.8.2
Keywords: | Operating System: Unknown/Multiple
Architecture: Unknown/Multiple | Type of failure: None/Unknown
Difficulty: Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: |
------------------------------------+-------------------------------------
This is another go at #5529 but with, we hope, clearer and better
arguments.
The original FFI spec defined a whole bunch of FFI types that are
acceptable in foreign import/export declarations, including lots of things
defined in Foreign.C.*. The original spec defined these as abstract types.
The original FFI spec also allowed for automatic newtype unwrapping in
foreign declarations. In 2009 Simon PJ [pointed out
http://www.haskell.org/pipermail/haskell-prime/2009-February/002726.html]
that automatic newtype unwrapping breaks abstraction for user-defined
types. In that same thread [I suggested http://www.haskell.org/pipermail
/haskell-prime/2009-February/002727.html] that the breaking of abstraction
for user types should be fixed, but that the intent of the FFI spec to
have the FFI types as abstract should be kept. Manuel [argued
http://www.haskell.org/pipermail/haskell-prime/2009-February/002729.html]
that the C FFI types should actually not be abstract, and thus no special
case for them was needed.
On the basis of that thread the decision in #5529 was to only allow FFI
decls to look through newtypes when the constructor is available, plus for
a few types GHC uses to represent the C FFI types, like Int32 etc.
Johan and I want to argue that it still makes sense as a user to not be
forced into knowing the representation of the C FFI types to be able to
use them. This is similar to but slightly weaker than the rationale of the
FFI spec originally making those types abstract. Manuels argument is
essentially that sometimes you need to know concrete types when those can
change, e.g. CInt might be Int32 or Int64 and you should be free to depend
on that difference.
Manuel's argument is fine when the "concrete" representation exists as yet
another portable type, as is the case for Int32. Of course we don't insist
that the representation for Int or Int32 be exposed, in large part because
they cannot have a Haskell implementation independent representation. The
important point is
Johan and I are defining/writing a portable low level ByteArray library
that could be considered alongside the FFI's definition of some of the
Foreign.* libraries: it defines and API for some low level types and
functions but different Haskell implementations will implement them
differently.
For GHC we implement `data ByteArray = BA ByteArray#`. We want to make
this an FFI type, in the same sense as the FFI spec defines the C types to
be FFI types. (You could consider our library as a Haskell extension and
implementations following this extension will support this type for FFI in
a similar way to the FFI spec). Of course for this implementation of
`ByteArray` the representation crosses the boundary into implementation
dependent, unlike the case for `newtype CInt = CInt Int32` where both are
still portable types.
So, we think the right thing to do is to again be able to declare certain
types (those defined in the FFI spec and its extensions) as being valid
types to use in FFI decls, without their constructors being available.
Thus users could choose to import `CInt` only (i.e. without its
constructor) and use it. We are not arguing against Manuel's point that
it's sometimes useful to not hide representations where that is possible
(like for CInt being an Int32 or 64). So we are not asking that the C FFI
types be made abstract again, just that it be possible to use them (and
our new type) as FFI types without user access to the constrctor.
For GHC, my suggestion for a reasonable way to do this is with a pragma.
The pragma would say that this single-constrcutor single-field newtype or
data is an FFI type, and that GHC may perform the usual newtype unwrapping
even when the constructor is not in scope at the FFI decl site. We would
then use this pragma on Int, Int32 and other core GHC (and FFI) types, and
also on the various C FFI types. And finally, we would also do this on our
ByteArray type.
Note that it would have to cover data as well as newtype to be able to
work for Int and other boxed wrappers of unboxed types.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9197>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list