Note [Why isn't the EPT Invariant enforced during Core passes?]
Recall the definition of the EPT Invariant from Note [EPT enforcement]. Why can't it be established as an invariant right while desugaring to Core? The reason is that some Core optimisations, such as FloatOut, will drop or delay evals whenever they think it useful and thus destroy the Invariant. Example: data Set a = Tip | Bin !a (Set a) (Set a) We start with thk = f () g x = ...(case thk of xv -> Bin xv Tip Tip)... So far so good; the argument to Bin (which is strict) is evaluated. Now we do float-out. And in doing so we do a reverse binder-swap (see Note [Binder-swap during float-out] in SetLevels) thus g x = ...(case thk of xv -> Bin thk Nil Nil)... The goal of the reverse binder-swap is to allow more floating -- and indeed it does! We float the Bin to top level: lvl = Bin thk Tip Tip g x = ...(case thk of xv -> lvl)... Now you can see that the argument of Bin, namely thk, points to the thunk, not to the value as it did before. In short, although it may be rare, the output of Core optimisation passes might destroy the EPT Invariant, hence we need to enforce the EPT invariant *after* passes such as FloatOut.
References 1
- EPT enforcement GHC.Stg.EnforceEpt
Referenced by 0
Nothing in the tree points here.