Skip to content

Worker/wrapper should replace absent unlifted args by rubbish literals

#9254 (closed) gave us the following example where demand analysis supposedly messed up:

f :: (() -> (# Int#, () #)) -> ()
     -- Strictness signature is
     --    <1C1(P(A,1L))>
     -- I.e. calls k, but discards first component of result
f k = case k () of (# _, r #) -> r

g :: Int -> ()
g y = f (\n -> (# case y of I# y2 -> y2, n #))

Here, f's strictness signature says (correctly) that it calls its argument function and ignores the first component of its result. But in function g, we will evaluate the case y of ..., because it has type Int#. So in the program as written, y will be evaluated. Hence we must record this usage of y, else g will say y is absent, and will w/w so that y is bound to an absent filler (see Note [Absent fillers]), leading to a crash when y is evaluated.

But actually, it would be OK to propagate absence to y if worker/wrapper was smart enough to replace the absent argument case y of I# y2 -> y2 with a suitable absent filler such as RUBBISH[IntRep] @Int# that doesn't force y when case-bound.

It would also mean less explaining in DmdAnal, which is always a good thing.

Edited by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information