Hello everyone,
I'm happy to report that I have implemented a compatibility layer in the ghc-tcplugin-api library which provides type-family rewriting functionality on GHC 9.0 and 9.2.
This means that plugin authors should now be able to use the exact same API from GHC 9.0 onwards (and in particular, without waiting for a version of GHC containing the new implementation of type-family rewriting plugins).
To refresh your memory, writing a type-checking plugin with this library currently consists of the provision of a record
data TcPlugin = forall s. TcPlugin
{ tcPluginInit :: TcPluginM Init s
, tcPluginSolve :: s -> TcPluginSolver
, tcPluginRewrite :: s -> UniqFM TyCon TcPluginRewriter
, tcPluginStop :: s -> TcPluginM Stop ()
}
with the following type synonyms:
type TcPluginSolver
= [GHC.Ct] -- ^ Givens
-> [GHC.Ct] -- ^ Wanteds
-> TcPluginM Solve TcPluginSolveResult
Note that Deriveds are no longer passed explicitly. (It is possible to retrieve
the Derived constraints
from the TcPluginM Solve monad; as they are not commonly used, it made sense to make them less conspicuous.)
type TcPluginRewriter
= [GHC.Ct] -- ^ Givens
-> [GHC.Type] -- ^ Type family arguments (saturated)
-> TcPluginM Rewrite TcPluginRewriteResult
On GHC 9.0 and 9.2, the tcPluginRewrite function will get hooked in as a pre-pass of the user-supplied tcPluginSolve function.
There are small differences in behaviour that arise from solver plugins not always getting a chance to run when GHC can solve the wanteds on its own,
but I expect this to have minimal impact.
On top of this, I expect (but have not measured) a performance degradation compared to the "native" plugin type-family rewriting functionality, as the solver plugin must traverse all constraints to find type-family applications.
I have not tested this compatibility layer extensively, so I welcome all feedback from plugin authors.
Note that I have also reduced the amount of re-exported datatype constructors and accessors in an attempt to improve cross compatibility.
Please let me know of any difficulties that you encounter as a consequence, and I will endeavour to re-export cross-compatible non-internal definitions.
Thanks,
Sam