summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Barbu <andrei@0xab.com>2021-09-30 17:19:36 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-12-15 16:33:17 -0500
commitf5a0b408c7e4ef71221eea3ea80ea250fbb28e18 (patch)
tree31b305405145c022d6aadfd512e83c3184330365
parent45bd630886157fbe4856594e098202808aedbdd0 (diff)
downloadhaskell-f5a0b408c7e4ef71221eea3ea80ea250fbb28e18.tar.gz
Plugin load order should follow the commandline order (fixes #17884)
In the past the order was reversed because flags are consed onto a list. No particular behavior was documented. We now reverse the flags and document the behavior.
-rw-r--r--compiler/GHC/Driver/Session.hs2
-rw-r--r--compiler/GHC/Runtime/Loader.hs4
-rw-r--r--docs/users_guide/extending_ghc.rst8
-rw-r--r--testsuite/tests/plugins/Makefile10
-rw-r--r--testsuite/tests/plugins/all.T15
-rw-r--r--testsuite/tests/plugins/plugins-order-pragma.hs6
-rw-r--r--testsuite/tests/plugins/plugins-order-pragma.stderr9
-rw-r--r--testsuite/tests/plugins/plugins-order.hs4
-rw-r--r--testsuite/tests/plugins/plugins-order.stderr9
9 files changed, 61 insertions, 6 deletions
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index 33b27c2f9f..3af4ede9bf 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -573,6 +573,8 @@ data DynFlags = DynFlags {
-- Plugins
pluginModNames :: [ModuleName],
+ -- ^ the @-fplugin@ flags given on the command line, in *reverse*
+ -- order that they're specified on the command line.
pluginModNameOpts :: [(ModuleName,String)],
frontendPluginOpts :: [String],
-- ^ the @-ffrontend-opt@ flags given on the command line, in *reverse*
diff --git a/compiler/GHC/Runtime/Loader.hs b/compiler/GHC/Runtime/Loader.hs
index 654b270fb1..704f499a4f 100644
--- a/compiler/GHC/Runtime/Loader.hs
+++ b/compiler/GHC/Runtime/Loader.hs
@@ -74,7 +74,7 @@ import GHC.Unit.Types (ModuleNameWithIsBoot)
initializePlugins :: HscEnv -> Maybe ModuleNameWithIsBoot -> IO HscEnv
initializePlugins hsc_env mnwib
-- plugins not changed
- | map lpModuleName (hsc_plugins hsc_env) == pluginModNames dflags
+ | map lpModuleName (hsc_plugins hsc_env) == reverse (pluginModNames dflags)
-- arguments not changed
, all same_args (hsc_plugins hsc_env)
= return hsc_env -- no need to reload plugins
@@ -96,7 +96,7 @@ loadPlugins hsc_env mnwib
; return $ zipWith attachOptions to_load plugins }
where
dflags = hsc_dflags hsc_env
- to_load = pluginModNames dflags
+ to_load = reverse $ pluginModNames dflags
attachOptions mod_nm (plug, mod) =
LoadedPlugin (PluginWithArgs plug (reverse options)) mod
diff --git a/docs/users_guide/extending_ghc.rst b/docs/users_guide/extending_ghc.rst
index ef9b584f04..06f3d2bb41 100644
--- a/docs/users_guide/extending_ghc.rst
+++ b/docs/users_guide/extending_ghc.rst
@@ -195,9 +195,11 @@ Using compiler plugins
Plugins can be added on the command line with the :ghc-flag:`-fplugin=⟨module⟩`
option where ⟨module⟩ is a module in a registered package that exports the
-plugin. Arguments can be passed to the plugins with the
-:ghc-flag:`-fplugin-opt=⟨module⟩:⟨args⟩` option. The list of enabled plugins can
-be reset with the :ghc-flag:`-fclear-plugins` option.
+plugin. Plugins are loaded in order, with command-line and Cabal flags preceding
+those in OPTIONS pragmas which are processed in file order. Arguments can be
+passed to the plugins with the :ghc-flag:`-fplugin-opt=⟨module⟩:⟨args⟩`
+option. The list of enabled plugins can be reset with the
+:ghc-flag:`-fclear-plugins` option.
.. ghc-flag:: -fplugin=⟨module⟩
:shortdesc: Load a plugin exported by a given module
diff --git a/testsuite/tests/plugins/Makefile b/testsuite/tests/plugins/Makefile
index 6716aecbfb..7ee0ccbfb7 100644
--- a/testsuite/tests/plugins/Makefile
+++ b/testsuite/tests/plugins/Makefile
@@ -172,3 +172,13 @@ test-defaulting-plugin:
test-defaulting-plugin-fail:
-"$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) -v0 test-defaulting-plugin-fail.hs -package-db defaulting-plugin/pkg.test-defaulting-plugin-fail/local.package.conf
+.PHONY: plugins-order
+plugins-order:
+ "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) --make -v0 plugins-order.hs -package-db plugin-recomp/pkg.plugins01/local.package.conf -fplugin ImpurePlugin -fplugin PurePlugin -fplugin-opt ImpurePlugin:First_Option -fplugin-opt PurePlugin:Second_Option -fplugin-opt PurePlugin:Second_Option_2 -fplugin FingerprintPlugin -fplugin-opt FingerprintPlugin:1
+ ./plugins-order
+
+.PHONY: plugins-order-pragma
+plugins-order-pragma:
+ "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) --make -v0 plugins-order-pragma.hs -package-db plugin-recomp/pkg.plugins01/local.package.conf -fplugin ImpurePlugin
+ ./plugins-order-pragma
+
diff --git a/testsuite/tests/plugins/all.T b/testsuite/tests/plugins/all.T
index 2146a2aa43..928bc494eb 100644
--- a/testsuite/tests/plugins/all.T
+++ b/testsuite/tests/plugins/all.T
@@ -249,7 +249,6 @@ test('T20417',
],
makefile_test, [])
-
test('T20218',
[extra_files(['simple-plugin/']), only_ways([config.ghc_plugin_way]),
pre_cmd('$MAKE -s --no-print-directory -C simple-plugin package.T20218 TOP={top}'),
@@ -275,3 +274,17 @@ test('test-defaulting-plugin-fail',
only_ways([config.ghc_plugin_way]),
pre_cmd('$MAKE -s --no-print-directory -C defaulting-plugin package.test-defaulting-plugin-fail TOP={top}')],
makefile_test, [])
+
+test('plugins-order',
+ [extra_files(['plugin-recomp/', 'plugin-recomp-test.hs']),
+ only_ways([config.ghc_plugin_way]),
+ pre_cmd('$MAKE -s --no-print-directory -C plugin-recomp package.plugins01 TOP={top}')
+ ],
+ makefile_test, [])
+
+test('plugins-order-pragma',
+ [extra_files(['plugin-recomp/', 'plugin-recomp-test.hs']),
+ only_ways([config.ghc_plugin_way]),
+ pre_cmd('$MAKE -s --no-print-directory -C plugin-recomp package.plugins01 TOP={top}')
+ ],
+ makefile_test, [])
diff --git a/testsuite/tests/plugins/plugins-order-pragma.hs b/testsuite/tests/plugins/plugins-order-pragma.hs
new file mode 100644
index 0000000000..eed6008748
--- /dev/null
+++ b/testsuite/tests/plugins/plugins-order-pragma.hs
@@ -0,0 +1,6 @@
+{-# OPTIONS -fplugin PurePlugin -fplugin-opt ImpurePlugin:First_Option -fplugin-opt PurePlugin:Second_Option -fplugin-opt PurePlugin:Second_Option_2 -fplugin FingerprintPlugin -fplugin-opt FingerprintPlugin:1 #-}
+
+-- Are plugins loaded in the correct order?
+module Main where
+
+main = pure ()
diff --git a/testsuite/tests/plugins/plugins-order-pragma.stderr b/testsuite/tests/plugins/plugins-order-pragma.stderr
new file mode 100644
index 0000000000..3f77276e4a
--- /dev/null
+++ b/testsuite/tests/plugins/plugins-order-pragma.stderr
@@ -0,0 +1,9 @@
+Simple Plugin Passes Queried
+Got options: First_Option
+Simple Plugin Passes Queried
+Got options: Second_Option Second_Option_2
+Simple Plugin Passes Queried
+Got options: 1
+Simple Plugin Pass Run
+Simple Plugin Pass Run
+Simple Plugin Pass Run
diff --git a/testsuite/tests/plugins/plugins-order.hs b/testsuite/tests/plugins/plugins-order.hs
new file mode 100644
index 0000000000..105cca3ed0
--- /dev/null
+++ b/testsuite/tests/plugins/plugins-order.hs
@@ -0,0 +1,4 @@
+-- Are plugins loaded in the correct order?
+module Main where
+
+main = pure ()
diff --git a/testsuite/tests/plugins/plugins-order.stderr b/testsuite/tests/plugins/plugins-order.stderr
new file mode 100644
index 0000000000..3f77276e4a
--- /dev/null
+++ b/testsuite/tests/plugins/plugins-order.stderr
@@ -0,0 +1,9 @@
+Simple Plugin Passes Queried
+Got options: First_Option
+Simple Plugin Passes Queried
+Got options: Second_Option Second_Option_2
+Simple Plugin Passes Queried
+Got options: 1
+Simple Plugin Pass Run
+Simple Plugin Pass Run
+Simple Plugin Pass Run