GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:53:24Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/5834Allow both INLINE and INLINABLE for the same function2019-07-07T18:53:24Zrl@cse.unsw.edu.auAllow both INLINE and INLINABLE for the same functionSometimes you really want both. Here is a small example:
```hs
module T where
foo :: Num a => a -> a -> a
foo x y = x+y+1
```
```hs
module U where
import T
appl :: (a -> b) -> a -> b
{-# NOINLINE appl #-}
appl f x = f x
bar :: Int -> Int -> Int
bar x y = appl foo x y
```
If I mark `foo` as `INLINE`, then GHC generates this code for `bar`:
```hs
bar1 :: Int -> Int -> Int
bar1 = foo @ Int $fNumInt
bar :: Int -> Int -> Int
bar = \ (x_aa0 :: Int) (y_aa1 :: Int) -> appl @ Int @ (Int -> Int) bar1 x_aa0 y_aa1
```
Whereas with `INLINABLE`, we get a nice specialisation but, of course, not guarantees with respect to inlining.
In general, it seems that requiring a function to inline when it is saturated and requiring it to specialise when it isn't are two different things and shouldn't be mutually exclusive.Sometimes you really want both. Here is a small example:
```hs
module T where
foo :: Num a => a -> a -> a
foo x y = x+y+1
```
```hs
module U where
import T
appl :: (a -> b) -> a -> b
{-# NOINLINE appl #-}
appl f x = f x
bar :: Int -> Int -> Int
bar x y = appl foo x y
```
If I mark `foo` as `INLINE`, then GHC generates this code for `bar`:
```hs
bar1 :: Int -> Int -> Int
bar1 = foo @ Int $fNumInt
bar :: Int -> Int -> Int
bar = \ (x_aa0 :: Int) (y_aa1 :: Int) -> appl @ Int @ (Int -> Int) bar1 x_aa0 y_aa1
```
Whereas with `INLINABLE`, we get a nice specialisation but, of course, not guarantees with respect to inlining.
In general, it seems that requiring a function to inline when it is saturated and requiring it to specialise when it isn't are two different things and shouldn't be mutually exclusive.8.0.1