
#14223: Casts get in the way of join points -------------------------------------+------------------------------------- Reporter: nomeata | Owner: (none) Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Keywords: JoinPoints | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- I was checking which of HLint’s rewirte rules are actually already known to the compiler in the sense that the simplifier can do them (using [ghc- proofs](http://hackage.haskell.org/package/ghc-proofs). I stumbled on this interesting case. `foldr @[] (&&) True xs` compiles down to this nice core {{{ joinrec { go [Occ=LoopBreaker] :: [Bool] -> Bool [LclId[JoinId(1)], Arity=1, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 44 20}] go (ds :: [Bool]) = case ds of { [] -> GHC.Types.True; : y ys -> case y of { False -> GHC.Types.False; True -> jump go ys } }; } in jump go xs }}} But `and @[] xs` (which HLint suggests to use instead, and we surely want people to use!) compiles down to {{{ go [Occ=LoopBreaker] :: [Bool] -> All [LclId, Arity=1, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 60 20}] go = \ (ds :: [Bool]) -> case ds of { [] -> GHC.Types.True `cast` (Sym Data.Monoid.N:All[0] :: Coercible Bool All); : y ys -> case y of { False -> GHC.Types.False `cast` (Nth:3 (Nth:3 ((Sym Data.Monoid.N:All[0] -> Sym Data.Monoid.N:All[0] -> <Bool>_R) ; (<All>_R -> <All>_R -> Sym Data.Monoid.N:All[0]))) :: Coercible Bool All); True -> go ys } }; } in (go xs) `cast` (Data.Monoid.N:All[0] :: Coercible All Bool) }}} If you squint and ignore all the casts, these two expressions are the same. So it would be very desirable to get a `joinrec` for `and xs` as well. Note that all “exit paths” of the return function cast from `Bool` to `All`, and the return value of the whole recursion casts back. That looks as if some smart floating of coercions could do the job. Maybe the common context transformation (https://mail.haskell.org/pipermail/ghc- devs/2013-December/003481.html)? Is this tied to GHC’s deviation of the paper to have a fixed return type for a join point? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14223 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler