Discussion about the structure of mkCoreUnfolding
I was contemplating the memory behaviour of mkCoreUnfolding
:
mkCoreUnfolding :: UnfoldingSource -> Bool -> CoreExpr
-> UnfoldingGuidance -> Unfolding
-- Occurrence-analyses the expression before capturing it
mkCoreUnfolding src top_lvl expr guidance
= CoreUnfolding { uf_tmpl = occurAnalyseExpr expr,
-- See Note [Occurrence analysis of unfoldings]
uf_src = src,
uf_is_top = top_lvl,
uf_is_value = exprIsHNF expr,
uf_is_conlike = exprIsConLike expr,
uf_is_work_free = exprIsWorkFree expr,
uf_expandable = exprIsExpandable expr,
uf_guidance = guidance }
The immediate problem to me is that this definition seems like it will retain both the old CoreExpr
(expr
) and a new CoreExpr
, (occurAnalyseExpr expr
).
However, occurAnalyseExpr expr
is also a thunk, so this doubling situation only happens when uf_tmpl
is forced but the predicate fields are not (or vice versa). Are these fields always forced in lock-step? We could-engineer that to be the case but it seems we might check the predicates before deciding to force the template.
Are the predicates on the expr
invariant under occurrence analysis? It seems to me that they should be.
Therefore, perhaps the best thing to is to engineer this definition so that the predicates are called on expr
if uf_tmpl
has not been forced, if it has been forced then instead the forced value should be used for computation. This could be achieved using IORefs and unsafe functions.
Thoughts?