
On Fri, Jun 15, 2007 at 06:46:11AM +0100, Duncan Coutts wrote:
On Fri, 2007-06-15 at 01:03 +0200, Udo Stenzel wrote:
The other occurence is:
| unsafeLiftIO :: (Buffer -> IO Buffer) -> Builder | unsafeLiftIO f = Builder $ \ k buf -> inlinePerformIO $ do | buf' <- f buf | return (k buf')
which might be safe, since 'f buf' cannot float out of the lambda which binds 'buf', but still, all this stuff is inlined, something constant might get plugged in the place of buf and the result might be floated out to give us an even harder to find Heisenbug.
I think this is safe because of the continuation k. In the Builder monoid, the continuation takes the place of the IO state token that gets single threaded through everything.
That's only safe if every function which passes an initial continuation (runBuilder etc) is NOINLINE - exactly the sort of global requirement that is far too easy to break if not documented. Stefan