Note [Arity for recursive join bindings]
Consider
f x = joinrec j 0 = \ a b c -> (a,x,b)
j n = j (n-1)
in j 20
Obviously `f` should get arity 4. But it's a bit tricky:
1. Remember, we don't eta-expand join points; see
Note [Do not eta-expand join points].
2. But even though we aren't going to eta-expand it, we still want `j` to get
idArity=4, via the findRhsArity fixpoint. Then when we are doing findRhsArity
for `f`, we'll call arityType on f's RHS:
- At the letrec-binding for `j` we'll whiz up an arity-4 ArityType
for `j` (See Note [arityType for non-recursive let-bindings]
in GHC.Core.Opt.Arity)b
- At the occurrence (j 20) that arity-4 ArityType will leave an arity-3
result.
3. All this, even though j's /join-arity/ (stored in the JoinId) is 1.
This is is the Main Reason that we want the idArity to sometimes be
larger than the join-arity c.f. Note [Invariants on join points] item 2b
in GHC.Core.
4. Be very careful of things like this (#21755):
g x = let j 0 = \y -> (x,y)
j n = expensive n `seq` j (n-1)
in j x
Here we do /not/ want eta-expand `g`, lest we duplicate all those
(expensive n) calls.
But it's fine: the findRhsArity fixpoint calculation will compute arity-1
for `j` (not arity 2); and that's just what we want. But we do need that
fixpoint.
Historical note: an earlier version of GHC did a hack in which we gave
join points an ArityType of ABot, but that did not work with this #21755
case.
5. arityType does not usually expect to encounter free join points;
see GHC.Core.Opt.Arity Note [No free join points in arityType].
But consider
f x = join j1 y = .... in
joinrec j2 z = ...j1 y... in
j2 v
When doing findRhsArity on `j2` we'll encounter the free `j1`.
But that is fine, because we aren't going to eta-expand `j2`;
we just want to know its arity. So we have a flag am_no_eta,
switched on when doing findRhsArity on a join point RHS. If
the flag is on, we allow free join points, but not otherwise. References 4
- arityType for non-recursive let-bindings GHC.Core.Opt.Arity
- Do not eta-expand join points GHC.Core.Opt.Arity
- No free join points in arityType GHC.Core.Opt.Arity
- Invariants on join points GHC.Core
Referenced by 5
- Invariants on join points GHC.Core
- Arity for non-recursive join bindings GHC.Core.Opt.Arity
- No free join points in arityType GHC.Core.Opt.Arity
- arityType for recursive let-bindings GHC.Core.Opt.Arity
- GHC.Core.Opt.Arity call site