CoreLint claims join points inside casted expressions are invalid.
In core lint we have:
lintCoreExpr (Cast expr co)
= do (expr_ty, ue) <- markAllJoinsBad $ lintCoreExpr expr
to_ty <- lintCastExpr expr expr_ty co
return (to_ty, ue)
This seems bogus to me. Currently I see this tripping for this Core on a branch of mine:
joinrec {
$sgo2_s1jk [Occ=LoopBreaker, Dmd=SCS(C1(L))]
:: (Maybe a_aTK ~R# Max a_aTK) -> [Max a_aTK] -> Max a_aTK
[LclId[JoinId(2)(Just [~, !])],
Arity=2,
Str=<L><1L>,
Unf=OtherCon []]
$sgo2_s1jk (sg_s1el :: Maybe a_aTK ~R# Max a_aTK)
(sc_s1jl [Occ=Once1!] :: [Max a_aTK])
= case sc_s1jl of {
[] ->
(Nothing @a_aTK) `cast` (sg_s1el :: Maybe a_aTK ~R# Max a_aTK);
: y_s1jn [Occ=Once1!] ys_s1jo [Occ=Once2] ->
case y_s1jn
`cast` (N:Max[0] <a_aTK>_N :: Max a_aTK ~R# Maybe a_aTK)
of {
Nothing ->
((jump $sgo2_s1jk @~(sg_s1el :: Maybe a_aTK ~R# Max a_aTK) ys_s1jo)
`cast` (N:Max[0] <a_aTK>_N :: Max a_aTK ~R# Maybe a_aTK))
`cast` (Sym (N:Max[0] <a_aTK>_N) :: Maybe a_aTK ~R# Max a_aTK);
Just ipv_s1jq [Occ=Once1] ->
((jump $sgo1_s1jb
ipv_s1jq
@~(Sym (N:Max[0]) <a_aTK>_N :: Maybe a_aTK ~R# Max a_aTK)
ys_s1jo)
`cast` (N:Max[0] <a_aTK>_N :: Max a_aTK ~R# Maybe a_aTK))
`cast` (Sym (N:Max[0] <a_aTK>_N) :: Maybe a_aTK ~R# Max a_aTK)
}
}
The join points are still in obvious tail call position. We just coerce the result their result to a different type which is a no-op at runtime. This becomes very obvious if we look at the generated STG:
$sgo1_s1j8 [Occ=LoopBreaker, Dmd=LCS(C1(C1(L)))]
:: a_aUA
-> (GHC.Maybe.Maybe a_aUA ~R# Data.Functor.Utils.Max a_aUA)
-> [Data.Functor.Utils.Max a_aUA]
-> Data.Functor.Utils.Max a_aUA
[LclId[JoinId(3)(Just [~, ~, !])],
Arity=3,
Str=<L><L><1L>,
Unf=OtherCon []] =
\r [sc_s1j9 sg_s1fd sc1_s1ja]
case sc1_s1ja of {
[] -> GHC.Maybe.Just [sc_s1j9];
: y_s1jc [Occ=Once1!] ys_s1jd [Occ=Once3] ->
case y_s1jc of {
GHC.Maybe.Nothing ->
$sgo1_s1j8 sc_s1j9 GHC.Prim.coercionToken# ys_s1jd;
GHC.Maybe.Just ipv_s1jf ->
case GHC.Classes.>= $dOrd_s1j6 sc_s1j9 ipv_s1jf of {
GHC.Types.False ->
$sgo1_s1j8 ipv_s1jf GHC.Prim.coercionToken# ys_s1jd;
GHC.Types.True ->
$sgo1_s1j8 sc_s1j9 GHC.Prim.coercionToken# ys_s1jd;
};
};
};
end Rec }
It also doesn't violate any of the join invariants. So I plan to just allow joins inside casts.