haskell/primitive

Ptr operations have the wrong types

Opened this issue · 4 comments

For example,

copyPtrToMutablePrimArray
:: forall m a. (PrimMonad m, Prim a)	 
=> MutablePrimArray (PrimState m) a
-> Int
-> Ptr a
-> Int	
-> m ()	 

This accepts an arbitrary PrimState m, but that breaks referential transparency in ST, since the result of the ST calculation will depend on what's stored at that address at that time. All operations that dereference Ptr or Addr values should require PrimState m ~ RealWorld.

Okay, it's actually more subtle than that. Sometimes a Ptr is actually immutable, or treated as such, and copying from it in pure code is fine. But we currently also allow writing to a Ptr in pure code, which is utterly bogus.

But we currently also allow writing to a Ptr in pure code, which is utterly bogus.

Kind of. If you take the address of a pinned MutableByteArray that's scoped with s and then write to it, it's fine. Although that seems like a weird way to subvert the type system for no real reason. I'd be fine with a change banned writes to Ptr in general contexts, but as you point out, we definitely need to be able to copy, particularly because of the existence of primitive string literals and of the internals that back ByteString.

@andrewthad I think it would make sense to offer an s-scoped version of Ptr for that purpose, but I don't think it's at all reasonable to write to a Ptr in general ST s. I'd also very much prefer if the "in any state thread" functions that read from Ptrs had ImmutablePtr or similar in their names.

So I'd want a copyPtrToMutableByteArray that works only in RealWorld, and an otherwise identical copyImmutablePtrToMutableByteArray (or whatever name) that works in any state thread.