bug in ghci module loading post 9.12.4?
I recently upgraded from ghc 9.2 to 9.6 (I know, I'm slow), and one of the things I was looking forward to was better recompilation avoidance, that wouldn't be fooled by spurious mtime changes that are common with with e.g. git branch switches. Unfortunately, it seems to have gotten buggy at the same time! I upgraded again to 9.12.4 and it looks like it's still buggy. Either that or I'm doing things wrong somehow. Here's a repro, it requires 3 modules: % cat >BugA.hs module BugA where x :: Int x = 13 % cat >BugB.hs module BugB where import qualified BugA f :: IO () f = print BugA.x % cat >BugC.hs module BugC where import qualified BugB bug :: IO () bug = BugB.f % ghci -fobject-code # compile so we can load .o GHCi, version 9.12.4: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/elaforge/qlib/dotfiles/.ghci Prelude> :load BugC [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [2 of 3] Compiling BugB ( BugB.hs, BugB.o ) [3 of 3] Compiling BugC ( BugC.hs, BugC.o ) Ok, three modules loaded. Leaving GHCi. % ghci Prelude> :load BugC Ok, three modules loaded. Prelude BugC> bug 13 As expected! Now go edit BugA.hs, and change 13 to say 14, and save. Now reload: Prelude BugC> :r [1 of 3] Compiling BugA ( BugA.hs, interpreted ) [Source file changed] Ok, three modules reloaded. Prelude BugC> bug 13 So that's not right! This will also cause linking errors if something was removed, though it's easier to reproduce the stale values. For my interpretation of what's going on, I believe previously it would have also reloaded BugB. While it has noticed that BugA must be reloaded (and switched to bytecode), it hasn't noticed that BugB is in the dependency path and should also be reloaded, and possibly winds up using stale values inlined into BugB.o. Is it a bug?
On Tue, Jun 23, 2026 at 01:07:58AM -0700, Evan Laforge wrote:
Loaded GHCi configuration from /Users/elaforge/qlib/dotfiles/.ghci Prelude> :load BugC [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [2 of 3] Compiling BugB ( BugB.hs, BugB.o ) [3 of 3] Compiling BugC ( BugC.hs, BugC.o ) Ok, three modules loaded. Leaving GHCi. % ghci Prelude> :load BugC Ok, three modules loaded. Prelude BugC> bug 13
As expected! Now go edit BugA.hs, and change 13 to say 14, and save. Now reload:
Prelude BugC> :r [1 of 3] Compiling BugA ( BugA.hs, interpreted ) [Source file changed] Ok, three modules reloaded. Prelude BugC> bug 13
I am unable to reproduce the above with either GHC 9.12.4 or GHC 9.14.1 on a Fedora 43 x86_64 system. Every change in BugA.hs changes the output of "bug" after a ":r" reload. $ tail -n1 BugA.hs x = 17 $ ghci -fobject-code GHCi, version 9.12.4: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/viktor/.ghc/ghci.conf λ> :load BugC [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [2 of 3] Compiling BugB ( BugB.hs, BugB.o ) [3 of 3] Compiling BugC ( BugC.hs, BugC.o ) Ok, three modules loaded. λ> bug 17 λ> [1]+ Stopped ghci -fobject-code $ perl -pi -e 's/17/18/' BugA.hs $ tail -n1 BugA.hs x = 18 $ fg ghci -fobject-code λ> :r [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [Source file changed] Ok, three modules reloaded. λ> bug 18 λ> Leaving GHCi. -- Viktor. 🇺🇦 Слава Україні!
I tried your reproducer with GHC 9.10.2, 9.12.2 and 9.12.4 and GHCi picked up the changes to BugA every time: ghci> bug 10 ghci> :r [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [Source file changed] Ok, three modules reloaded. ghci> bug 11 Which platform/OS are you building on and how did you obtain GHC? On 26/06/23 01:07, Evan Laforge wrote:
I recently upgraded from ghc 9.2 to 9.6 (I know, I'm slow), and one of the things I was looking forward to was better recompilation avoidance, that wouldn't be fooled by spurious mtime changes that are common with with e.g. git branch switches. Unfortunately, it seems to have gotten buggy at the same time! I upgraded again to 9.12.4 and it looks like it's still buggy. Either that or I'm doing things wrong somehow. Here's a repro, it requires 3 modules:
% cat >BugA.hs module BugA where
x :: Int x = 13 % cat >BugB.hs module BugB where import qualified BugA
f :: IO () f = print BugA.x % cat >BugC.hs module BugC where import qualified BugB
bug :: IO () bug = BugB.f
% ghci -fobject-code # compile so we can load .o GHCi, version 9.12.4: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/elaforge/qlib/dotfiles/.ghci Prelude> :load BugC [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [2 of 3] Compiling BugB ( BugB.hs, BugB.o ) [3 of 3] Compiling BugC ( BugC.hs, BugC.o ) Ok, three modules loaded. Leaving GHCi. % ghci Prelude> :load BugC Ok, three modules loaded. Prelude BugC> bug 13
As expected! Now go edit BugA.hs, and change 13 to say 14, and save. Now reload:
Prelude BugC> :r [1 of 3] Compiling BugA ( BugA.hs, interpreted ) [Source file changed] Ok, three modules reloaded. Prelude BugC> bug 13
So that's not right! This will also cause linking errors if something was removed, though it's easier to reproduce the stale values.
For my interpretation of what's going on, I believe previously it would have also reloaded BugB. While it has noticed that BugA must be reloaded (and switched to bytecode), it hasn't noticed that BugB is in the dependency path and should also be reloaded, and possibly winds up using stale values inlined into BugB.o.
Is it a bug? _______________________________________________ Haskell-Cafe mailing list -- haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
On Tue, Jun 23, 2026 at 6:44 AM Zubin Duggal <zubin@well-typed.com> wrote:
Which platform/OS are you building on and how did you obtain GHC?
Oh I should have mentioned, it's OSX, 26.5.1. Obtained via ghcup, and using the "ghcup" channel rather than vanilla. However, I just tested this with linux on a GCP VM and ghc 9.10.3 and I still see the issue. One thing, I see in your non-reproduction that it says "[1 of 3] Compiling BugA ( BugA.hs, BugA.o )", which implies -fobject-code is still on. The bug only seems to happen when you are in bytecode mode, but there are .o files available to load, so you'd have to restart ghci without -fobject-code.
On Tue, Jun 23, 2026 at 10:48 AM Evan Laforge <qdunkan@gmail.com> wrote:
On Tue, Jun 23, 2026 at 6:44 AM Zubin Duggal <zubin@well-typed.com> wrote:
Which platform/OS are you building on and how did you obtain GHC?
Oh I should have mentioned, it's OSX, 26.5.1. Obtained via ghcup, and using the "ghcup" channel rather than vanilla.
However, I just tested this with linux on a GCP VM and ghc 9.10.3 and I still see the issue. One thing, I see in your non-reproduction that it says "[1 of 3] Compiling BugA ( BugA.hs, BugA.o )", which implies -fobject-code is still on. The bug only seems to happen when you are in bytecode mode, but there are .o files available to load, so you'd have to restart ghci without -fobject-code.
Hate to nag but... has anyone managed to reproduce it? I can make it happen on linux and OSX, and I can verify that it doesn't happen in 9.2.8, and that it starts happening at 9.4. I believe this is when ghc got a new recompilation avoidance mechanism that was supposed to use hashes instead of mtimes, so that's my guess about what introduced it. I guess I can go ahead and file a bug on gitlab now. I'm pretty sure now it's a bug so I guess I don't need to wait for someone else to repro but it would be nice to verify... Since permanently leaving on -fobject-code seems to be a workaround and processors are so fast now, I may just leave that flag on now. I'm surprised more people haven't run into this problem in the years since 9.4.
I can reproduce on my Arch Linux system, also with 9.14.1. cat >A.hs <<EOF module A where x :: Int x = 13 EOF cat >B.hs <<EOF module B where import qualified A f :: IO () f = print A.x EOF cat >C.hs <<EOF module C where import qualified B bug :: IO () bug = B.f EOF ghci -fobject-code :load C
[1 of 3] Compiling A ( A.hs, A.o )[main] [2 of 3] Compiling B ( B.hs, B.o )[main] [3 of 3] Compiling C ( C.hs, C.o )[interactive-session] Ok, three modules loaded. :q
ghci :load C
Ok, three modules loaded. bug -- yields 13 -- update A.hs to say 14 :r [1 of 3] Compiling A ( A.hs, interpreted )[main] [Source file changed] Ok, three modules reloaded. bug -- yields 13 again :q
rm *.o ghci :load C
[1 of 3] Compiling A ( A.hs, interpreted )[main] [Source file changed] [2 of 3] Compiling B ( B.hs, interpreted )[main] [Missing bytecode] [3 of 3] Compiling C ( C.hs, interpreted )[interactive-session] [Missing bytecode] Ok, three modules loaded. bug -- yields 14 -- update A.hs to say 15 :r [1 of 3] Compiling A ( A.hs, interpreted )[main] [Source file changed] Ok, three modules reloaded. bug -- yields 15
So it's really only happening if C (and/or B) is loaded from object code, in which case they seem to not be reloaded when a depended-on module is now reloaded in a different mode (namely interpreted). - Tom On 30/06/2026 08:30, Evan Laforge wrote:
On Tue, Jun 23, 2026 at 10:48 AM Evan Laforge <qdunkan@gmail.com> wrote:
On Tue, Jun 23, 2026 at 6:44 AM Zubin Duggal <zubin@well-typed.com> wrote:
Which platform/OS are you building on and how did you obtain GHC? Oh I should have mentioned, it's OSX, 26.5.1. Obtained via ghcup, and using the "ghcup" channel rather than vanilla.
However, I just tested this with linux on a GCP VM and ghc 9.10.3 and I still see the issue. One thing, I see in your non-reproduction that it says "[1 of 3] Compiling BugA ( BugA.hs, BugA.o )", which implies -fobject-code is still on. The bug only seems to happen when you are in bytecode mode, but there are .o files available to load, so you'd have to restart ghci without -fobject-code. Hate to nag but... has anyone managed to reproduce it? I can make it happen on linux and OSX, and I can verify that it doesn't happen in 9.2.8, and that it starts happening at 9.4. I believe this is when ghc got a new recompilation avoidance mechanism that was supposed to use hashes instead of mtimes, so that's my guess about what introduced it.
I guess I can go ahead and file a bug on gitlab now. I'm pretty sure now it's a bug so I guess I don't need to wait for someone else to repro but it would be nice to verify...
Since permanently leaving on -fobject-code seems to be a workaround and processors are so fast now, I may just leave that flag on now. I'm surprised more people haven't run into this problem in the years since 9.4. _______________________________________________ Haskell-Cafe mailing list -- haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
fwiw I can't duplicate on MacOS 26.5.2 and ghc 9.12.5 rc2: ghci -fobject-code Loaded package environment from /Users/gcolpitts/.ghc/aarch64-darwin-9.12.4.20260614/environments/default GHCi, version 9.12.4.20260614: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/gcolpitts/.ghci λ> :load BugC [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [2 of 3] Compiling BugB ( BugB.hs, BugB.o ) [3 of 3] Compiling BugC ( BugC.hs, BugC.o ) Ok, three modules loaded. (0.41 secs,) λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup 13 it :: () (3.58 secs, 70,664 bytes) λ> :r [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [Source file changed] Ok, three modules reloaded. λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup 14 it :: () (0.34 secs, 67,952 bytes) On Tue, Jun 30, 2026 at 4:31 AM Evan Laforge <qdunkan@gmail.com> wrote:
On Tue, Jun 23, 2026 at 10:48 AM Evan Laforge <qdunkan@gmail.com> wrote:
On Tue, Jun 23, 2026 at 6:44 AM Zubin Duggal <zubin@well-typed.com>
wrote:
Which platform/OS are you building on and how did you obtain GHC?
Oh I should have mentioned, it's OSX, 26.5.1. Obtained via ghcup, and using the "ghcup" channel rather than vanilla.
However, I just tested this with linux on a GCP VM and ghc 9.10.3 and I still see the issue. One thing, I see in your non-reproduction that it says "[1 of 3] Compiling BugA ( BugA.hs, BugA.o )", which implies -fobject-code is still on. The bug only seems to happen when you are in bytecode mode, but there are .o files available to load, so you'd have to restart ghci without -fobject-code.
Hate to nag but... has anyone managed to reproduce it? I can make it happen on linux and OSX, and I can verify that it doesn't happen in 9.2.8, and that it starts happening at 9.4. I believe this is when ghc got a new recompilation avoidance mechanism that was supposed to use hashes instead of mtimes, so that's my guess about what introduced it.
I guess I can go ahead and file a bug on gitlab now. I'm pretty sure now it's a bug so I guess I don't need to wait for someone else to repro but it would be nice to verify...
Since permanently leaving on -fobject-code seems to be a workaround and processors are so fast now, I may just leave that flag on now. I'm surprised more people haven't run into this problem in the years since 9.4. _______________________________________________ Haskell-Cafe mailing list -- haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
An essential component of the reproducer is that you close ghci after the first :load (which serves only to generate the .o files) and reopen it without -fobject-code, so that the reload of BugA turns it into an interpreted module. On 30/06/2026 13:53, George Colpitts wrote:
fwiw I can't duplicate on MacOS 26.5.2 and ghc 9.12.5 rc2:
ghci -fobject-code Loaded package environment from /Users/gcolpitts/.ghc/aarch64-darwin-9.12.4.20260614/environments/default GHCi, version 9.12.4.20260614: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/gcolpitts/.ghci λ> :load BugC [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [2 of 3] Compiling BugB ( BugB.hs, BugB.o ) [3 of 3] Compiling BugC ( BugC.hs, BugC.o ) Ok, three modules loaded. (0.41 secs,) λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup 13 it :: () (3.58 secs, 70,664 bytes) λ> :r [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [Source file changed] Ok, three modules reloaded. λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup 14 it :: () (0.34 secs, 67,952 bytes)
On Tue, Jun 30, 2026 at 4:31 AM Evan Laforge <qdunkan@gmail.com> wrote:
On Tue, Jun 23, 2026 at 10:48 AM Evan Laforge <qdunkan@gmail.com> wrote: > > On Tue, Jun 23, 2026 at 6:44 AM Zubin Duggal <zubin@well-typed.com> wrote: > > Which platform/OS are you building on and how did you obtain > > GHC? > > Oh I should have mentioned, it's OSX, 26.5.1. Obtained via ghcup, and > using the "ghcup" channel rather than vanilla. > > However, I just tested this with linux on a GCP VM and ghc 9.10.3 and > I still see the issue. One thing, I see in your non-reproduction that > it says "[1 of 3] Compiling BugA ( BugA.hs, BugA.o )", > which implies -fobject-code is still on. The bug only seems to happen > when you are in bytecode mode, but there are .o files available to > load, so you'd have to restart ghci without -fobject-code.
Hate to nag but... has anyone managed to reproduce it? I can make it happen on linux and OSX, and I can verify that it doesn't happen in 9.2.8, and that it starts happening at 9.4. I believe this is when ghc got a new recompilation avoidance mechanism that was supposed to use hashes instead of mtimes, so that's my guess about what introduced it.
I guess I can go ahead and file a bug on gitlab now. I'm pretty sure now it's a bug so I guess I don't need to wait for someone else to repro but it would be nice to verify...
Since permanently leaving on -fobject-code seems to be a workaround and processors are so fast now, I may just leave that flag on now. I'm surprised more people haven't run into this problem in the years since 9.4. _______________________________________________ Haskell-Cafe mailing list -- haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list --haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
Interesting. On ghc 9.12.5 rc2 in the second ghci session I get the following error λ> :load BugC [1 of 3] Compiling BugA ( BugA.hs, interpreted ) [Source file changed] Ok, three modules loaded. (0.01 secs,) λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup GHC.Linker.Loader.dynLoadObjs: Loading temp shared object failed During interactive linking, GHCi couldn't find the following symbol: dlopen(/var/folders/n0/sz8qwjxd1rv1_0h1r16xr2_c0000gp/T/ghc9044_tmp_0_0/libghc_tmp_3.dylib, 0x0005): symbol not found in flat namespace '_BugA_x_closure' This may be due to you not asking GHCi to load extra object files, archives or DLLs needed by your current session. Restart GHCi, specifying the missing library using the -L/path/to/object/dir and -lmissinglibname flags, or simply by naming the relevant files on the GHCi command line. Alternatively, this link failure might indicate a bug in GHCi. If you suspect the latter, please report this as a GHC bug: https://www.haskell.org/ghc/reportabug On Tue, Jun 30, 2026 at 12:27 PM Tom Smeding <x@tomsmeding.com> wrote:
An essential component of the reproducer is that you close ghci after the first :load (which serves only to generate the .o files) and reopen it without -fobject-code, so that the reload of BugA turns it into an interpreted module.
On 30/06/2026 13:53, George Colpitts wrote:
fwiw I can't duplicate on MacOS 26.5.2 and ghc 9.12.5 rc2:
ghci -fobject-code Loaded package environment from /Users/gcolpitts/.ghc/aarch64-darwin-9.12.4.20260614/environments/default GHCi, version 9.12.4.20260614: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/gcolpitts/.ghci λ> :load BugC [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [2 of 3] Compiling BugB ( BugB.hs, BugB.o ) [3 of 3] Compiling BugC ( BugC.hs, BugC.o ) Ok, three modules loaded. (0.41 secs,) λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup 13 it :: () (3.58 secs, 70,664 bytes) λ> :r [1 of 3] Compiling BugA ( BugA.hs, BugA.o ) [Source file changed] Ok, three modules reloaded. λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup 14 it :: () (0.34 secs, 67,952 bytes)
On Tue, Jun 30, 2026 at 4:31 AM Evan Laforge <qdunkan@gmail.com> wrote:
On Tue, Jun 23, 2026 at 10:48 AM Evan Laforge <qdunkan@gmail.com> wrote:
On Tue, Jun 23, 2026 at 6:44 AM Zubin Duggal <zubin@well-typed.com>
wrote:
Which platform/OS are you building on and how did you obtain GHC?
Oh I should have mentioned, it's OSX, 26.5.1. Obtained via ghcup, and using the "ghcup" channel rather than vanilla.
However, I just tested this with linux on a GCP VM and ghc 9.10.3 and I still see the issue. One thing, I see in your non-reproduction that it says "[1 of 3] Compiling BugA ( BugA.hs, BugA.o )", which implies -fobject-code is still on. The bug only seems to happen when you are in bytecode mode, but there are .o files available to load, so you'd have to restart ghci without -fobject-code.
Hate to nag but... has anyone managed to reproduce it? I can make it happen on linux and OSX, and I can verify that it doesn't happen in 9.2.8, and that it starts happening at 9.4. I believe this is when ghc got a new recompilation avoidance mechanism that was supposed to use hashes instead of mtimes, so that's my guess about what introduced it.
I guess I can go ahead and file a bug on gitlab now. I'm pretty sure now it's a bug so I guess I don't need to wait for someone else to repro but it would be nice to verify...
Since permanently leaving on -fobject-code seems to be a workaround and processors are so fast now, I may just leave that flag on now. I'm surprised more people haven't run into this problem in the years since 9.4. _______________________________________________ Haskell-Cafe mailing list -- haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list -- haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list -- haskell-cafe@haskell.org To (un)subscribe, modify options or view archives go to: Only members subscribed via the mailman list are allowed to post.
Ok, thanks for indulging me! Next step, get gitlab login to cooperate! I'll try the ghc mailing list on that one since that's where I've seen talk about gitlab problems. On Tue, Jun 30, 2026 at 11:09 AM George Colpitts <george.colpitts@gmail.com> wrote:
λ> bug ld: warning: duplicate -rpath '/opt/homebrew/Cellar/gcc/15.2.0_1/lib/gcc/current/gcc/aarch64-apple-darwin25/15' ignored ld: warning: -U option is redundant when using -undefined dynamic_lookup
GHC.Linker.Loader.dynLoadObjs: Loading temp shared object failed
Yep, this is also a symptom of the same issue. Well the ld warnings I think are just harmless OSX/ghc mismatches, but I see the "symbol not found" stuff pretty regularly.
participants (5)
-
Evan Laforge -
George Colpitts -
Tom Smeding -
Viktor Dukhovni -
Zubin Duggal