Description
Hello CLC :)
I would like to propose an addition to the Foreign data types: NonNullPtr
.
Rationale
Just like NonEmpty
, I need to express and enforce certain properties of my pointers in FFI.
While looking for such a thing on Hackage Search, I found @sergv's implementation, which he authorised me to submit for upstreaming to base
.
Implementation
This would be a newtype wrapper in the form of:
newtype NonNullPtr a = NonNullPtr (Ptr a)
deriving (a bunch of instances)
With the constructor not exported.
with the following API:
nonNull :: forall a. Ptr a -> Maybe (NonNullPtr a)
getNonNull :: forall (a :: Type). NonNullPtr a -> Ptr a
castPtr :: forall a b. NonNullPtr a -> NonNullPtr b
movePtr :: forall a b. NonNullPtr a -> Int -> NonNullPtr b
diffPtr :: forall a b. NonNullPtr a -> NonNullPtr b -> Int
alignPtr :: forall a. NonNullPtr a -> Word -> NonNullPtr a
alloca :: forall a b. Storable a => (NonNullPtr a -> IO b) -> IO b
allocaBytes :: forall a b. Word -> (NonNullPtr a -> IO b) -> IO b
allocaBytesAligned :: forall a b. Word -> Word -> (NonNullPtr a -> IO b) -> IO b
Due to name clashes, it would have to live in its own module: Foreign.NonNullPtr
. Qualified import would be heavily suggested in the documentation.
Breakage
From a search on Hackage and GitHub, only emacs-module
seems to implement such a thing. I do not expect much direct breakage from this addition.
Discussion
Making sure the pointer is always non null
I'm taking suggestions on that one. I'm not uncomfortable with drawing boundaries (after all, GHC is not a proof assistant), but if anyone's ever had to maintain that kind of invariant throughout a program, I am all ears for experience feedback.
emacs-module
for instance has an ASSERTIONS
CPP flag that would provoke an exception if the pointer is shown to be null
at run-time (https://github.com/sergv/emacs-module/blob/master/src/Data/Emacs/Module/NonNullPtr.hs#L29). This technique is most commonly found in C, although Haskell has a preference for returning Maybe
types.
On the C (:ocean:) side, the ARM toolchain manual reports:
__attribute__((nonnull)) function attribute
This function attribute specifies function parameters that are not supposed to be null pointers. This enables the compiler to generate a warning on encountering such a parameter.