Note [Desugaring seq]
There are a few subtleties in the desugaring of `seq`, all implemented in the `seqId` case of `ds_app_var`: 1. (as described in #1031) Consider, f x y = x `seq` (y `seq` (# x,y #)) Because the argument to the outer 'seq' has an unlifted type, we'll use call-by-value, and compile it as if we had f x y = case (y `seq` (# x,y #)) of v -> x `seq` v But that is bad, because we now evaluate y before x! Seq is very, very special! So we recognise it right here, and desugar to case x of _ -> case y of _ -> (# x,y #) 2. (as described in #2273) Consider let chp = case b of { True -> fst x; False -> 0 } in chp `seq` ...chp... Here the seq is designed to plug the space leak of retaining (snd x) for too long. If we rely on the ordinary inlining of seq, we'll get let chp = case b of { True -> fst x; False -> 0 } case chp of _ { I# -> ...chp... } But since chp is cheap, and the case is an alluring context, we'll inline chp into the case scrutinee. Now there is only one use of chp, so we'll inline a second copy. Alas, we've now ruined the purpose of the seq, by re-introducing the space leak: case (case b of {True -> fst x; False -> 0}) of I# _ -> ...case b of {True -> fst x; False -> 0}... We can try to avoid doing this by ensuring that the binder-swap in the case happens, so we get this at an early stage: case chp of chp2 { I# -> ...chp2... } But this is fragile. The real culprit is the source program. Perhaps we should have said explicitly let !chp2 = chp in ...chp2... But that's painful. So the code here does a little hack to make seq more robust: a saturated application of 'seq' is turned *directly* into the case expression, thus: x `seq` e2 ==> case x of x -> e2 -- Note shadowing! e1 `seq` e2 ==> case x of _ -> e2 So we desugar our example to: let chp = case b of { True -> fst x; False -> 0 } case chp of chp { I# -> ...chp... } And now all is well. The reason it's a hack is because if you define mySeq=seq, the hack won't work on mySeq. 3. (as described in #2409) The isInternalName ensures that we don't turn True `seq` e into case True of True { ... } which stupidly tries to bind the datacon 'True'.
References 0
This Note does not link to any other.
Referenced by 3
- GHC.HsToCore.Expr call site ×2
- seqId magic GHC.Types.Id.Make