[Haskell-cafe] dangerous inlinePerformIO in Data.Binary(?)

Udo Stenzel u.stenzel at web.de
Sun Jun 17 13:42:41 EDT 2007

Roberto Zunino wrote:
> Floating out (newBuffer defaultSize) as in
> | foo = newBuffer defaultSize
> |
> | toLazyByteString m = S.LPS $ inlinePerformIO $ do
> |     buf <- foo
> |     return (runBuilder (m `append` flush) (const []) buf)
> would still be safe, AFAICS. Floating out buf instead should be 
> prevented by the implicit RealWorld parameter.

That's actually what I meant, though I wouldn't describe it as "floating
out buf", since that's not the only thing that happens, and it is not
prevented.  Unfolding a bit gives you something like

| toLazyByteString m = S.LPS (
| 	case newBuffer defaultSize RealWorld# of { ( buf, world1 ) ->
| 	runBuilder blahblah buf } )

since the scrutinee of the case expression is constant, it can float

| bufAndWorld1 = newBuffer defaultSize RealWorld# 
| toLazyByteString m = S.LPS (
| 	case bufAndWorld1 of { (# buf, world1 #) ->
| 	runBuilder blahblah buf } )

and that is bad.  It might simplify even further, making the resulting
bug even harder to detect.  The only reason this doesn't happen with
unsafePerformIO or runST is that it is not inlined.  One of them even
has a comment in the GHC library sources to the effect that the NOINLINE
pragma was forgotten, which resulted in a subtle and ugly bug.

If you cannot in the long run tell everyone what you have been doing,
your doing was worthless.
                -- Erwin Schrödinger
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20070617/156d6759/attachment-0001.bin

More information about the Haskell-Cafe mailing list