CoreTidy drops specialisations of exported functions
This is T7785
, from #7785 (closed):
{-# LANGUAGE TypeFamilies, ConstraintKinds #-}
module Foo( shared, foo, bar) where
import Data.Kind
type family Domain (f :: Type -> Type) a :: Constraint
type instance Domain [] a = ()
class MyFunctor f where
myfmap :: (Domain f a, Domain f b) => (a -> b) -> f a -> f b
instance MyFunctor [] where
myfmap = map
shared :: (MyFunctor f, Domain f Int) => f Int -> f Int
shared = let
f = myfmap negate
in
f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f.
f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f.
f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f.
f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f. f.
f . f . f . f . f . f . f . f . f . f . f . f . f
foo, bar :: [Int] -> [Int]
foo xs = shared $ 0:xs
bar xs = 0:shared xs
The gist is that we have an exported, specialisable function shared :: (MyFunctor f, Domain f Int) => f a -> f b
. There are two call sites foo
, bar
within the module that force a specialisation for []
, $sshared
. We get a RULE attached to shared
that rewrites shared @[] $dMyFunctor = $sshared
. Ultimately, we want to see that rule (with -ddump-rules
) exported and thus the specialisation $sshared
kept alive. Indeed, the expected test output is
==================== Tidy Core rules ====================
"SPEC shared @[]"
forall ($dMyFunctor :: MyFunctor []) (irred :: Domain [] Int).
shared @[] $dMyFunctor irred
= bar_$sshared
But when I look at -ddump-simpl
output, this RULE is announced as an IMP rule!
------ Local rules for imported ids --------
"SPEC shared @[]"
forall ($dMyFunctor :: MyFunctor []) (irred :: Domain [] Int).
shared @[] $dMyFunctor irred
= Foo.bar_$sshared
Which seems wrong. As it happens, the specialisation $sshared
is only kept alive through the call site in bar
(which I haven't shown), not through the RULE associated with the exported function shared
.
Now !7788 (closed) comes up with a slightly different specialisation that causes $sshared
to inline into that call site. Result: the RULE and $sshared
are dropped completely and our specialisation work has been lost.
Question: Is there a reason why CoreTidy doesn't keep alive $sshared
if its only occurrence is in the RHS of a RULE attached to the exported function shared
?