Don't reconstruct sum types if the type subtly changes
Consider this test case:
module Main (main) where
fun :: Either Int String -> Either String String
fun x = case x of
Left int -> Left (show int)
Right str -> Right str
{-# NOINLINE fun #-}
main :: IO ()
main = do
l <- getLine
print $ fun (Right l)
The core we get for fun looks like:
Main.fun [InlPrag=NOINLINE]
:: Data.Either.Either GHC.Types.Int GHC.Base.String
-> Data.Either.Either GHC.Base.String GHC.Base.String
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType <S,1*U>]
Main.fun =
\ (x_aur :: Data.Either.Either GHC.Types.Int GHC.Base.String) ->
case x_aur of _ [Occ=Dead] {
Data.Either.Left int_aus ->
Data.Either.Left
@ GHC.Base.String
@ GHC.Base.String
(GHC.Show.$fShowInt_$cshow int_aus);
Data.Either.Right str_aCG ->
Data.Either.Right @ GHC.Base.String @ GHC.Base.String str_aCG
}
There would be less allocations and probably perform better if we just coerced x
into the new type. Because the coercion is common code, this also means that if hypothetically some other sum type which had 15 constructors, and only 3 had subtle type changes, 12 of the case branches could be CSE'd into the single coerce greatly reducing code generated and also hinting the inliner better.
Trac metadata
Trac field | Value |
---|---|
Version | 7.8.2 |
Type | FeatureRequest |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |