Casts and `coerce` defeat inlining though `Exts.inline`
Summary
Exts.inline is supposed to force inlining, however in the presence of casts this fails. Most explicitly this happens when manually inserting coerce
.
Steps to reproduce
When compiling this module:
{-# OPTIONS_GHC -O -fno-cse -dno-typeable-binds #-}
module M where
import GHC.Exts (inline)
import Data.Coerce
-- A type we can coerce
newtype MyMaybe = MyMaybe { getMaybe :: (Maybe Int) }
myFunction :: MyMaybe -> MyMaybe
myFunction (MyMaybe m) = case m of
Nothing -> MyMaybe Nothing
-- Make it largeish
Just n -> MyMaybe $ Just $ succ . succ . succ . succ . succ . succ . succ . succ . succ . succ $ n
-- Inlines as expected
bar :: MyMaybe -> MyMaybe
bar = inline myFunction
-- Doesn't inline - but I think it should.
foo :: MyMaybe -> Maybe Int
foo = (inline (coerce myFunction))
Expected behavior
I would expect myFunction to inline into foo
despite the cast being "in the way".
While it might be debatable if we should inline here, after all one might consider coerce
to be the function to be inlined the same happens when casts occur in a program through other means, as it happened in #24765 (closed) .
The relevant core for the reproducer in this ticket looks like this:
-- RHS size: {terms: 2, types: 3, coercions: 4, joins: 0/0}
foo :: MyMaybe -> Maybe Int
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=False,
Value=False, ConLike=False, WorkFree=False, Expandable=False,
Guidance=IF_ARGS [] 20 0}]
foo
= inline
@(MyMaybe -> Maybe Int)
(myFunction
`cast` (<MyMaybe>_R %<Many>_N ->_R M.N:MyMaybe[0]
:: (MyMaybe -> MyMaybe) ~R# (MyMaybe -> Maybe Int)))
Which to to me makes it obvious that inlining is desired in this case.
Environment
- GHC version used: GHC-HEAD and 9.6.2