Hi Sam,

As a plugin writer, I'm fine with the proposed API change, as long as the
final implementation comes with some nice soft documentation: what kind of
actions I would do in `tcPluginPostTc` and what kinds of actions I would do
in `tcPluginShutdown`.

Cheers,

Christiaan

On Mon, 9 Feb 2026 at 10:46, Sam Derbyshire via ghc-devs <
[email protected]> wrote:

> Dear GHC devs, and typechecker plugin authors in particular,
>
> In GHC ticket #26935 <https://gitlab.haskell.org/ghc/ghc/-/issues/26395>,
> I noticed that typechecker plugins were not getting run when doing pattern
> match checking, which was a long standing source of frustration. I fixed
> this in GHC MR !14797
> <https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14797> (only present
> in GHC HEAD at the moment), but, as noted in GHC ticket #26839
> <https://gitlab.haskell.org/ghc/ghc/-/issues/26839>, this meant that GHC
> is repeatedly initialising typechecker plugins for a single module
> (starting and stopping the plugins for each call of initTcDsForSolver by
> the pattern-match checker).
>
> I am proposing to change the TcPlugin datatype to split the existing
> "stop" action into two separate actions, "end of typechecking" and "plugin
> shutdown". This would allow typechecker plugins to be kept running after
> typechecking (for the benefit of the pattern-match checker) while upholding
> the invariant that typechecker plugins are initialised once per module
> being typechecked (modulo small caveats about certain one-off runs of the
> typechecker by e.g. Backpack).
>
> The current TcPlugin data type is as follows:
>
> data TcPlugin = forall s. TcPlugin
>   { tcPluginInit :: TcPluginM s
>   , tcPluginSolve :: s -> TcPluginSolver
>   , tcPluginRewrite :: s -> UniqFM TyCon TcPluginRewriter
>   , tcPluginStop :: s -> TcPluginM ()
>     -- ^ Clean up after the plugin, when exiting the type-checker.
>   }
>
> To allow typechecker plugins to be run by the pattern-match checker, I
> propose to change this to:
>
> data TcPlugin = forall s. TcPlugin
>   { tcPluginInit :: TcPluginM s
>   , tcPluginSolve :: s -> TcPluginSolver
>   , tcPluginRewrite :: s -> UniqFM TyCon TcPluginRewriter
>   , tcPluginPostTc :: s -> TcPluginM ()
>     -- ^ Action to run at the end of type-checking.
>   , tcPluginShutdown :: s -> IO ()
>     -- ^ Clean up after the plugin, after desugaring is finished.
>   }
>
> tcPluginPostTc would run at the end of typechecking. This gives plugins a
> final opportunity to modify the typechecker environment before it is
> finalised (as e.g. the clippy plugin does
> <https://github.com/ArturGajowy/ghc-clippy-plugin/blob/0f97274f238b78e1117b751fdd3f39e210841864/src/Clippy.hs#L33>).
> If the plugin relies on an active session (e.g. with Z3), the post-tc
> action should not end the session, because the plugin might still be
> invoked by the pattern match checker, later, during desugaring.
>
> Some remarks:
>
>    - I changed tcPluginStop to tcPluginPostTc, because it now serves a
>    different function (an action at the end of typechecking that should
>    *not* shut down the plugin). Keeping the same name would be confusing,
>    I think.
>    - The tcPluginShutdown action runs in IO only, as running in TcPluginM 
> would
>    require holding on to a typechecker environment during desugaring, which
>    can cause memory leaks.
>    - This same change would also be carried over to defaulting plugins,
>    but not to hole fit plugins – the latter cannot affect pattern match
>    checking.
>    - A better solution to all of this would be to run the pattern match
>    checker during typechecking, but that would be a significant
>    infrastructural change to GHC.
>
> I would like feedback from authors of typechecker plugins on this proposed
> change.
>
> Thanks,
>
> Sam
> _______________________________________________
> ghc-devs mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
>
_______________________________________________
ghc-devs mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to