`noinline` worsens demand signatures when it should not.
In terms of demands I would have expected the variants of foo
and bar
to behave the same:
{-# NOINLINE foo #-}
foo x y = (noinline const) x y
{-# NOINLINE bar #-}
bar x y = const x y
{-# NOINLINE sfoo #-}
sfoo x y = (noinline (+)) x y :: Int
{-# NOINLINE sbar #-}
sbar x y = x + y :: Int
However noinline
completely destroys the demand information:
==================== Tidy Core ====================
Result size of Tidy Core
= {terms: 21, types: 36, coercions: 0, joins: 0/0}
-- RHS size: {terms: 8, types: 11, coercions: 0, joins: 0/0}
foo [InlPrag=NOINLINE] :: forall {t1} {t2}. t1 -> t2 -> t1
[GblId, Arity=2, Str=<L><L>, Unf=OtherCon []]
foo
= \ (@t_aCy) (@t1_aCu) (x_aiJ :: t_aCy) (y_aiK :: t1_aCu) ->
noinline
@(forall a b. a -> b -> a) const @t_aCy @t1_aCu x_aiJ y_aiK
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
bar [InlPrag=NOINLINE] :: forall {a} {b}. a -> b -> a
[GblId, Arity=2, Str=<1L><A>, Unf=OtherCon []]
bar = const
-- RHS size: {terms: 7, types: 9, coercions: 0, joins: 0/0}
sfoo [InlPrag=NOINLINE] :: Int -> Int -> Int
[GblId, Arity=2, Str=<L><L>, Unf=OtherCon []]
sfoo
= \ (x_aiS :: Int) (y_aiT :: Int) ->
noinline
@(forall a. Num a => a -> a -> a)
+
@Int
GHC.Num.$fNumInt
x_aiS
y_aiT
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
sbar [InlPrag=NOINLINE] :: Int -> Int -> Int
[GblId, Arity=2, Str=<1!P(L)><1!P(L)>, Cpr=1, Unf=OtherCon []]
sbar = GHC.Num.$fNumInt_$c+
It seems very reasonale to have a special case for noinline wich works something like:
dmdAnal' env dmd <noinline @type f> = dmdAnal' env dmd f
.