
#13479: Core Lint issues during slowtest -------------------------------------+------------------------------------- Reporter: bgamari | Owner: nomeata Type: bug | Status: new Priority: high | Milestone: 8.2.1 Component: Compiler | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple crash or panic | Test Case: Blocked By: | Blocking: Related Tickets: #10181 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by nomeata): The problem is that Call Arity has not been changed to know about the special semantics of join points. This is the code for in question: {{{ f :: forall a. [Int] -> a [LclIdX, Arity=1, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [0] 128 0}] f = \ (@ a_a1iy) (a_XX6 :: [Int]) -> let { z_a34C :: Integer -> a_a1iy [LclId, CallArity=1, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=False, ConLike=False, WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 28 0}] z_a34C = joinrec { go_a34D [Occ=LoopBreaker] :: [Int] -> Integer -> a_a1iy [LclId[JoinId(1)], Arity=1, CallArity=2, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 24 0}] go_a34D (ds_a34E :: [Int]) = case ds_a34E of { [] -> case lvl_s4VT of wild_00 { }; : y_a34J ys_a34K -> jump go_a34D ys_a34K }; } in jump go_a34D a_XX6 } in letrec { go_a34D [Occ=LoopBreaker] :: [Int] -> Integer -> a_a1iy [LclId, Arity=1, CallArity=2, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 40 0}] go_a34D = \ (ds_a34E :: [Int]) -> case ds_a34E of { [] -> z_a34C; : y_a34J ys_a34K -> go_a34D ys_a34K }; } in go_a34D a_XX6 lvl_s4VV }}} Call Arity (which analyzes things from bottom to top) correctly finds out that the bottom `go_a34D` should have arity 2 (it is called with two arguments, and keeps passing the second one around). This implies that `z_a34C` is called with one argument, so that gets `CallArity=1`. From this Call Arity follows that to first `go_a34D` (the join point) should also have arity two, and it records it so. The subsequent simplification then eta-expands the `go_a34D` function, which turns it into a join point (yay!). But it does not *not* eta-expand the join point `go_a34D` (which gets renamed to `go_X45x`): {{{ f = \ (@ a_a1iy) (a_XX6 :: [Int]) -> joinrec { go_a34D [Occ=LoopBreaker] :: [Int] -> Integer -> a_a1iy [LclId[JoinId(2)], Arity=2, CallArity=2, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [36 0] 54 0}] go_a34D (ds_a34E :: [Int]) (eta_B1 :: Integer) = case ds_a34E of { [] -> joinrec { go_X35x [Occ=LoopBreaker] :: [Int] -> a_a1iy [LclId[JoinId(1)], Arity=1, CallArity=2, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 24 0}] go_X35x (ds_X35z :: [Int]) = case ds_X35z of { [] -> case lvl_s4VT of wild_00 { }; : y_a34J ys_a34K -> jump go_X35x ys_a34K }; } in jump go_X35x a_XX6; : y_a34J ys_a34K -> jump go_a34D ys_a34K eta_B1 }; } in jump go_a34D a_XX6 lvl_s4VV }}} At this point, something went wrong. The now named `go_X45x` is still marked as having CallArity=2, but it does not actually have that arity! Where did the argument `eta_B1`, which I would have expected to be passed to `go_X35x`, disappear? Was it “pushed into the branches”, and then into the empty set branches of the empty case there? So the simplifier uses the function `tryEtaExpandRhs` to try to eta-expand if Call Arity tells it to do so, but it does not even try that for join points (see `completeBind` in `Simplify`). I am a bit lost in the code right now and cannot quite reproduce what precisely is happening here. Something related to `simplJoinRHS` and “Context goes *inside* the lambdas.” Certainly, Luke’s opinion would be welcome. In any case, I believe the fix is to have the simplifier to simply zap Call Arity information. It is the only place where it is actually used, and as this demonstrates, the simplifier does not preserve Call Arity information. I will prepare a PR for this. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13479#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler