Plugin order is reversed in ghc 9.4
Summary
Plugin order is important, because the output of one plugin can feed into another plugin. The GHC manual says that "Plugins are loaded in order". However, this order seems to have been reversed in ghc 9.4: prior to 9.4, plugins were loaded in reverse order to how they appear in OPTIONS_GHC
, whereas in 9.4 they are in order. This means that CPP may now be required (in code that supports multiple ghc versions) to correctly load multiple plugins.
Steps to reproduce
Consider this simple plugin code that adds some suffix
to every string literal in a module:
{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
module Plugin (Plugin, pluginWithSuffix) where
import Data.Data
import GHC.Plugins
import GHC.Hs
pluginWithSuffix :: String -> Plugin
pluginWithSuffix suffix = defaultPlugin {
parsedResultAction = \_ _ -> return .
ignoreMessages (modifyStrings suffix)
}
where
#if __GLASGOW_HASKELL__ >= 904
ignoreMessages f (ParsedResult modl msgs) = ParsedResult (f modl) msgs
#else
ignoreMessages = id
#endif
modifyStrings :: String -> HsParsedModule -> HsParsedModule
modifyStrings suffix m@HsParsedModule{hpm_module} =
m{hpm_module = go hpm_module}
where
go :: forall a. Data a => a -> a
go x =
case (isHsExpr x, x) of
(Just Refl, HsLit e1 (HsString e2 str)) ->
HsLit e1 (HsString e2 (mappend str (fsLit suffix)))
_otherwise ->
gmapT go x
isHsExpr :: forall a. Data a => a -> Maybe (a :~: HsExpr GhcPs)
isHsExpr _ = eqT
We can then define 3 plugins with different suffices; A
:
module PluginA (plugin) where
import Plugin
plugin :: Plugin
plugin = pluginWithSuffix"A"
B
:
module PluginB (plugin) where
import Plugin
plugin :: Plugin
plugin = pluginWithSuffix "B"
and C
:
module PluginC (plugin) where
import Plugin
plugin :: Plugin
plugin = pluginWithSuffix "C"
Then here is a simple test:
{-# OPTIONS_GHC -fplugin=PluginA #-}
{-# OPTIONS_GHC -fplugin=PluginB #-}
{-# OPTIONS_GHC -fplugin=PluginC #-}
module Main (main) where
main :: IO ()
main = putStrLn "Hi"
It doesn't matter if these are separate OPTIONS_GHC
pragmas or a single one.
Expected behavior
Running the above code with ghc 9.2 gives
HiCBA
whereas in ghc 9.4 it gives
HiABC
Environment
- GHC version used: ghc 9.2.7, ghc 9.4.4