The GHC developers are very pleased to announce the release of GHC 9.10.1.
Binary distributions, source distributions, and documentation are available at downloads.haskell.org and shortly via GHCup.
GHC 9.10 brings a number of new features and improvements, including:
The introduction of the GHC2024 language edition, building upon GHC2021 with the addition of a number of widely-used extensions.
Partial implementation of the GHC Proposal #281, allowing visible
quantification to be used in the types of terms.
Extension of LinearTypes to allow linear let and where
bindings
The implementation of the exception backtrace proposal, allowing the annotation of exceptions with backtraces, as well
as other user-defined context
Further improvements in the info table provenance mechanism, reducing
code size to allow IPE information to be enabled more widely
Javascript FFI support in the WebAssembly backend
Improvements in the fragmentation characteristics of the low-latency
non-moving garbage collector.
ā¦ and many more
A full accounting of changes can be found in the release notes.
As always, GHCās release status, including planned future releases, can
be found on the GHC Wiki status.
We would like to thank GitHub, IOG, the Zw3rk stake pool,
Well-Typed, Tweag I/O, Serokell, Equinix, SimSpace, the Haskell
Foundation, and other anonymous contributors whose on-going financial
and in-kind support has facilitated GHC maintenance and release
management over the years. Finally, this release would not have been
possible without the hundreds of open-source contributors whose work
comprise this release.
As always, do give this release a try and open a ticket if you see
anything amiss.
Thanks to all for their hard work on the release, Iām personally stoked about RequiredTypeArguments! No more need for Proxys or ambiguous types when reifying!!
For a type class variable, the (invisible) quantification must occur before the class head:
class forall a. Storable a where
sizeOf :: Int
There is no way to quantify a differently, and a is already bound in the method. This trick gets around it by using a second (visible) quantifier, and then asserting their equality.
Yes, the use of forall a' -> a ~ a' => ... is a workaround. Ideally we need a syntax to specify that some of class variables need to be quantified visibly in a method. Iāve known about this issue for a long time, hereās an old proposal of mine:
It needs to be refurbished and submitted to the committee. If you read the discussion there you can see the idea wasnāt received as well as I hoped it would, but I still believe itās a solid approach.
Thanks to all the GHC developers for this release. May I ask a couple of questions?
I see the GHC 9.10.1 archive for Windows is 586 MB, compared to ~ 325 MB for GHC 9.6.3 to 9.8.2. Is there a reason for the 80% increase?
I note the new GHC boot packages: ghc-experimental-0.1.0.0, ghc-internal-9.1001.0 (which seems an unusual version number, compared to other GHC boot packages), ghc-platform-0.1.0.0 and ghc-toolchain-0.1.0.0. None of them are documented at 2.1. Version 9.10.1 ā Glasgow Haskell Compiler 9.10.1 User's Guide. Is that an oversight?
BTW, Iāve just experimented a little with GHC 9.10.1 to see something interesting with the new exception backtraces, but I couldnāt see it in action in my toy examples. Hereās what I tried in the end:
Main.hs
import GHC.Internal.Exception.Backtrace
import GHC.Environment
import GHC.Stack
{-# NOINLINE f #-}
f :: HasCallStack => [String] -> [String]
f [x] = error "Some Pesky Error"
f xs = ("def" ++) <$> xs
{-# NOINLINE g #-}
g :: [String] -> IO [String]
g xs = return $ ("abc" ++) <$> f xs
main = do
setBacktraceMechanismState CostCentreBacktrace True
setBacktraceMechanismState HasCallStackBacktrace True
setBacktraceMechanismState ExecutionBacktrace True
setBacktraceMechanismState IPEBacktrace True
args <- getFullArgs
print =<< g args
Hereās the output I got from this program:
$ ghc-9.10 Main.hs && ./Main
[1 of 2] Compiling Main ( Main.hs, Main.o ) [Source file changed]
[2 of 2] Linking Main [Objects changed]
Main: Some Pesky Error
CallStack (from HasCallStack):
error, called at Main.hs:8:9 in main:Main
f, called at Main.hs:13:32 in main:Main
Cost-centre stack backtrace:
IPE backtrace:
HasCallStack backtrace:
collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:128:3 in ghc-internal:GHC.Internal.Exception
What do I need to do in order to observe something interesting in the backtrace lines?
Thatās right, but Iād say HasCallStack backtrace is also āemptyā, because it only displays some stack entries internal to its implementation, it doesnāt even pick up on the HasCallStack constraint of my f (which I already see in the āoldā output).
Iām interested in any way of observing the new backtraces feature in action (i.e. any output with some new information about my exception that we didnāt get pre 9.10).
setBacktraceMechanismState acts as a filter for what gets included in the exception annotation, but the backtrace mechanism itself might need additional setup to work.
For the HasCallStackBacktrace to work, all functions in your call stack need a HasCallStack constraint (in your example, g doesnāt have it).
For the CostCentreBacktrace to work, you need to build your program with profiling support: -prof.
For the ExecutionBacktrace to work, you need to be on Linux and build your program with DWARF support: -g3.
For the IPEBacktrace to work, you need to build your program with info-table provenance: -finfo-table-map.
Iāve added HasCallStack to g and main and Iāve added -g3 -finfo-table-map -prof arguments to ghc while building Main.hs, but Iām still not getting any result:
$ ghc-9.10 Main.hs -g3 -finfo-table-map -prof && ./Main
[1 of 2] Compiling Main ( Main.hs, Main.o )
[2 of 2] Linking Main
Main: Some Pesky Error
CallStack (from HasCallStack):
error, called at Main.hs:9:9 in main:Main
f, called at Main.hs:14:32 in main:Main
g, called at Main.hs:23:13 in main:Main
main, called at Main.hs:17:1 in main:Main
Cost-centre stack backtrace:
IPE backtrace:
HasCallStack backtrace:
collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:128:3 in ghc-internal:GHC.Internal.Exception
Indeed I hope to publish a blog post about this feature soon. I was hoping to have it ready for the release but unfortunately time has been very tight recently.
In short:
HasCallStackBacktrace requires that all functions of interest in the failing branch of the call-graph have a HasCallStack constraint. Unfortunately, it does look like something isnāt quite right in the behavior here. Iāve opened #24807 to track this (and have now fixed it)
CostCentreBacktrace requires not only -prof but also that cost-centres are added to the program (e.g. via a {-# CCS ... #-} pragma or -fprof-auto
ExecutionBacktrace requires DWARF support and that all libraries of your program (e.g. including base) are built with -g. As we see here, if any function in the call-chain does not have debug information the backtrace will be truncated at that frame.
IPEBacktrace requires -finfo-prov-map. In general the more packages that are built with IPE information, the more helpful this backtrace will be. However, unlike ExecutionBacktrace, absence of IPE information for a frame will not truncate the backtrace but rather will simply contribute no useful information.
With a GHC build with IPE and debug information enabled (and the fix noted above), I get the following output from your program:
$ _build-ipe/stage1/bin/ghc hi.hs -g3 -finfo-table-map -prof -fprof-auto -fforce-recomp
$ ./hi h
hi: Some Pesky Error
CallStack (from HasCallStack):
error, called at hi.hs:8:9 in main:Main
f, called at hi.hs:13:32 in main:Main
CallStack (from -prof):
Main.f (hi.hs:(8,1)-(9,24))
Main.g (hi.hs:13:1-35)
Main.main.\ (hi.hs:21:3-18)
Main.main (hi.hs:(15,1)-(21,18))
Cost-centre stack backtrace:
Main.main (hi.hs:(15,1)-(21,18))
Main.main.\ (hi.hs:21:3-18)
Main.g (hi.hs:13:1-35)
Main.f (hi.hs:(8,1)-(9,24))
Native stack backtrace:
set_initial_registers (rts/Libdw.c:294.5) in /mnt/data/exp/ghc/ghc-9.10/hi
dwfl_thread_getframes in
get_one_thread_cb in /nix/store/53nia34f1pqf89idqs4bbm86k0xfgydf-elfutils-0.189/lib/libdw-0.189.so
dwfl_getthreads in /nix/store/53nia34f1pqf89idqs4bbm86k0xfgydf-elfutils-0.189/lib/libdw-0.189.so
dwfl_getthread_frames in /nix/store/53nia34f1pqf89idqs4bbm86k0xfgydf-elfutils-0.189/lib/libdw-0.189.so
libdwGetBacktrace (rts/Libdw.c:263.15) in /mnt/data/exp/ghc/ghc-9.10/hi
_ghczminternal_GHCziInternalziExecutionStackziInternal_sat_s2QY_entry (libraries/ghc-internal/src/GHC/Internal/ExecutionStack/Internal.hsc:217.31) in /mnt/data/exp/ghc/ghc-9.10/hi
stg_keepAlive_frame_info (rts/PrimOps.cmm:2954.1) in /mnt/data/exp/ghc/ghc-9.10/hi
ghczminternal_GHCziInternalziExecutionStackziInternal_collectStackTrace1_info (libraries/ghc-internal/src/GHC/Internal/ExecutionStack/Internal.hsc:86.10) in /mnt/data/exp/ghc/ghc-9.10/hi
ghczminternal_GHCziInternalziExceptionziBacktrace_zdwcollectBacktraces_info (libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs:145.54) in /mnt/data/exp/ghc/ghc-9.10/hi
ghczminternal_GHCziInternalziExceptionziBacktrace_collectBacktraces1_info (libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs:43.9) in /mnt/data/exp/ghc/ghc-9.10/hi
ghczminternal_GHCziInternalziException_errorCallWithCallStackException_info (libraries/ghc-internal/src/GHC/Internal/Exception.hs:122.1) in /mnt/data/exp/ghc/ghc-9.10/hi
stg_marked_upd_frame_info (rts/Updates.cmm:56.1) in /mnt/data/exp/ghc/ghc-9.10/hi
_ghczminternal_GHCziInternalziTopHandler_realzuhandler_r387_entry (libraries/ghc-internal/src/GHC/Internal/TopHandler.hs:188.1) in /mnt/data/exp/ghc/ghc-9.10/hi
stg_catch_frame_info (rts/Exception.cmm:405.1) in /mnt/data/exp/ghc/ghc-9.10/hi
stg_unmaskAsyncExceptionszh_ret_info (rts/Exception.cmm:87.1) in /mnt/data/exp/ghc/ghc-9.10/hi
stg_stop_thread_info (rts/StgStartup.cmm:47.1) in /mnt/data/exp/ghc/ghc-9.10/hi
StgRunIsImplementedInAssembler (rts/StgCRun.c:378.5) in /mnt/data/exp/ghc/ghc-9.10/hi
schedule (rts/Schedule.c:481.13) in /mnt/data/exp/ghc/ghc-9.10/hi
scheduleWaitThread (rts/Schedule.c:2675.11) in /mnt/data/exp/ghc/ghc-9.10/hi
rts_evalLazyIO (rts/RtsAPI.c:565.1) in /mnt/data/exp/ghc/ghc-9.10/hi
hs_main (rts/RtsMain.c:73.18) in /mnt/data/exp/ghc/ghc-9.10/hi
in /mnt/data/exp/ghc/ghc-9.10/hi
__libc_start_call_main in
__libc_start_main@@GLIBC_2.34 in /nix/store/46m4xx889wlhsdj72j38fnlyyvvvvbyb-glibc-2.37-8/lib/libc.so.6
_start in /mnt/data/exp/ghc/ghc-9.10/hi
IPE backtrace:
Cmm$rts/StgStartup.cmm. (:)
Cmm$rts/Exception.cmm. (:)
Cmm$rts/Exception.cmm. (:)
GHC.Internal.TopHandler. (:)
Cmm$rts/Updates.cmm. (:)
GHC.Internal.Exception.bindIO (libraries/ghc-internal/src/GHC/Internal/Base.hs:2246:1-76)
GHC.Internal.Exception.Backtrace. (:)
GHC.Internal.Exception.Backtrace.$ (libraries/ghc-internal/src/GHC/Internal/Base.hs:2180:1-9)
HasCallStack backtrace:
collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:92:13 in ghc-internal:GHC.Internal.Exception
toExceptionWithBacktrace, called at libraries/ghc-internal/src/GHC/Internal/Exception.hs:127:5 in ghc-internal:GHC.Internal.Exception
error, called at hi.hs:8:9 in main:Main
f, called at hi.hs:13:32 in main:Main
In this case, the trivial nature of the test program means that the execution backtraces arenāt particularly helpful. It may be that IPE coverage needs improvement in this case or that we should improve the stack decoderās treatment of primitive stack frame types (e.g. update frames, see #24811, #24812). I havenāt looked closely enough at this program to see why that is but I donāt doubt that there are improvements that could be made here.
An aside: When interpreting IPE and DWARF ābacktracesā one must remember that the execution stack tracks continuations and not call-sites. In contrast to C, where there is a very strong correspondence between continuations and call-sites, in Haskell tail calls are quite common and therefore you will often see the entries from the āfutureā of your program in the backtrace.