Skip to content

Demand signature of `lazy` is too conservative

When I write

module Lib where

import GHC.Exts

foo :: a -> a
foo a = lazy a

I expect to see a demand signature (with -O -ddump-dmd-signatures) like <ML>, i.e., used at most once (albeit lazily). Instead I see <L>.

That is because the current wiring of lazy does not specify any demand signature whatsoever, so it defaults to topSig, which expands to <L>.

This is easily fixed by specifying a demand signature in GHC.Types.Id.Make.


I'm a bit hesitant though, because CorePrep eliminates lazy x entirely into x. That might cause trouble, for example when we see

let x = expensive 42 in
let y = lazy x in
y + y
  • Demand analysis concludes that y is used many times, but x is only used at most once because of the apparent thunk.
  • Alas, CorePrep should eliminate lazy x to x, at which point the trivial binding y = x is simply inlined! Now x is used many times. Yet the demand info on x still says used once, so we will duplicate evaluation of expensive 42.

So I'm wondering whether we should detect lazy x as trivial iff x is trivial (the same should be morally true of all the other CorePrep-inlined primops such as noinline, runRW#, dataToTag#). Or simply not bother to fix this ticket.

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