
#10867: Primop types should not mention () -------------------------------------+------------------------------------- Reporter: simonpj | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by simonpj): * cc: core-libraries-committee (added) Comment: Simon, can you help a little more? I'm also copying the core libraries committee, since I propose an API change for weak-pointer primpops. The type `Weak#` and primop `mkWeak#`, are declared thus: {{{ primtype Weak# b primop MkWeakOp "mkWeak#" GenPrimOp o -> b -> c -> State# RealWorld -> (# State# RealWorld, Weak# b #) }}} I think `c` is the finalizer. This type suggests that you can put any old value in for the finalizer, which seems unlikely. '''In fact it can easily lead to a seg-fault (with no use of `unsafeCoerce` by building a weak pointer whose "finaliser" with the wrong type.''' Then the primop `finalizeWeak#` is declared thus: {{{ primop FinalizeWeakOp "finalizeWeak#" GenPrimOp Weak# a -> State# RealWorld -> (# State# RealWorld , Int# , State# RealWorld -> (# State# RealWorld, () #) #) }}} I believe the following: * The third argument to `mkWeak#` is returned as the third component of the result to `finalizeWeak#`, but is otherwise totally un-examined by the RTS. Is that true? In that case it would be far, far better to declare them like this: {{{ primtype Weak# value finalizer primop MkWeakOp "mkWeak#" GenPrimOp key -> value -> finalizer -> State# RealWorld -> (# State# RealWorld, Weak# payload finalizer #) }}} So `Weak#` gets two type parameters, the second recording the type of the "finaliser". All the RTS promises to do is to cough up the "finalizer" when the `key` dies. Now in `GHC.Weak` we can declare `Weak` thus: {{{ data Weak v = Weak (Weak# v) (IO ()) }}} That is `Weak` specialises the "any only value can be a finaliser" API offered by `Weak#` to "the finaliser is a vlaue of type `IO ()`" API for `Weak`. Doing this would eliminate an unpleasant potential source of seg-faults; and it would eliminate one of the two unpleasant uses of `()` in `primpops.txt.pp`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10867#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler