Some specializations resulting from SPECIALIZE pragmas are pruned
Summary
I'm seeing some specializations resulting from SPECIALIZE
pragmas getting pruned (the specialized binding nor the rule exist in the optimized module). The specializations are generated and the rules get attached to the corresponding overloaded bindings, according to -ddump-spec
output. But at some point, presumably in GHC.Iface.Tidy.findExternalRules
(or chooseExternalIds
?), we decide to prune them.
Steps to reproduce
Unfortunately my only reproducer is in the Cabal-syntax library. Specifically, in Distribution.PackageDescription.FieldGrammar
, there is a pragma: {-# SPECIALIZE libraryFieldGrammar :: LibraryName -> ParsecFieldGrammar' Library #-}
. In -ddump-spec
, I see that the specialization and rewrite rule are generated. In -ddump-simpl
, they are gone. Here are some specific steps:
git clone https://github.com/haskell/cabal
git checkout a6b1eb5c6bbda819fab7108238e4105e99ff9cb5
cabal build --ghc-options="-ddump-spec -ddump-simpl -ddump-to-file -dumpdir=dumps" Cabal-syntax:lib:Cabal-syntax
Now, check that the specialization exists in -ddump-spec
and does not exist in -ddump-simpl
:
$ cat Cabal-syntax/dumps/src/Distribution/PackageDescription/FieldGrammar.dump-spec | grep 'libraryFieldGrammar @Parsec'
RULES: "USPEC libraryFieldGrammar @Parsec @ParsecFieldGrammar"
...
$ cat Cabal-syntax/dumps/src/Distribution/PackageDescription/FieldGrammar.dump-simpl | grep 'libraryFieldGrammar @Parsec'
<no output>
Also note that the specializations resulting from the pragma directly underneath that one ({-# SPECIALIZE libraryFieldGrammar :: LibraryName -> PrettyFieldGrammar' Library #-}
) are not pruned:
$ cat Cabal-syntax/dumps/src/Distribution/PackageDescription/FieldGrammar.dump-simpl | grep 'libraryFieldGrammar @Pretty'
"USPEC libraryFieldGrammar @Pretty @PrettyFieldGrammar"
...
and some of the specializations resulting from other ParsecFieldGrammar'
survive as well, for example:
$ cat Cabal-syntax/dumps/src/Distribution/PackageDescription/FieldGrammar.dump-simpl | grep 'flagFieldGrammar @Parsec'
"USPEC flagFieldGrammar @Parsec @ParsecFieldGrammar"
...
This has something to do with Parsec
being a single-method type class, as adding a dummy method to that class causes the specializations to stick around, as expected. It seems that the dictionaries referenced in the LHS of the generated rules, for the single-method type class, are not considered external ids and therefore we prune the rule.
Expected behavior
I expect these specializations to stick around, since they are coming from SPECIALIZE
pragmas.
Environment
I have only reproduced this on 9.6.4 and 9.8.1, and I have failed to reproduce this on 9.10.1-rc1 and HEAD, so this is fixed, I am just opening this for the sake of tracking.
Optional:
- Operating System: darwin
- System Architecture: aarch64