summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2021-04-12 18:09:03 +0100
committerBen Gamari <ben@smart-cactus.org>2021-12-11 19:41:23 -0500
commitc52f51424d3eae253c0477ba254f5073b568e328 (patch)
treedf11b8639e2058c156085a283fb34f5726abf787
parent48203872de7f8967834c3218a90a0354bfe786f2 (diff)
downloadhaskell-c52f51424d3eae253c0477ba254f5073b568e328.tar.gz
Only load package environment file once when starting GHCi
Since d880d6b2e48268f5ed4d3eb751fe24cc833e9221 the parsing of the environment files was moved to `parseDynamicFlags`, under the assumption it was typically only called once. It turns out not to be true in GHCi and this led to continually reparsing the environment file whenever a new option was set, the options were appended to the package state and hence all packages reloaded, as it looked like the options were changed. The simplest fix seems to be a clearer specification: > Package environment files are only loaded in GHCi during initialisation. Fixes #19650 (cherry picked from commit 40d2843686ecb08f9fce8691b833ba6517cfc6ec)
-rw-r--r--docs/users_guide/packages.rst4
-rw-r--r--ghc/GHCi/UI.hs8
-rw-r--r--testsuite/tests/ghci/scripts/Makefile4
-rw-r--r--testsuite/tests/ghci/scripts/T19650.script1
-rw-r--r--testsuite/tests/ghci/scripts/T19650.stdout1
-rwxr-xr-xtestsuite/tests/ghci/scripts/all.T8
6 files changed, 24 insertions, 2 deletions
diff --git a/docs/users_guide/packages.rst b/docs/users_guide/packages.rst
index 837a444a74..ff6953ac8c 100644
--- a/docs/users_guide/packages.rst
+++ b/docs/users_guide/packages.rst
@@ -536,6 +536,10 @@ or ``ghci`` that are local to a shell session or to some file system location.
They are intended to be managed by build/package tools, to enable ``ghc`` and
``ghci`` to automatically use an environment created by the tool.
+In the case of ``ghci``, the environment file will be read once, during
+initialisation. If the file changes then you have to restart GHCi to reflect
+the updated file.
+
The file contains package IDs and optionally package databases, one directive
per line:
diff --git a/ghc/GHCi/UI.hs b/ghc/GHCi/UI.hs
index edd473bba9..c707bd4ee7 100644
--- a/ghc/GHCi/UI.hs
+++ b/ghc/GHCi/UI.hs
@@ -3028,13 +3028,17 @@ setOptions wds =
-- then, dynamic flags
when (not (null minus_opts)) $ newDynFlags False minus_opts
+-- | newDynFlags will *not* read package environment files, therefore we
+-- use 'parseDynamicFlagsCmdLine' rather than 'parseDynamicFlags'. This
+-- function is called very often and results in repeatedly loading
+-- environment files (see #19650)
newDynFlags :: GhciMonad m => Bool -> [String] -> m ()
newDynFlags interactive_only minus_opts = do
let lopts = map noLoc minus_opts
logger <- getLogger
idflags0 <- GHC.getInteractiveDynFlags
- (idflags1, leftovers, warns) <- GHC.parseDynamicFlags logger idflags0 lopts
+ (idflags1, leftovers, warns) <- DynFlags.parseDynamicFlagsCmdLine idflags0 lopts
liftIO $ handleFlagWarnings logger idflags1 warns
when (not $ null leftovers)
@@ -3050,7 +3054,7 @@ newDynFlags interactive_only minus_opts = do
dflags0 <- getDynFlags
when (not interactive_only) $ do
- (dflags1, _, _) <- liftIO $ GHC.parseDynamicFlags logger dflags0 lopts
+ (dflags1, _, _) <- liftIO $ DynFlags.parseDynamicFlagsCmdLine dflags0 lopts
must_reload <- GHC.setProgramDynFlags dflags1
-- if the package flags changed, reset the context and link
diff --git a/testsuite/tests/ghci/scripts/Makefile b/testsuite/tests/ghci/scripts/Makefile
index 40ba561f69..a76b8c090c 100644
--- a/testsuite/tests/ghci/scripts/Makefile
+++ b/testsuite/tests/ghci/scripts/Makefile
@@ -66,3 +66,7 @@ T11389:
T12023:
-'$(TEST_HC)' $(TEST_HC_OPTS_INTERACTIVE) \
-ghci-script T12023.script < /dev/null | grep -c -E '(~#|~R#|~P#)'
+
+.PHONY: T19650_setup
+T19650_setup:
+ '$(GHC_PKG)' latest base > my_package_env
diff --git a/testsuite/tests/ghci/scripts/T19650.script b/testsuite/tests/ghci/scripts/T19650.script
new file mode 100644
index 0000000000..1426870840
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T19650.script
@@ -0,0 +1 @@
+:set -DMAGIC
diff --git a/testsuite/tests/ghci/scripts/T19650.stdout b/testsuite/tests/ghci/scripts/T19650.stdout
new file mode 100644
index 0000000000..4bca5be26b
--- /dev/null
+++ b/testsuite/tests/ghci/scripts/T19650.stdout
@@ -0,0 +1 @@
+Loaded package environment from my_package_env
diff --git a/testsuite/tests/ghci/scripts/all.T b/testsuite/tests/ghci/scripts/all.T
index f38a1738eb..8c5f34fb08 100755
--- a/testsuite/tests/ghci/scripts/all.T
+++ b/testsuite/tests/ghci/scripts/all.T
@@ -332,3 +332,11 @@ test('T19667Ghci', extra_files(['T19667Ghci.hs']), ghci_script, ['T19667Ghci.scr
test('T19688', normal, ghci_script, ['T19688.script'])
test('T20019', normal, ghci_script, ['T20019.script'])
test('T20101', normal, ghci_script, ['T20101.script'])
+test('T19650',
+ [ pre_cmd('$MAKE -s --no-print-directory T19650_setup'),
+ extra_hc_opts('-package-env my_package_env -v1'),
+ # Should only appear once
+ filter_stdout_lines(r'Loaded package env.*')
+ ],
+ ghci_script,
+ ['T19650.script'])