Note [Demand transformer for a dictionary selector]

GHC/Types/Demand.hs:2424 compiler

Suppose we have a superclass selector 'sc_sel' and a class method
selector 'op_sel', and a function that uses both, like this

Strictness sig: 1P(1,A)
sc_sel (x,y) = x

Strictness sig: 1P(A,1)
op_sel (p,q)= q

f d v = op_sel (sc_sel d) v

What do we learn about the demand on 'd'?  Alas, we see only the
demand from 'sc_sel', namely '1P(1,A)'.  We /don't/ see that 'd' really has a nested
demand '1P(1P(A,1C(1,1)),A)'.  On the other hand, if we inlined the two selectors
we'd have

f d x = case d of (x,_) ->
        case x of (_,q) ->
        q v

If we analyse that, we'll get a richer, nested demand on 'd'.

We want to behave /as if/ we'd inlined 'op_sel' and 'sc_sel'. We can do this
easily by building a richer demand transformer for dictionary selectors than
is expressible by a regular demand signature.
And that is what 'dmdTransformDictSelSig' does: it transforms the demand on the
result to a demand on the (single) argument.

How does it do that?
If we evaluate (op dict-expr) under demand 'd', then we can push the demand 'd'
into the appropriate field of the dictionary. What *is* the appropriate field?
We just look at the strictness signature of the class op, which will be
something like: P(AAA1AAAAA). Then replace the '1' (or any other non-absent
demand, really) by the demand 'd'. The '1' acts as if it was a demand variable,
the whole signature really means `\d. P(AAAdAAAAA)` for any incoming
demand 'd'.

NB: even unary classes behave as if there was a data constructor, and so do
not need special handling here. See Note [Unary class magic] in GHC.Core.TyCon.

References 1

Referenced by 3