Some places in the compiler assume arity of an `Id` is the same as the depth of its `StrictSig`
That assumption isn't always upheld; see
Note [idArity varies independently of dmdTypeDepth] in DmdAnal.
Rather than assuming that indeed in all cases where we assume that
idArity matches as an unchecked precondition, we should use functions like
appIsDeadEnd after !3014 (closed)). Here is an inexhaustive list of places in the code where we don't account for arity-DmdType-depth mismatches:
Id.isBottomingId: Just checks
isBottomingSig, which doesn't do any arity checks. Probably use
appIsBottom sig (idArity id)instead, or pass the arity to check to
isBottomingId. This function probably poses the biggest "thread".
exprIsDeadEndafter !3014 (closed), you get the idea): In the
Var idcase, it checks whether
isBottomingId idand then checks whether the number of incoming arguments is
>= idArity id. I think it should compare to the DmdType depth instead. For example, DmdType depth might be 2 but
idAritymight be 1. I don't know if there is such a scenario, but if there is, then it means chaos.
Hs.Core.Utils.isCheapApp: Doesn't consider arity/
n_val_argsat all. Even
Note [isCheapApp: bottoming functions]says that it's unclear why we have this special case. But I dug up 9be18ea4 and apparently, this check used to be in a function called
notRedex, that then got torn apart (407c11b8) into
isBottomingIdcheck, leaving that Note behind. I think the gist is that a partial application is always a cheap app, and as soon as we saturate the
StrictSig, we bottom out, which we also consider cheap in that it doesn't have to be shared. BUT: What if we had
n_val_args == idArity fn == 1, but the
StrictSighad depth 2? Then certainly that application is not cheap! So this should also call
appIsBottom (idStrictness fn) n_val_args.
Hs.Core.Op.FloatOut.floatBind: Looks at
isBottomingId, the eta-expands with
idArity. Should probably call
appIsBottom (idStrictness var) (idArity var).
- Other usages in LiberateCase, Simplify, SetLevels