From d193accdad1e30733f02bb474ecb45180a73bf71 Mon Sep 17 00:00:00 2001 From: nineonine Date: Sat, 14 Nov 2020 23:29:00 -0800 Subject: [PATCH] Force module recompilation if '*' prefix was used to load modules in ghci (#8042) Usually pre-compiled code is preferred to be loaded in ghci if available, which means that if we try to load module with '*' prefix and compilation artifacts are available on disc (.o and .hi files) or the source code was untouched, the driver would think no recompilation is required. Therefore, we need to force recompilation so that desired byte-code is generated and loaded. Forcing in this case should be ok, since this is what happens for interpreted code anyways when reloading modules. --- compiler/GHC/Driver/Pipeline.hs | 13 ++++++++++--- testsuite/tests/ghci/scripts/T8042recomp.script | 7 +++++++ testsuite/tests/ghci/scripts/T8042recomp.stdout | 6 ++++++ testsuite/tests/ghci/scripts/all.T | 1 + 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/ghci/scripts/T8042recomp.script create mode 100644 testsuite/tests/ghci/scripts/T8042recomp.stdout diff --git a/compiler/GHC/Driver/Pipeline.hs b/compiler/GHC/Driver/Pipeline.hs index a2dc71d9576..8aacefe0c99 100644 --- a/compiler/GHC/Driver/Pipeline.hs +++ b/compiler/GHC/Driver/Pipeline.hs @@ -340,14 +340,18 @@ compileOne' m_tc_result mHscMessage current_dir = takeDirectory basename old_paths = includePaths dflags2 !prevailing_dflags = hsc_dflags hsc_env0 + loadAsByteCode + | Just (Target _ obj _) <- findTarget summary (hsc_targets hsc_env0) + , not obj + = True + | otherwise = False -- Figure out which backend we're using (bcknd, dflags3) -- #8042: When module was loaded with `*` prefix in ghci, but DynFlags -- suggest to generate object code (which may happen in case -fobject-code -- was set), force it to generate byte-code. This is NOT transitive and -- only applies to direct targets. - | Just (Target _ obj _) <- findTarget summary (hsc_targets hsc_env0) - , not obj + | loadAsByteCode = (Interpreter, dflags2 { backend = Interpreter }) | otherwise = (backend dflags, dflags2) @@ -363,7 +367,10 @@ compileOne' m_tc_result mHscMessage -- -fforce-recomp should also work with --make force_recomp = gopt Opt_ForceRecomp dflags source_modified - | force_recomp = SourceModified + -- #8042: Usually pre-compiled code is preferred to be loaded in ghci + -- if available. So, if the "*" prefix was used, force recompilation + -- to make sure byte-code is loaded. + | force_recomp || loadAsByteCode = SourceModified | otherwise = source_modified0 always_do_basic_recompilation_check = case bcknd of diff --git a/testsuite/tests/ghci/scripts/T8042recomp.script b/testsuite/tests/ghci/scripts/T8042recomp.script new file mode 100644 index 00000000000..d8fa2b54cc0 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T8042recomp.script @@ -0,0 +1,7 @@ +:set -v1 +System.IO.writeFile "T8042B.hs" "module T8042B where { fooB = \"T8042B\"; }" +System.IO.writeFile "T8042A.hs" "module T8042A where { import T8042B; run = putStrLn fooB }" +:set -fobject-code +:load T8042A +:load *T8042A +:break run diff --git a/testsuite/tests/ghci/scripts/T8042recomp.stdout b/testsuite/tests/ghci/scripts/T8042recomp.stdout new file mode 100644 index 00000000000..49250577dc0 --- /dev/null +++ b/testsuite/tests/ghci/scripts/T8042recomp.stdout @@ -0,0 +1,6 @@ +[1 of 2] Compiling T8042B ( T8042B.hs, T8042B.o ) +[2 of 2] Compiling T8042A ( T8042A.hs, T8042A.o ) +Ok, two modules loaded. +[2 of 2] Compiling T8042A ( T8042A.hs, interpreted ) +Ok, two modules loaded. +Breakpoint 0 activated at T8042A.hs:1:44-56 diff --git a/testsuite/tests/ghci/scripts/all.T b/testsuite/tests/ghci/scripts/all.T index 29b01a0b0c9..6fec18bd920 100755 --- a/testsuite/tests/ghci/scripts/all.T +++ b/testsuite/tests/ghci/scripts/all.T @@ -175,6 +175,7 @@ test('T7873', normal, ghci_script, ['T7873.script']) test('T7939', normal, ghci_script, ['T7939.script']) test('T7894', normal, ghci_script, ['T7894.script']) test('T8042', normal, ghci_script, ['T8042.script']) +test('T8042recomp', normal, ghci_script, ['T8042recomp.script']) test('T8116', normal, ghci_script, ['T8116.script']) test('T8113', normal, ghci_script, ['T8113.script']) test('T8172', when(opsys('mingw32'), normalise_drive_letter), -- GitLab