Are you suggesting that it should have an "IO Int" result type to force sequencing?  Is this warranted?

Yes. This is warranted. That's why Foreign.Storable.peek has IO in its result type. On any CString with a finite lifetime, it is necessary to sequence any reads and writes, and IO is the way this is done in base. By contrast, on a CString that is both immutable and has an infinite lifetime, we do not need to sequence reads. What kinds of CStrings fit the bill? Only those backed by primitive string literals. So, for example, if you have:

    myString :: CString
    myString = Ptr "foobar"#

Since, myString is backed by something in the rodata section of a binary (meaning that it will never change and it will never be deallocated), then we do not care if reads get floated around. There are no functions in base for unsequenced reads, but in primitive, you'll find Data.Primitive.Ptr.indexOffPtr, which is unsequenced. So something like this would be ok:

    someOctet :: Word8
    someOctet = Data.Primitive.Ptr.indexOffPtr myString 3

The cstringLength# in GHC.CString is similar to indexOffPtr. In fact, it could be implemented using indexOffPtr. The reason that cstringLength# exists (and in base of all places) is so that a built-in rewrite rule perform this transformation:

    cstringLength "foobar"#
    ==>
    6#

This will eventually be used to great effect in bytestring. See https://github.com/haskell/bytestring/pull/191.

To get back to the original question, I think that any user-facing cstringLength
function should probably be:

    cstringLength :: CString -> IO Int

We need a separate FFI call that returns its result in IO to accomplish this. But
this just be done in base rather than ghc-prim. There are no interesting rewrite
rules that exist for such a function.

On Fri, Jan 22, 2021 at 3:31 PM Viktor Dukhovni <ietf-dane@dukhovni.org> wrote:
On Fri, Jan 22, 2021 at 08:45:54AM -0500, Andrew Martin wrote:

> x <- malloc ...
> memcpy ... copy a nul-terminated string into x
> let len = cstringLength x
> free x

Isn't this broadly true for general uses of CString?  Which is why we
have `withCString`:

    https://hackage.haskell.org/package/base-4.14.1.0/docs/Foreign-C-String.html#v:withCString

Is there any particularly different about the proposed `cstringLength`?

Are you suggesting that it should have an "IO Int" result type to force
sequencing?  Is this warranted?  Shouldn't users of CString (Ptr CChar)
be already aware of the liveness issue in general.

--
    Viktor.
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


--
-Andrew Thaddeus Martin