<div dir="ltr"><div>Hi again everyone,</div><div><br></div><div><br></div><div>I've been making some more adjustments to the API of type-checking plugins.</div><div>Following a suggestion by Richard, the mechanism for reporting errors while rewriting type family applications now consists of emitting a wanted constraint with a custom type error message. There are several technical reasons for this, which I will not get into.</div><div>This means there are now only two constructors of TcPluginRewriteResult: TcPluginNoRewrite and TcPluginRewriteTo. Both of these now take an extra argument: additional wanted constraints, which will be processed and emitted by GHC.<br></div><div><br></div><div><br></div><div>Coming back to the type-checking plugin API as a whole (not just the rewriting of type family applications), I've come to the realisation that it is probably best to keep GHC's interface as simple as possible, to allow library authors to write their own APIs.</div><div>After all, most of the API doesn't need to live within the GHC codebase, and instead (in my opinion) belongs in libraries that simply import the ghc package (which thankfully doesn't hide any exports one might want to use).</div><div>This means we don't have to tie any experimentation with type-checking plugin APIs to the GHC release schedule.<br></div><div><br></div><div>To that end, I have concluded that one single non-backwards-compatible change seems important: changing the TcPluginM monad from being isomorphic to "ReaderT EvBindsVar TcM" to simply being a newtype around TcM. Then, we instead pass an EvBindsVar as an extra argument to tcPluginSolve.<br></div><div>This avoids all the silly business with functions whose documentation said "only call this within tcPluginSolve or it will cause a crash" (a situation which was only made worse by the addition of rewriting plugins). It's also less opinionated: library authors can use a ReaderT wrapper in their API if they desire, but are not forced to do so.</div><div>Please note that I don't make this change lightly, as I know it is already time-consuming enough to maintain type-checking plugins, especially as much more significant changes abound (removal of flattening variables in GHC 9.2, removal of derived constraints (possibly in GHC 9.4)). I hope nevertheless that you might find this acceptable.<br></div><div><br></div><div><br></div><div>Finally, facilitated by the above, I have started implementing a library providing a simple API for type-checking plugins; see here <a href="https://github.com/sheaf/ghc-tcplugin-api" style="">https://github.com/sheaf/ghc-tcplugin-api</a>.</div><div>An example of a not-totally-trivial rewriting plugin is given here: <a href="https://github.com/sheaf/ghc-tcplugin-api/blob/ad6ca964c3b27c28bb27392d7ba406cfac82176d/examples/RewriterPlugin/plugin/RewriterPlugin.hs" style="">https://github.com/sheaf/ghc-tcplugin-api/blob/ad6ca964c3b27c28bb27392d7ba406cfac82176d/examples/RewriterPlugin/plugin/RewriterPlugin.hs</a>.</div><div>Note that I barely had to import anything from the ghc package; I hope this can remain true for more involved plugins (up to a point).</div><div>Please let me know what you think, in particular if you think certain important functions are missing from the API.<br></div><div><br></div><div> For this library specifically, I have added back ReaderT layers (but only in the appropriate situations, to avoid reintroducing the aforementioned problem with "only call this in tcPluginSolve"), and provided MTL-style typeclasses for operations that work with multiple different phases of the plugin.</div><div>Other design options are of course possible; at any rate, I think it is preferable to be making these API choices outside of GHC itself whenever possible.</div><div>I've also included helpers for creating custom type errors within type-checking plugins, as that was unnecessarily cumbersome. (One still needs to provide a CtLoc to inform GHC of the source location of the error; one can get this from a constraint fed to the plugin in a solver plugin, or from the rewriting environment in a rewriter plugin).<br></div><div><br></div><div><br></div><div>Note that this all still depends on the WIP GHC MR 5909, available at <a href="https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5909" style="">https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5909</a>.</div><div><br></div><div><br></div><div>I look forward to your feedback,<br></div><div><br></div><div>Thanks,</div><div><br></div><div>Sam<br></div></div>