Make unsafePerformIO lazy
authorsimonpj@microsoft <unknown>
Mon, 8 May 2006 14:25:07 +0000 (14:25 +0000)
committersimonpj@microsoft <unknown>
Mon, 8 May 2006 14:25:07 +0000 (14:25 +0000)
commit19dfd6fc5b4c1f09b4aee82874bcb179ed6cd0cc
treec12f27f5c920c498882097c97685af428350b902
parentb9756aa906e938841a289c23fd637f19a40f9c5f
Make unsafePerformIO lazy

The stricteness analyser used to have a HACK which ensured that NOINLNE things
were not strictness-analysed.  The reason was unsafePerformIO. Left to itself,
the strictness analyser would discover this strictness for unsafePerformIO:
unsafePerformIO:  C(U(AV))
But then consider this sub-expression
unsafePerformIO (\s -> let r = f x in
       case writeIORef v r s of (# s1, _ #) ->
       (# s1, r #)
The strictness analyser will now find that r is sure to be eval'd,
and may then hoist it out.  This makes tests/lib/should_run/memo002
deadlock.

Solving this by making all NOINLINE things have no strictness info is overkill.
In particular, it's overkill for runST, which is perfectly respectable.
Consider
f x = runST (return x)
This should be strict in x.

So the new plan is to define unsafePerformIO using the 'lazy' combinator:

unsafePerformIO (IO m) = lazy (case m realWorld# of (# _, r #) -> r)

Remember, 'lazy' is a wired-in identity-function Id, of type a->a, which is
magically NON-STRICT, and is inlined after strictness analysis.  So
unsafePerformIO will look non-strict, and that's what we want.
GHC/IOBase.lhs