Skip to content

ConstPtr loses constness when wrapped in newtype

Consider the following program:

{-# LANGUAGE CApiFFI #-}

module Repro where

import Foreign.C
import Foreign.C.ConstPtr

newtype BadConstPtr a = BadConstPtr (ConstPtr a)

foreign import capi unsafe "foo" c_foo :: IO (ConstPtr CChar)

The generated C stub would contain

const char* ghczuwrapperZC0ZCmainZCReproZCfoo(void) {return foo();}

However, if c_foo is changed to return IO (BadConstPtr CChar), then the C stub becomes

char* ghczuwrapperZC0ZCmainZCReproZCfoo(void) {return foo();}

Whether or not the constness is robust against newtypes is not mentioned either in #22043 (closed) or Foreign.C.ConstPtr haddock. If we decide the constness is only effective when ConstPtr is used verbatim, that's fine, but it should be documented; otherwise it's actually pretty easy to fix the issue, just add logic to constQual in GHC.HsToCore.Foreign.C to expand type synonyms and newtypes.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information