This is the twenty-ninth edition of our Haskell ecosystem activities report, which describes the work Well-Typed are doing on GHC, Cabal, HLS and other parts of the core Haskell toolchain. The current edition covers roughly the months of September 2025 to November 2025.

You can find the previous editions collected under the haskell-ecosystem-report tag.

Sponsorship

We offer Haskell Ecosystem Support Packages to provide commercial users with support from Well-Typed’s experts while investing in the Haskell community and its technical ecosystem including through the work described in this report. To find out more, read our announcement of these packages in partnership with the Haskell Foundation. We need funding to continue this essential maintenance work!

Many thanks to our Haskell Ecosystem Supporters: Standard Chartered, Channable and QBayLogic, as well as to our other clients who also contribute to making this work possible: Anduril, Juspay and Mercury; and to the HLS Open Collective for supporting HLS release management.

Team

Ben, who has been a key maintainer of GHC for many years, announced in October that he is moving to a new role that will allow less time for GHC work, though he remains a Partner at Well-Typed. We were delighted to welcome Magnus to the team in November.

The Haskell toolchain team at Well-Typed currently includes:

In addition, many others within Well-Typed contribute to GHC, Cabal and HLS occasionally, or contribute to other open source Haskell libraries and tools. This report includes contributions from Alex Washburn, Tobias Dammers, Wen Kokke and Wolfgang Jeltsch in particular.

GHC

GHC Releases

  • Ben worked on backports for GHC 9.12.3. Zubin continued this work and released rc1 and rc2.
  • Ben worked on backports for GHC 9.14.1, and released alpha1, alpha2, alpha3 and rc1. Zubin continued this work and released rc2 and rc3.
  • An overview of the status of GHC releases is available on the GHC wiki.

Reinstallable Base

  • Matthew has facilitated a period of community discussion about plans for making the base library reinstallable, in order to reduce the coupling between GHC upgrades and library version upgrades. This discussion aims to assess what the consensus is about the project and to establish a shared plan amongst all the stakeholders.

  • Wolfgang and Tobias have been investigating the technical aspects of reinstallable base, including questions such as what concretely it takes to compile an API-identical base with multiple GHC versions, what the testing story for an external base repository would be and which parts of ghc-internal can be moved back to base.

Frontend

  • Sam added error message hints for unsolved HasField constraints. GHC will now provide additional hints for an unsolved constraint of the form HasField fld_name rec_ty fld_ty, such as similar name suggestions for misspelled field names, warnings about record fields that contain existentials or foralls, import suggestions, etc. This is particular useful for users of the OverloadedRecordDot extension (#18776, #22382, #26480, !14952).

  • Magnus worked on fixing several oversights with the initial implementation of ExplicitLevelImports, such as re-instating an erroneously removed level check (#26099, !15053) and addressing a module graph issue (#26568, !15118). He also took the opportunity to better document that area of the codebase (!15117).

  • Sam reworked the way error messages involving invisible components (e.g. the k in Proxy @k ty, or RuntimeRep variables as in TYPE r) are reported, bringing the pretty-printing of multiplicities (from LinearTypes) in line with other invisible components (#26335, #26340, !14761).

  • Sam cleaned up how GHC pulls out TypeError msg when computing insoluble constraints. This makes the code much more consistent, but also improves detection of redundant pattern matches as in #26400 (!14802).

  • Ben added a special case to avoid GHC emitting “unused package” warnings for packages which don’t contain any modules, as such packages are typically used for other purposes such as providing linker flags (#24120, !14965).

  • Sam reviewed Vladislav Zavialov’s work implementing type .. and data .. namespace-specified wildcards from GHC proposal #581 (!15014).

Type-checker plugins

  • Sam made GHC invoke type-checker plugins when running the pattern-match checker. This greatly improves pattern match warnings when using type-checker plugins and dealing with GADTs that involve natural numbers (such as Vec :: Nat -> Type -> Type) (#26395, !14797).

  • Sam added an Outputable Natural instance in the ghc library, useful in particular for type-checking plugins dealing with natural numbers.

Representation polymorphism

  • Sam improved the representation-polymorphism checks to allow function applications in which the representation of the argument is hidden under a type family reduction (such as in #26072). As part of this work, Sam undertook a major overhaul of the typechecking of data constructors as it relates to linear types. The end result is that GHC no longer eta-expands saturated applications of data constructors any, resulting in reduced compilation times (!14357, !14764).

  • Sam fixed an incorrect coercion constructed during representation-polymorphism checking (#26528, !15038).

Other frontend bug fixes

  • Matthew improved error handling in the driver when processing linking nodes, resolving some failures in the T9930fail test (!14964).

  • Sam fixed a GHC panic that could occur when writing Arrow/Category code in which overloaded code is instantiated to the function arrow (->) (#26277, !14760).

  • Sam reverted !14402 in order to fix GHC failing to compile Agda (#26154, !14763).

  • Sam fixed a GHC panic that could occur when reporting an invalid record update in which the record constructor was out of scope (#26391, !14804).

  • Sam fixed a GHC panic that could occur when typechecking a pattern synonym that uses a view pattern (#26465, !14936).

Backend

  • Matthew improved the memory usage of recompilation checking by using OsPath in the getModificationTimeIfExists function (!14917).

  • With the help of Andreas, Sam identified and fixed a long standing serious bug in the Cmm Sink optimisation pass, which is responsible for inlining variable declarations at the Cmm level (#26550, !15041).

  • Sam implemented several fixes relating to register allocation, in particular in relation to tracking formats of registers for the purpose of spilling to the stack (#26542, !15041, #26411, !15121).

  • Sam fixed an oversight in the Cmm liveness analysis pass in which GHC did not properly combine register allocations at different formats (#26595, #26611, !15121).

  • Zubin re-engineered the tags used for Uniques within GHC, making GHC use a proper ADT rather than ad-hoc characters to namespace Uniques (#26246, !14639). This also makes it clearer to plugin authors which tag to use when generating Uniques.

  • Andreas investigated the performance of occurrence analysis, adding a new performance test from #26425 (!14927). Several improvements were then made, such as avoiding space leaks by being a bit more strict (!14928).

  • Andreas added handling of ticks in the sizeExpr computation (!14883).

  • Andreas added a regression test for #26056 (!14719), which had been fixed by his earlier work on the interaction of ticks with unsafeCoerce# (!13413).

  • Matthew made the loading of bytecode static pointer entries more lazy (!14900).

GHCi and bytecode interpreter

  • Matthew added support for bytecode libraries, allowing the bytecode for standard libraries (such as base) to be distributed, which in turns allows the GHCi debugger to step through these libraries (!15062).

  • Matthew added support in GHC for generating bytecode object files (.gbc). This allows compiled bytecode to be cached, improving load times of the interpreter (!14717).

  • Matthew refactored the code involved in loading bytecode in order to unify two code-paths with a lot of duplication (#26459, !14901).

  • Alex worked on issues with the reliance of the bytecode linker on laziness (#25636, !15092).

  • Rodrigo improved the performance of the bytecode interpreter by pruning certain useless sequences of instructions (!14576).

  • Rodrigo changed the breakpoint index from Word16 to Word32 in order to fix #26325 (!14691).

  • Matthew renamed, within the GHC codebase, the “interpreter backend” to the “bytecode backend”, which names what the backend produces rather than the means by which the code will eventually run (!14915).

Trees That Grow

  • Alex has been working on fully realising the vision introduced by the “Trees that Grow” (TTG) paper by making the syntax tree used by GHC fully independent of GHC. This aims at making GHC more modular and potentially making it easier for other Haskell tools to reuse GHC’s syntax tree without acquiring a dependency on the full ghc package.

  • Alex decoupled Language.Haskell.Syntax.Type from depending on GHC.Utils.Panic (#26626, !15134), and initiated preliminary work to decouple other modules in the Language.Haskell namespace from GHC internal modules.

Runtime system and linker

  • With the help of Andreas, Zubin identified and fixed a segfault that would occur on Windows due to DLL name strings getting freed while they were still used (#26613, !15100).

  • Ben added dynamic initialisation of built-in RTS closures in order to address MacOS 26 breakage of -undefined dynamic_lookup (#26166, !14902).

  • Rodrigo moved certain symbols from ghc-internal to the rts package, as part of the effort to address the aforementioned MacOS 26 breakage (!14956).

  • Ben improved how the RTS deals with address space reservations in low memory, avoiding potential loops (#26151, !14466).

  • Matthew fixed a deadlock that could occur when the RTS was shutting down while trying to emit eventlogs (#26573, !15068).

  • Ben fixed a runtime loop that could occur with the non-moving garbage collector by using atomic operations (#26053, !14519).

  • Rodrigo dropped some obsolete logic in the RTS relating to Windows DLLs (!14873).

  • Hannes fixed an off-by-one error in an assertion in the RTS (!15019).

Profiling

  • Hannes enabled the stack frame annotation mechanisms by default for IPE backtraces (#26218, !14721).

  • Hannes moved the implementation of stack decoding logic from ghc-heap to ghc-internal, in order to allow its usage in GHC.Stack.CloneStack in base (!14543).

  • Matthew implemented several fixes to the stack decoding logic when using the profiled runtime (#26507, !14991).

  • Building on previous work by Finley McIlwaine, Hannes introduced the -fno-distinct-constructor-tables and -fdistinct-constructor-tables-only flags which provide more granular control over which constructors get different info tables when using info-table profiling (#23703, !14705). This is useful as -fdistinct-constructor-tables can lead to unreasonably large binary sizes in some projects.

Template Haskell

  • Ben improved the documentation of getQ from the template-haskell library to better reflect its semantics (#26484, !14970).

  • Sam improved the Template Haskell compatibility story for the new “expressions in specialise pragmas” patch by using a pattern synonym to avoid breaking existing Template Haskell code (#26356, !14729).

Build system and packaging

  • Andreas fixed a bug with long paths on Windows when invoking GHC to gather module dependency information (!15060).

  • Rodrigo made further progress on removing global settings files in favour of per-target configuration (#26227, !14554).

  • Rodrigo ensures that flags such as CFLAGS apply only to the build phase, and are not carried over to target settings (#25637, !14854).

  • Rodrigo deleted some stale settings from the Hadrian bindist configure script (#26478, !14937).

  • Ben fixed zstd-enabled builds (#26312, !14693).

  • Ben fixed inconsistencies in configure checks relating to C compilers (#26394, !14796).

  • Ben fixed a build failure caused by Clang warning on implicit constant arrays (#26502, !14971).

  • Ben made a change to the order of arguments when building with Hadrian (#25281, !14318). Thanks to Cheng Shao for helping land this work.

  • Andreas added hpc to the release script (!15056).

CI and testing

  • In an ongoing general effort to improve CI stability in nightly pipelines, Magnus fixed several issues with the CI to make nightly GHC builds available again. This included fixing the Debian 9 CI job, which was failing due to a small Python issue (!15127).

  • Andreas improved the jspace test to be less flaky, fixing a recurrent issue with AArch64 LLVM jobs in CI (#25401, !14837).

  • Zubin added support for testsuite output files that depend on the testsuite way, fixing test failures that used the external interpreter (#26552, !15078).

  • Zubin addressed an issue in which spurious linker warnings were causing testsuite failures (#26349, !14615).

  • Zubin fixed the links to -fno-xxx flags in the user’s guide (#26352,!14794).

  • Sam fixed a Unix vs Windows filepath issue with the codes test (which checks test coverage of error codes). This makes the test more robust on Windows (#25178, !14778).

  • Ben made whether a job is a release job into a GitLab “input”, facilitating release management for maintainers (!14933).

  • Ben disabled split sections on FreeBSD in order to fix CI failures on FreeBSD (#26303, !14782).

  • Matthew made some changes to the testsuite driver to allow some tests to run only with GHCi (!14914).

  • Rodrigo made some progress on fixing the test-reinstall jobs which tests compilation of GHC using cabal (#26202, !14518).

Infrastructure

  • Ben migrated ghcup-metadata jobs to run on the new OpenCape CI runners (!14814).

  • Magnus set up new Windows x86 runners and improved stability and observability of the GHC GitLab instance.

Haddock

  • Sam made several changes to the information stored in interface files for data constructors, in order to improve Haddock output. This allows Haddock to display the user-written kind signature (instead of aggressively expanding type synonyms), as well as preserve user-written type variable names (#26246, !14868).

Cabal

  • Mikolaj took part in the preparation of the upcoming Cabal release 3.16.1.0.

  • Matthew helped on the Cabal issue tracker and reviewed PRs from other Cabal contributors.

  • Matthew wrote up a Cabal proposal to add support for bytecode library files and bytecode object files.

  • Matthew fixed two issues reported in #11107 that occur when starting an interactive session with cabal repl (PR #11237).

Haskell Language Server

  • Zubin prepared the release of HLS 2.12.0.0 (PR #4728).

  • Hannes fixed a bug in which GHC plugins aren’t loaded for files that are checked in the background (#4631, PR #4749).

  • Hannes and Andreas diagnosed a recurrent segfault that turned out to be caused by how the ghc-lib-parser library would re-use shared CAFs defined in the RTS but expecting a different memory layout due to API changes in between GHC versions (HLS issue #4674, GHC tickets #26033 and #26553).

Haskell Debugger

  • Rodrigo continued work on the new Haskell Debugger. The debugger will first be compatible with the upcoming GHC 9.14 release, and we’ll be looking forward to you all trying it out.

  • Rodrigo presented the debugger at MuniHac in a tutorial oriented for users. The recording is available here.

  • A detailed list of improvements to the debugger can be found in the changelog. Notably:

    • Several robustness fixes and bug fixes
    • Support for stepping-out of functions
    • Conditional and hit conditional breakpoints
    • Proxy program which runs on the terminal to allow passing input to the debuggee
  • Matthew and Rodrigo worked on allowing customisation of how the debugger displays user values. By instantiating the DebugView type class for your data type, you can control how the debugger expands and displays the value in the debugger.

Live monitoring using the eventlog

  • Wen has been working on improvements to eventlog-live, a collection of libraries and tools for the live profiling of Haskell applications using the eventlog-socket library to stream data from the eventlog to an external monitoring process.

  • Matthew has implemented support for creating TCP sockets and increased the testing coverage of the eventlog-socket library (PR #18).

  • The socket created can now be used bidirectionally using a control protocol to instruct the monitored process for further heap profiling information (PR #20). In future work, the protocol will be extended to allow other libraries to register commands.