[Git][ghc/ghc][wip/T27724] 20 commits: rts: Fix missing memory barrier in eval_thunk_selector (#27477)
by Simon Peyton Jones (@simonpj) 15 Sep '26
by Simon Peyton Jones (@simonpj) 15 Sep '26
15 Sep '26
Simon Peyton Jones pushed to branch wip/T27724 at Glasgow Haskell Compiler / GHC
Commits:
06eee015 by Luite Stegeman at 2026-09-08T06:03:06+02:00
rts: Fix missing memory barrier in eval_thunk_selector (#27477)
unchain_thunk_selectors() was missing an ACQUIRE_LOAD for the
indirectee, leading to segfaults and corruption during GC on
weakly-ordered architectures.
Fixes #27477
- - - - -
f8b2bd8f by Alan Zimmerman at 2026-09-08T09:39:12-04:00
EPA Fix HsCmdDo exact print with comments
Exact printing of HsCmdDo was ignoring the location for the do
statements, and this is an annotation that can have comments in it.
Update it so we print the statements as a unit, including any
comments.
Also add the result of auditing that we capture comments in all needed
places, noting that the remaining Anno SrcSpan instances are benign.
- - - - -
430967ab by Duncan Coutts at 2026-09-09T11:07:01+01:00
Reorder cmm decls in HeapStackCheck for a better logical grouping
And put more section headers in to deliniate the groups.
We're about to add more here, so better to organise it first.
- - - - -
344080fd by Duncan Coutts at 2026-09-09T11:07:01+01:00
Add raisePrimIOException and add it to RTS<->ghc-internal API
The raisePrimIOException is a new helper function that I/O primops will
use to help them report I/O errors. This is implemented in Haskell
(since that's a lot easier), but has a calling convention that is
easy(ish) to use from Cmm in the I/O primops.
So we add it to the RTS API struct, and since we'll use it from Cmm we
also need a field accessor macro for cmm (in deriveConstants).
See the Note about how we cannot have nice things due to async
exceptions and thunks preventing us from using catch.
- - - - -
cfdb3399 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Add new blocking functions for I/O primops
See the Note [Thread blocking for new I/O primops],
and the Note [Calling convention for raisePrimIOException].
The point is, it will allow us to report synchronous exceptions from I/O
primops, and do so much more flexibly.
Previously the I/O managers could only report async exceptions and only
nullary exceptions. This was OK historically, but no good as we add
more I/O managers and expand the range of I/O operations we support.
- - - - -
f09c09d8 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Change the encoding of results from the I/O manager to I/O primops
Previously we just had async continue or heap overflow.
We now extend what we can report with synchronous success, and
synchronous failure with an errno.
See Note [Encoding of result of I/O manager operations]
We don't use these two new cases yet, but we will. In particular an
epoll I/O manager needs to be able to report synchronous success or
failure for waitRead#/waitWrite#.
- - - - -
30f074d9 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Switch waitRead/Write# to use new blocking return frames
and update the I/O managers to set the result before resuming the
blocked threads.
This makes it possible for I/O managers to report synchronous exceptions
from the I/O primops, but that will be done in a subsequent commit.
- - - - -
a8786ced by Duncan Coutts at 2026-09-09T11:07:01+01:00
Switch Poll and Select I/O managers to report sync exceptions
rather than using raiseAsync with blockedOnBadFD_closure.
This uses the new mechanism in the blocking frame return code to report
synchronous exceptions.
- - - - -
7a9df79a by Duncan Coutts at 2026-09-09T11:07:01+01:00
Remove now-unused blockedOnBadFD
It was previously thrown by the select and poll I/O managers, but now
they use raisePrimIOException (with an EBADF errno).
- - - - -
6b0424e3 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Improve the docs for delay# waitRead# and waitWrite#
Document that the waitRead/Write# can throw exceptions (this was true
before too), and that all of them are async exception cancellation
points.
- - - - -
afeb2c30 by Duncan Coutts at 2026-09-09T20:08:58-04:00
Enable printf warnings for trace functions and fix resulting warnings
Most of the existing printf-style functions are annotated with
attributes to enable gcc/clang warnings for the printf format string,
but several trace functions in Trace.h were missing this annotation.
Enable them, and fix the resulting warnings.
- - - - -
9a442c93 by Alan Zimmerman at 2026-09-09T20:09:36-04:00
EPA: Exact print ConDeclGADT without custom enterAnn
!16321 brought in explicit capture of parens in a ConDeclGADT.
The ExactPrint update introduced a modification of the fundamental
function in exact printing, `enterAnn`, by splitting it into a version
allowing injection of functionality normally handled by the
ExactPrint class methods.
This commit refactors that code, to restore the prior `enterAnn`
version, by following the convention in ExactPrint of introducing a
helper data structure with its own `ExactPrint` instance to achieve
the same effect.
- - - - -
4e9297ea by Simon Jakobi at 2026-09-11T08:32:45-04:00
ci: Actually pass --ignore-perf-failures to the testsuite driver
684c0018d9 changed the IGNORE_PERF_FAILURES handling to append to
RUNTEST_ARGS with bash array syntax, but the three use sites still
expand RUNTEST_ARGS as a scalar, which yields only the first array
element. The appended flag was therefore dropped in every job, so
perf improvements kept failing Marge Bot batches and master pipelines,
contrary to #19562.
Append as a string instead, matching the existing --force-colors
append in test_hadrian.
Fixes #27563.
Assisted-by: Claude Fable 5.1
- - - - -
4f78dfdf by Simon Jakobi at 2026-09-11T08:33:24-04:00
testsuite: Give T26537 a 1.5x compile timeout
Its -fregs-graph compile step tends to time out in unoptimized builds
(#27188, #27776).
Assisted-by: Claude Fable 5.1
- - - - -
130286e3 by Alan Zimmerman at 2026-09-11T08:34:08-04:00
EPA: Remove ListBanana / ListParens from AnnListBrackets
This is a step towards making AnnList only represent
lists of items which can have either braces or layout.
- - - - -
a9827d13 by Simon Jakobi at 2026-09-11T18:53:32-04:00
Reject ~, UNPACK and multiplicity annotations on type data fields
Only `!` was rejected so far. `~`, UNPACK and multiplicity annotations
were silently accepted. None of them make sense at the type level, so
restriction (R3) of Note [Type data declarations] now covers all of
them.
Fixes #27732.
Assisted-by: Claude Fable 5.1
- - - - -
c71d5e23 by Alan Zimmerman at 2026-09-11T18:54:11-04:00
EPA: Add a Note for the exact print main loop
- - - - -
7a108e43 by Simon Jakobi at 2026-09-12T18:35:59-04:00
FastString: Drop mkFastStringWith's constructor callback
All three callers passed the same callback, a partial application of
mkNewFastStringShortByteString to the string being interned. That
partial application is allocated as a closure before the table lookup,
on the common hit path too, although the callback is needed only after
a miss.
Drop the parameter and call mkNewFastStringShortByteString directly
after a miss. Since nothing is passed "with" anymore, rename the
function to internSB.
Suggested by Simon PJ in #27528:
https://gitlab.haskell.org/ghc/ghc/-/work_items/27528#note_687031
Assisted-by: Claude Fable 5
- - - - -
82c73b22 by Alan Zimmerman at 2026-09-12T18:36:38-04:00
EPA: More targeted HsDo exact print annotation
HsDo is multi-purpose, as encoded in its HsDoFlavour field. Some of
these are in a layout context (DoExpr, MDoExpr), others are not
(ListComp, MonadComp).
We are moving towards using AnnList only in layout contexts, so we
switch the HsDo TTG annotation from holding an AnnList for this, to
holding
Either (EpToken "[", EpToken "]") AnnList
This also allows us to trim down AnnListBrackets to only have braces
or None, thereby opening the door for unification with the existing
layout context data type EpLayout.
- - - - -
6ce1e2d0 by Simon Peyton Jones at 2026-09-15T11:16:53+01:00
Redesign the noinline magic
Main idea:
* When simplifying `noinline (f e1 e2)`, switch off inlining when simplifying `f`
* Mechanism: see `simplOutId`, the `noinlineIdKey` case
* If we see `noinline (f e1) e2`, the simplifier moves the `e2` inside; see the `splitContArgs` call.
This is important so you can write `noinliine f e1 e2` and have it mean the same as `noinline (f e1 e2)`.
* Now `f` sees all its arguments, henc:
* Fixes #27724
* Fixes #23911
See Note [noinlineId magic] for lots of specifics. It's surprisingly tricky!
- - - - -
102 changed files:
- .gitlab/ci.sh
- + changelog.d/27732
- + changelog.d/T27724
- + changelog.d/fix-parallel-gc-selector-race-27477
- compiler/GHC/Builtin/WiredIn/Ids.hs
- compiler/GHC/Builtin/WiredIn/Prim.hs
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Extension/Pass.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Types/Origin.hs
- docs/users_guide/exts/type_data.rst
- libraries/ghc-internal/include/RtsIfaceSymbols.h
- libraries/ghc-internal/src/GHC/Internal/Conc/IO.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Magic.hs
- rts/Capability.c
- rts/HeapStackCheck.cmm
- rts/IOManager.c
- rts/IOManager.h
- rts/IOManagerInternals.h
- rts/Messages.c
- rts/Prelude.h
- rts/PrimOps.cmm
- rts/Printer.c
- rts/STM.c
- rts/Schedule.c
- rts/Sparks.c
- rts/StableName.c
- rts/ThreadPaused.c
- rts/Threads.c
- rts/Trace.h
- rts/include/rts/RtsToHsIface.h
- rts/include/stg/MiscClosures.h
- rts/posix/Poll.c
- rts/posix/Poll.h
- rts/posix/Select.c
- rts/posix/Timeout.c
- rts/sm/Compact.c
- rts/sm/Evac.c
- rts/sm/GC.c
- rts/sm/GCUtils.c
- rts/sm/MBlock.c
- rts/sm/NonMoving.c
- rts/sm/NonMovingMark.c
- rts/sm/Storage.c
- rts/sm/Sweep.c
- testsuite/tests/codeGen/should_run/all.T
- testsuite/tests/corelint/LintEtaExpand.hs
- + testsuite/tests/dmdanal/should_compile/T23911.hs
- testsuite/tests/dmdanal/should_compile/all.T
- testsuite/tests/ghc-api/T25121_status.stdout
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/printer/Test20297.stdout
- + testsuite/tests/rts/T27477.hs
- + testsuite/tests/rts/T27477.stdout
- testsuite/tests/rts/all.T
- + testsuite/tests/simplCore/should_compile/T27724a.hs
- + testsuite/tests/simplCore/should_compile/T27724a.stderr
- + testsuite/tests/simplCore/should_compile/T27803.hs
- + testsuite/tests/simplCore/should_compile/T27803.stderr
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/type-data/should_fail/T27732a.hs
- + testsuite/tests/type-data/should_fail/T27732a.stderr
- + testsuite/tests/type-data/should_fail/T27732b.hs
- + testsuite/tests/type-data/should_fail/T27732b.stderr
- + testsuite/tests/type-data/should_fail/T27732c.hs
- + testsuite/tests/type-data/should_fail/T27732c.stderr
- + testsuite/tests/type-data/should_fail/T27732d.hs
- + testsuite/tests/type-data/should_fail/T27732d.stderr
- + testsuite/tests/type-data/should_fail/T27732e.hs
- + testsuite/tests/type-data/should_fail/T27732e.stderr
- + testsuite/tests/type-data/should_fail/T27732f.hs
- + testsuite/tests/type-data/should_fail/T27732f.stderr
- testsuite/tests/type-data/should_fail/TDStrictnessGADT.stderr
- testsuite/tests/type-data/should_fail/TDStrictnessH98.stderr
- testsuite/tests/type-data/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Utils.hs
- utils/deriveConstants/Main.hs
- utils/genprimopcode/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/13341b88fd3f09d509113f9027497e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/13341b88fd3f09d509113f9027497e…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
15 Sep '26
Zubin pushed to branch wip/9.14.2-rc2 at Glasgow Haskell Compiler / GHC
Commits:
8189a970 by Cheng Shao at 2026-09-15T15:33:07+05:30
libffi: update to 3.8.0
Bumps libffi submodule.
(cherry picked from commit 0bc6b06990a4107171e03b21c2141d7a2aced6cf)
- - - - -
baa7741a by Zubin Duggal at 2026-09-15T15:33:12+05:30
Prepare 9.14.2-rc2
-------------------------
Metric Decrease:
T4029
-------------------------
- - - - -
25 changed files:
- − changelog.d/27626
- − changelog.d/27627
- − changelog.d/27703
- − changelog.d/27704
- − changelog.d/27717
- − changelog.d/T26423
- − changelog.d/T26716
- − changelog.d/T27202
- − changelog.d/T27308
- − changelog.d/T27314.md
- − changelog.d/T27360
- − changelog.d/T27440
- − changelog.d/T27455
- − changelog.d/T27583
- − changelog.d/T27586
- − changelog.d/T27639
- − changelog.d/T27657
- − changelog.d/T27705
- − changelog.d/arm_ncg_fixes_T27430
- − changelog.d/fix-parallel-gc-selector-race-27477
- − changelog.d/llvm-23
- − changelog.d/unit-index
- docs/users_guide/9.14.2-notes.rst
- libffi-tarballs
- libraries/base/changelog.md
Changes:
=====================================
changelog.d/27626 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where an argument used only by a function's stable unfolding
- could still be marked absent, resulting in a runtime crash.
-mrs: !16503
-issues: #27626
=====================================
changelog.d/27627 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where an absent constraint argument could be replaced by an
- error thunk, which GHC then evaluated, crashing the program.
-mrs: !16519
-issues: #27627
=====================================
changelog.d/27703 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where the specialiser could drop an argument that the
- function's stable unfolding still used, resulting in a runtime crash.
-mrs: !16519
-issues: #27703
=====================================
changelog.d/27704 deleted
=====================================
@@ -1,6 +0,0 @@
-section: compiler
-synopsis: Fix a bug where a class declared abstractly in an hs-boot file was
- assumed not to be unary, so GHC speculatively evaluated a dictionary that
- could be bottom, crashing the program.
-mrs: !16519
-issues: #27704
=====================================
changelog.d/27717 deleted
=====================================
@@ -1,6 +0,0 @@
-section: compiler
-synopsis: Fix a bug where -fspec-eval-dictfun could speculatively evaluate a
- looping dictionary whose recursion went through an hs-boot import, hanging
- the program.
-mrs: !16519
-issues: #27717
=====================================
changelog.d/T26423 deleted
=====================================
@@ -1,15 +0,0 @@
-section: compiler
-synopsis: Introduce ``ExternalUnitDatabases`` and ``ExternalUnitDatabaseCache`` to cache unit databases.
-issues: #26423
-mrs: !16115
-
-description: {
- Cache the ``UnitDatabase`` in memory in ``ExternalUnitDatabases`` to avoid constantly reading
- the same ``UnitDatabase`` from disk with multiple home units.
-
- Allows to share the on-disk representation of ``UnitInfo`` across the whole ``UnitEnv``.
- We cache a mutable version of ``ExternalUnitDatabases`` as ``ExternalUnitDatabaseCache``
- in ``UnitEnv``.
- This allows us more easily to change the ``packageDBFlags`` and reading new package databases
- from disk if required, but cache everything that has been read from disk before.
-}
=====================================
changelog.d/T26716 deleted
=====================================
@@ -1,15 +0,0 @@
-section: rts
-synopsis: Fix design of TSO blocking info, fixing a use-after-free bug
-issues: #26716 #26717
-mrs: !15519
-description: {
- Experimental work on ASAN support for GHC (MR !15168) revealed a
- use-after-free bug when using the combination of the new poll I/O
- manager with the compacting GC. The ultimate cause is that a TSO's
- `block_info` (used by I/O managers and many other parts of the RTS)
- is sometimes a GC pointer and sometimes not, but without a consistent
- and easy-to-follow rule for when this is the case. The solution has
- been to clean up and enforce that the TSO's `why_blocked` enumeration
- is a proper tag for the `block_info`, and to use an encoding that
- determines precisely when the `block_info` is a GC pointer or not.
-}
=====================================
changelog.d/T27202 deleted
=====================================
@@ -1,13 +0,0 @@
-section: ghci
-synopsis: Fix regression to honour module targets in nested directories into GHCi after startup.
-issues: #27202 #27640
-mrs: !15980 !16591
-
-description: {
- Fix a regression that made it impossible to import modules using `:load <Mod>` and `:add <Mod>` after GHCi startup.
- GHCi wasn't honouring the `-i<directory>` argument if given via `ghci -i<directory>`.
-
- Further, we fix a bug while setting up package database stacks for GHCi that was uncovered during this fix.
- By underspecifying the version of dependencies, import modules from dependencies were ambiguous, even though
- they shouldn't have been!
-}
=====================================
changelog.d/T27308 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-synopsis: Drop `preloadClosure` from `UnitState`
-issues: #27308
-mrs: !16108
-
-description: {
- Drop `preloadClosure` from `UnitState` as it is always set to the empty set.
- This allows to simplify the `UnitState` and related functions.
-}
-
=====================================
changelog.d/T27314.md deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27314
-mrs: !16118
-synopsis:
- Fix spurious ``-Wincomplete-uni-patterns`` warning under ``-finfo-table-map``.
-description:
- The pattern-match checker now ignores ticks when comparing scrutinees in
- its CoreMap, so long-distance information is no longer lost across
- function-application scrutinees because debug source annotations
- (e.g. SourceNotes added by ``-finfo-table-map``) were inserted.
=====================================
changelog.d/T27360 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27360
-mrs: !16161
-synopsis:
- Recognise ``considerAccessible`` under ticks (``-g``, ``-finfo-table-map``, ``-fhpc`` etc)
-description:
- The pattern-match checker now properly recognises ``considerAccessible`` even
- when it is surrounded by ticks (e.g. debug info ticks with ``-g``, with
- ``-finfo-table-map``, etc). This ensures it works as advertised, suppressing
- redundant pattern-match warnings, even when it occurs under a tick.
=====================================
changelog.d/T27440 deleted
=====================================
@@ -1,8 +0,0 @@
-section: compiler
-issues: #27440
-mrs: !16434
-synopsis:
- Fix a panic on ``@ty`` in a pattern synonym RHS
-description:
- An invisible type argument (``@ty``) in the right-hand side of an implicitly
- bidirectional pattern synonym no longer causes a panic.
=====================================
changelog.d/T27455 deleted
=====================================
@@ -1,8 +0,0 @@
-section: base
-issues: #27455
-mrs: !16274
-synopsis:
- Don't drop `ExceptionContext` in `SomeException(toException)`
-description:
- Previously the implementation of ``Exception(toException)`` given to `SomeException` would inappropriately drop the carried `ExceptionContext`. Now ``toException = id``, faithfully implementing the semantics proposed in :ref:`CLC Proposal #200 <https://github.com/haskell/core-libraries-committee/issues/200>`.
-
=====================================
changelog.d/T27583 deleted
=====================================
@@ -1,9 +0,0 @@
-section: compiler
-issues: #27583
-mrs: !16434
-synopsis:
- Fix spurious out-of-scope errors from ``type ty`` in a pattern synonym RHS
-description:
- A required type argument with an explicit namespace specifier (``type ty``)
- in the right-hand side of an implicitly bidirectional pattern synonym no
- longer reports variables bound by the pattern as out of scope.
=====================================
changelog.d/T27586 deleted
=====================================
@@ -1,9 +0,0 @@
-section: compiler
-issues: #27586
-mrs: !16440
-synopsis:
- Fix a panic on a required type argument in a pattern synonym RHS
-description:
- An argument of a pattern synonym that is matched against a required type
- argument in the right-hand side no longer causes a panic; it is reported as
- an illegal term-level use of a type variable.
=====================================
changelog.d/T27639 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27639
-mrs: !16474
-synopsis:
- Stop representation-polymorphism checks from producing a coercion that fails
- Core Lint.
-description:
- The representation-polymorphism check that is done when subsumption performs
- eta-expansion now composes the coercions it builds in the correct order,
- avoiding a Core Lint failure.
=====================================
changelog.d/T27657 deleted
=====================================
@@ -1,9 +0,0 @@
-section: base
-issues: #27657
-mrs: !16508
-synopsis:
- Fix ``retry`` and async exception delivery inside a ``catchSTM`` handler
-description:
- ``catchSTM``\'s ``WhileHandling`` annotation used ``catch#``, leaving an IO
- ``CATCH_FRAME`` inside the transaction. Use ``catchSTM#``, which is the
- correct way to catch exceptions inside STM.
=====================================
changelog.d/T27705 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fixed an issue that caused the specializer to sometimes loop on recursive dictionary superclasses.
-issues: #27705
-mrs: !16559
-
=====================================
changelog.d/arm_ncg_fixes_T27430 deleted
=====================================
@@ -1,18 +0,0 @@
-section: compiler
-issues: #27430 #27539 #27538 #27537 #27550 #27565 #27533
-mrs: !16255
-synopsis:
- A series of fixes to the ARM64 ncg, related to handling of primitive
- 8/16bit types and simd.
-description:
- A series of related fixes to the ncg fixing:
-
- Fixed sign extension for subword values returned from unsafe ffi calls.
- Clarify and lint for invalid conversions of int8/int16 -> float/double conversions.
- Fix incorrect clobbering of local variables when comparing signed subword values.
- Fix incorrect use of 32bit reads/stores for 8/16bit wide reads/stores.
- Fix zero extension on function entry if arguments are passed at word-width
- but used at subword-widths.
- Fix broadcast# for non-literal arguments (arm64 only).
- Fix rare assembler errors caused by overflowing literals, by properly checking
- whether a constant is a viable immediate argument.
=====================================
changelog.d/fix-parallel-gc-selector-race-27477 deleted
=====================================
@@ -1,10 +0,0 @@
-section: rts
-synopsis: Fix a parallel GC race on weakly-ordered architectures (AArch64) that could crash or silently corrupt the heap
-description:
- On weakly-ordered architectures such as AArch64 programs using
- could crash during parallel garbage collection (segmentation fault
- or ``internal error: eval_thunk_selector: strange selectee <n>``) or
- continue running with silently corrupted heap data, due to a missing
- memory barrier in the parallel GC.
-mrs: !16488
-issues: #27477
=====================================
changelog.d/llvm-23 deleted
=====================================
@@ -1,4 +0,0 @@
-section: llvm-backend
-synopsis: Bump LlvmMaxVersion to support LLVM 23.x releases.
-issues: #27764
-mrs: !16617
=====================================
changelog.d/unit-index deleted
=====================================
@@ -1,14 +0,0 @@
-section: compiler
-synopsis: Use global ``UnitIndex`` to deduplicate ``UnitInfo``s over multiple home units
-issues: #27500 #26423 #27748
-mrs: !16115 !16598
-
-description: {
- The ``UnitState`` used to be duplicated for all ``HomeUnitEnv``, not sharing any of the ``UnitInfo``s.
- This can lead to excessive memory usage with multiple home units and large package databases.
-
- Our solution to this problem is deduplicating ``UnitInfo``s globally across the whole ``UnitEnv``.
- We store this information in the ``UnitIndex`` which contains data global to all ``UnitState``s.
- All processed ``UnitInfo``s and the ``WiredMap`` are stored in there, and in the future, we might
- move more fields from ``UnitState`` to ``UnitIndex``.
-}
=====================================
docs/users_guide/9.14.2-notes.rst
=====================================
@@ -87,13 +87,30 @@ Compiler
- Make the order of usages deterministic (:ghc-ticket:`26877`)
- Fix the interaction of ExplicitLevelImports with qualified imports (:ghc-ticket:`26616`, :ghc-ticket:`27385`)
- Rename ZonkAny to UnusedType and add pretty printing logic for it (:ghc-ticket:`27390`)
+- Cache unit databases and use a global ``UnitIndex`` to deduplicate
+ ``UnitInfo``\s across multiple home units, reducing memory usage
+ (:ghc-ticket:`26423`, :ghc-ticket:`27500`, :ghc-ticket:`27748`)
+- Drop ``preloadClosure`` from ``UnitState`` (:ghc-ticket:`27308`)
+- Fix a bug where an argument used only by a function's stable unfolding could still be marked absent, resulting in a runtime crash. (:ghc-ticket:`27626`)
+- Fix a bug where an absent constraint argument could be replaced by an error thunk, which GHC then evaluated, crashing the program. (:ghc-ticket:`27627`)
+- Fix a bug where the specialiser could drop an argument that the function's stable unfolding still used, resulting in a runtime crash. (:ghc-ticket:`27703`)
+- Fix a bug where a class declared abstractly in an hs-boot file was assumed not to be unary, so GHC speculatively evaluated a dictionary that could be bottom, crashing the program. (:ghc-ticket:`27704`)
+- Fix a bug where ``-fspec-eval-dictfun`` could speculatively evaluate a looping dictionary whose recursion went through an hs-boot import, hanging the program. (:ghc-ticket:`27717`)
+- Fix a panic on ``@ty`` in a pattern synonym RHS (:ghc-ticket:`27440`)
+- Fix spurious out-of-scope errors from ``type ty`` in a pattern synonym RHS (:ghc-ticket:`27583`)
+- Fix a panic on a required type argument in a pattern synonym RHS (:ghc-ticket:`27586`)
+- Stop representation-polymorphism checks from producing a coercion that fails Core Lint. (:ghc-ticket:`27639`)
+- Fixed an issue that caused the specializer to sometimes loop on recursive dictionary superclasses. (:ghc-ticket:`27705`)
+- Bumped the maximum supported LLVM version to 23 (:ghc-ticket:`27764`)
+- Recognise ``considerAccessible`` under ticks (``-g``, ``-finfo-table-map``, ``-fhpc`` etc) (:ghc-ticket:`27360`)
+- Fix spurious ``-Wincomplete-uni-patterns`` warning under ``-finfo-table-map``. (:ghc-ticket:`27314`)
GHCi
~~~~
- Added the ``-fimport-loaded-targets`` flag, which automatically imports all loaded targets into the GHCi session (:ghc-ticket:`26866`)
- Added support for custom external interpreter commands, allowing GHC API clients to extend the external interpreter with their own message handlers (:ghc-ticket:`26652`)
-- Fix regression to allow loading modules into the GHCi after startup (:ghc-ticket:`27202`)
+- Fix regression to allow loading modules into the GHCi after startup (:ghc-ticket:`27202`, :ghc-ticket:`27640`)
- Fixed the GHCi prompt and session home units to use a consistent package database stack, avoiding spurious ambiguous-import errors for home unit dependencies (:ghc-ticket:`27202`)
- Fixed the order in which ``:info`` lists instances, which previously depended on the order in which interface files happened to be loaded (:ghc-ticket:`27532`)
@@ -128,6 +145,9 @@ Runtime System
- Fix several black hole handling bugs that could lead to deadlocks or crashes in multithreaded programs. These could show up as the program hanging or "END_TSO_QUEUE object entered" errors (:ghc-ticket:`26922`, :ghc-ticket:`26936`)
- Rethrow exceptions in overlapped IO when using the WinIO IO manager (:ghc-ticket:`27283`)
- Fix "unknown/strange object 24 crash" in compacting GC (:ghc-ticket:`27434`)
+- Fix a possible use-after-free bug with TSOs (:ghc-ticket:`26716`, :ghc-ticket:`26717`)
+- Fix a parallel GC race on weakly-ordered architectures (AArch64) that could crash or silently corrupt the heap (:ghc-ticket:`27477`)
+- Fix stack corruption when returning large unboxed tuples in GHCi (:ghc-ticket:`27633`)
Code Generation
~~~~~~~~~~~~~~~
@@ -139,6 +159,10 @@ Code Generation
- Fix module finalizers on multiple platforms (:ghc-ticket:`27072`)
- Fix miscompiled %load_relaxed primop, add missing %store_relaxed (:ghc-ticket:`27483`)
- Fix redundant AP thunk codegen when not using -ticky-ap-thunk (:ghc-ticket:`27502`)
+- A number of fixes to the ARM64 ncg, fixing a number of bugs, including
+ incorrect runtime results when using subword operations
+ (:ghc-ticket:`27430`, :ghc-ticket:`27539`, :ghc-ticket:`27538`,
+ :ghc-ticket:`27537`, :ghc-ticket:`27550`, :ghc-ticket:`27533`)
Bytecode Compiler
~~~~~~~~~~~~~~~~~
@@ -151,6 +175,8 @@ Bytecode Compiler
~~~~~~~~~~~~~~~~
- Added ``@since`` annotation to ``System.Info.fullCompilerVersion`` (:ghc-ticket:`26973`)
+- Don't drop ``ExceptionContext`` in ``SomeException(toException)`` (:ghc-ticket:`27455`)
+- Fix ``retry`` and async exception delivery inside a ``catchSTM`` handler (:ghc-ticket:`27657`)
``ghc-heap`` library
~~~~~~~~~~~~~~~~~~~~
=====================================
libffi-tarballs
=====================================
@@ -1 +1 @@
-Subproject commit 49a97b7dec4829c61856442319ca6839b9d2a82a
+Subproject commit 1c6824309c9944f6235ebe9767a5ced21c76d735
=====================================
libraries/base/changelog.md
=====================================
@@ -8,6 +8,7 @@
* Hide implementation details of `throw` and `throwSTM` from exception stack traces ([CLC proposal #387](https://github.com/haskell/core-libraries-committee/issues/387), [#26808](https://gitlab.haskell.org/ghc/ghc/-/issues/26808))
* GHC internals re-exported from `GHC.Num` have been deprecated and will be removed after one major release ([CLC proposal #360](https://github.com/haskell/core-libraries-committee/issues/360))
* The implementation of `toException` in `SomeException`'s `Exception` instance no longer drops exception context, in keeping with the behavior originally proposed in [CLC Proposal #200](https://github.com/haskell/core-libraries-committee/issues/200).
+ * Fix `retry` and async exception delivery inside a `catchSTM` handler ([#27657](https://gitlab.haskell.org/ghc/ghc/-/issues/27657))
## 4.22.0.0 *December 2025*
* Shipped with GHC 9.14.1
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/9e6272cb9980ec4d3bc2fa8f04a2ec…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/9e6272cb9980ec4d3bc2fa8f04a2ec…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/apk/iface-encoding] .hi files: Various encoding improvements
by Andreas Klebinger (@AndreasK) 15 Sep '26
by Andreas Klebinger (@AndreasK) 15 Sep '26
15 Sep '26
Andreas Klebinger pushed to branch wip/apk/iface-encoding at Glasgow Haskell Compiler / GHC
Commits:
205f6936 by Andreas Klebinger at 2026-09-15T08:51:47+00:00
.hi files: Various encoding improvements
Binders: Encode non-linear binders more efficiently.
There is no need to serialize the Many type. We just use one bit to
encode that there is an implicit Many as multiplicity when writing to
disk.
Names: Use the low rather than high bit to encode the "compactness".
Since we encode name references as LEB128 using the high bit forces
5-byte references. By using the low bit we can actually compress the
small references when when storing name references using putName.
This allows use to LEB128 encode the combination of tag + value efficiently.
instance Binary Integer:
We used to use a tag byte to store if it fits in a Int64, and if not the
sign and then encode the actual value as LEB128.
Instead we now just encode as SLEB128. The only real downside is that we
have to discover during LEB decoding if we need to swap from Int to
Integer. This saves one byte for small values.
instance Binary iteral:
Don't encode it pointwise. Instead encode the Literal con tag + LitNumberType in a single tag
byte. Followed by the actual value if we deal with number literals.
This saves a byte per literal for small numbers.
`IfaceApp`: There is no real benefit to avoid collapsing chains of
applications. So we add a explicit constructor for n-ary applications.
We could do this just in the Binary instance. But in this case I felt
there is no real downside to express this in the type itself. So I
added:
IfaceApps IfaceExpr [IfaceExpr]
Of course we use a small trick. We use parts of the IFaceExpr tag space
to encode arity of the application. So we don't have to store the length
of the list in the common case.
Saves ~1 byte per argument. Exactly one for small applications. If we
serialize the list length slightly less.
`IfaceAlt`: Improve the encoding
We avoid storing the length for the always-empty lists on _DEFAULT and
literal alternatives by dispatching on the alt type.
`IfaceCase`: Add a special case for single default alts, encoded via
one of the tag bits from `IfaceExpr`.
Generally .hi files get a few % smaller. With a relative big variance with some files
getting more then 20% smaller.
-------------------------
Metric Decrease:
if_ifacetype
-------------------------
- - - - -
14 changed files:
- + changelog.d/T27808-iface-encoding-improvements
- compiler/GHC/CoreToIface.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Rename.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Types/Literal.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Utils/Binary.hs
- + testsuite/tests/utils/should_run/Binary_Literal.hs
- + testsuite/tests/utils/should_run/Binary_Literal.stdout
- testsuite/tests/utils/should_run/all.T
- utils/haddock/haddock-api/src/Haddock/InterfaceFile.hs
Changes:
=====================================
changelog.d/T27808-iface-encoding-improvements
=====================================
@@ -0,0 +1,8 @@
+section: compiler
+synopsis: Improved ``.hi`` file encoding resulting in less space used on disk.
+issues: #27808
+mrs: !16683
+description: {
+ This was mostly done by moving from simple pointwise encoding to adding
+ special cases for common cases.
+}
=====================================
compiler/GHC/CoreToIface.hs
=====================================
@@ -651,16 +651,19 @@ toIfaceApp (Var v) as
toIfaceApp e as = mkIfaceApps (toIfaceExpr e) as
mkIfaceApps :: IfaceExpr -> [CoreExpr] -> IfaceExpr
-mkIfaceApps f as = foldl' (\f a -> IfaceApp f (toIfaceExpr a)) f as
+-- `mkIfaceApp` is just a smart constructor for the IfaceApp[s] constructors.
+-- See Note [Iface applications] in GHC.Iface.Syntax
+mkIfaceApps f as = mkIfaceApp f (map toIfaceExpr as)
---------------------
toIfaceVar :: Id -> IfaceExpr
toIfaceVar v
| isBootUnfolding (idUnfolding v)
= -- See Note [Inlining and hs-boot files]
- IfaceApp (IfaceApp (IfaceExt noinline_id)
- (IfaceType (toIfaceType ty)))
- (IfaceExt name) -- don't use mkIfaceApps, or infinite loop
+ IfaceApps (IfaceExt noinline_id)
+ [IfaceType (toIfaceType ty), IfaceExt name]
+ -- don't use mkIfaceApps, or infinite loop since it ends up calling
+ -- toIfaceVar indirectly again.
| Just fcall <- isFCallId_maybe v = IfaceFCall fcall (toIfaceType (idType v))
-- Foreign calls have special syntax
=====================================
compiler/GHC/Iface/Binary.hs
=====================================
@@ -741,25 +741,38 @@ In more detail:
Tuples aren't included in the wired-in names map: see (ST1) below
* Serialisation is done by `putName`:
- - When we serialise a compact Name,
- we serialise it as a single 32-bit word:
- 10xxxxxx xxyyyyyy yyyyyyyy yyyyyyyy
- where xxxx is the tag, and yyyy is the payload.
- The function `wiredInNamesOkay` checks that the wired-in names all have
- uniques that fit into the `yyy` field.
+ - When we serialise a compact Name, we serialise its Unique, split by
+ `unpkUniqueGrimily` into the tag character and the payload:
+
+ yyyyyyyy yyyyyyyy yyyyyyyx xxxxxxx1
+ \________ payload _______/\_ tag _/^ marker bit
+
+ Why are we storing the marker/tag in the low rather than high bits? Because
+ we LEB128 encode the whole word when writing to disk so we want to keep as
+ many of the high bits zero as possible to allow for shorter encodings. See
+ also wrinkle ST3.
+
+ Tags are 8 bits by construction, and there is a check that the actual unique
+ part fits in 22 bits which `wiredInNamesOkay` (in GHC.Builtin) checks for all
+ known-key names.
- When we serialise a non-compact name:
- We look it up in the (stateful, growing) symbol table
- - If it not there we add it to the symbol table
- - We serialise the occurrenc to a single 32-bit word:
- 00xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
- where `xxxxx` is an index into the symbol table.
+ - If it is not there we add it to the symbol table
+ - We serialise the occurrence as
-* Deserialision is done by `getName`. We read a 32-bit word
- - If the MSB is `10` it must be a compact name, so we use
+ 0xxxxxxx xxxxxxxx xxxxxxxx xxxxxxx0
+
+ In other words we simply shift the index by a bit.
+ The high bit is currently unused. But `putSymtabNameRef`
+ asserts that `ix` fits in 30 bits.
+
+* Deserialisation is done by `getSymtabName`, which dispatches on the low bit
+ of the word it reads:
+ - If it is 1 it must be a compact name, so we reassemble the Unique and use
`lookupCompactName` to get from the Unique to the Name.
- - If the MSB is `00` it must be a non-compact Name,
- so we look it up in the symbol table.
+ - If it is 0 it must be a non-compact Name, so we look it up in the
+ symbol table.
Wrinkles:
@@ -785,6 +798,20 @@ Wrinkles:
`isCompactName` that tests for `knownUniqueTupleName` and then the
TyConRepNames would be serialised as non-compact names, and everything would
work. Fewer tests, but Typeable-heavy code might have bigger interface files.
+
+(ST3) Both kinds of Name are serialised as a single `Word32`, which is serialized to
+ disk in it's ULEB128 encoded variable-length form (see `putULEB128`).
+ This has consequences as it means we want to keep the high bits zero where possible
+ to allow for a shorter ULEB128 encoding.
+
+ This is why we put both the tag and the marker bit at the LSB end of the word. They
+ are always present. But by putting them at the low end we ensure LEB128 encoding
+ still works as expected, producing smaller encodings for compact names with small
+ uniques.
+
+ The downside is that we steal one bit from non-compact names for which the marker
+ bit and tag would have been zero either way. But in practice this matters far less
+ than ensuring built in (compact) names encode well.
-}
isCompactName :: Name -> Bool
@@ -803,6 +830,31 @@ lookupCompactName u
where
(tag, ix) = unpkUniqueGrimily u
+-- | Write a reference to a symbol table index.
+-- See Note [Symbol table representation of names]
+putSymtabNameRef :: WriteBinHandle -> Int -> IO ()
+{-# INLINE putSymtabNameRef #-}
+putSymtabNameRef bh ix
+ = assertPpr (ix >= 0 && ix < (1 `shiftL` 30))
+ (text "putSymtabNameRef: symbol table index out of range:" <+> int ix) $
+ -- Bit 0 == False marks a symbol table reference
+ put_ bh ((fromIntegral ix `shiftL` 1) :: Word32)
+
+-- | Write a reference to a compact (known-key) 'Name'.
+-- See Note [Symbol table representation of names]
+putCompactNameRef :: WriteBinHandle -> Unique -> IO ()
+{-# INLINE putCompactNameRef #-}
+putCompactNameRef bh uniq
+ = -- INVARIANTS:
+ -- * 8 bits tag (true by construction)
+ -- * the payload fits in 22 bits (checked for all known keys elsewhere)
+ -- Bit 0 == True marks a compact (known-key) name
+ put_ bh ( (fromIntegral payload `shiftL` 9)
+ .|. (fromIntegral (ord tag) `shiftL` 1)
+ .|. 1 :: Word32)
+ where
+ (tag, payload) = unpkUniqueGrimily uniq
+
-- See Note [Symbol table representation of names]
putName :: BinSymbolTable -> WriteBinHandle -> Name -> IO ()
putName BinSymbolTable{
@@ -810,16 +862,12 @@ putName BinSymbolTable{
bin_symtab_next = symtab_next }
bh name
| isCompactName name
- , let (c, u) = unpkUniqueGrimily (nameUnique name) -- INVARIANT: (ord c) fits in 8 bits
- = -- assert (u < 2^(22 :: Int))
- put_ bh (0x80000000
- .|. (fromIntegral (ord c) `shiftL` 22)
- .|. (fromIntegral u :: Word32))
+ = putCompactNameRef bh (nameUnique name)
| otherwise
= do (symtab_map,symtab_tbl) <- readIORef symtab_map_ref
case lookupNameEnv symtab_map name of
- Just off -> put_ bh (fromIntegral off :: Word32)
+ Just off -> putSymtabNameRef bh off
Nothing -> do
off <- freshIndex
let mod = nameModule name
@@ -829,12 +877,11 @@ putName BinSymbolTable{
let !symtab_tbl' = extendModuleEnv symtab_tbl mod ((off,name):mod_nms)
writeIORef symtab_map_ref $! ( symtab_map', symtab_tbl' )
- put_ bh (fromIntegral off :: Word32)
+ putSymtabNameRef bh off
where
freshIndex :: IO Int
freshIndex = do
off <- readFastMutInt symtab_next
- -- massert (off < 2^(30 :: Int))
writeFastMutInt symtab_next (off+1)
return off
@@ -843,12 +890,10 @@ getSymtabName :: SymbolTable Name
-> ReadBinHandle -> IO Name
getSymtabName symtab bh = do
i :: Word32 <- get bh
- case i .&. 0xC0000000 of
- 0x00000000 -> return $! symtab ! fromIntegral i
- 0x80000000 -> return $! lookupCompactName u
- where
- tag = chr (fromIntegral ((i .&. 0x3FC00000) `shiftR` 22))
- ix = fromIntegral i .&. 0x003FFFFF
- u = mkUniqueGrimilyWithTag tag ix
-
- _ -> pprPanic "getSymtabName:unknown name tag" (ppr i)
+ if i .&. 1 == 0
+ then -- Symbol table reference, written by putSymtabNameRef
+ return $! symtab ! fromIntegral (i `shiftR` 1)
+ else -- Compact name, written by putCompactNameRef
+ let tag = chr (fromIntegral ((i `shiftR` 1) .&. 0xFF))
+ payload = fromIntegral (i `shiftR` 9) :: Word64
+ in return $! lookupCompactName (mkUniqueGrimilyWithTag tag payload)
=====================================
compiler/GHC/Iface/Rename.hs
=====================================
@@ -828,6 +828,8 @@ rnIfaceExpr (IfaceLam lam_bndr expr)
= IfaceLam <$> rnIfaceLamBndr lam_bndr <*> rnIfaceExpr expr
rnIfaceExpr (IfaceApp fun arg)
= IfaceApp <$> rnIfaceExpr fun <*> rnIfaceExpr arg
+rnIfaceExpr (IfaceApps fun args)
+ = IfaceApps <$> rnIfaceExpr fun <*> rnIfaceExprs args
rnIfaceExpr (IfaceCase scrut case_bndr alts)
= IfaceCase <$> rnIfaceExpr scrut
<*> pure case_bndr
=====================================
compiler/GHC/Iface/Syntax.hs
=====================================
@@ -10,7 +10,8 @@ module GHC.Iface.Syntax (
IfaceDecl(..), IfaceFamTyConFlav(..), IfaceClassOp(..), IfaceAT(..),
IfaceConDecl(..), IfaceConDecls(..), IfaceEqSpec,
- IfaceExpr(..), IfaceAlt(..), IfaceLetBndr(..), IfaceBinding,
+ IfaceExpr(..), mkIfaceApp,
+ IfaceAlt(..), IfaceLetBndr(..), IfaceBinding,
IfaceBindingX(..), IfaceMaybeRhs(..), IfaceConAlt(..),
IfaceIdInfo, IfaceIdDetails(..), IfaceUnfolding(..), IfGuidance(..),
IfaceInfoItem(..), IfaceRule(..), IfaceAnnotation(..), IfaceAnnTarget,
@@ -96,8 +97,8 @@ import GHC.Utils.Fingerprint
import GHC.Utils.Binary
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Panic
-import GHC.Utils.Misc( dropList, filterByList, notNull, unzipWith,
- zipWithEqual )
+import GHC.Utils.Misc( dropList, filterByList, notNull,
+ unzipWith, zipWithEqual )
import GHC.Data.FastString
import GHC.Data.BooleanFormula (pprBooleanFormula, isTrue)
@@ -700,6 +701,11 @@ data IfaceExpr
| IfaceTuple TupleSort [IfaceExpr] -- Saturated; type arguments omitted
| IfaceLam IfaceLamBndr IfaceExpr
| IfaceApp IfaceExpr IfaceExpr
+ -- ^ Application to exactly one argument.
+ -- See Note [Iface applications]
+ | IfaceApps IfaceExpr [IfaceExpr]
+ -- ^ Application to two or more arguments.
+ -- See Note [Iface applications]
| IfaceCase IfaceExpr IfLclName [IfaceAlt]
| IfaceECase IfaceExpr IfaceType -- See Note [Empty case alternatives]
| IfaceLet (IfaceBinding IfaceLetBndr) IfaceExpr
@@ -710,6 +716,18 @@ data IfaceExpr
| IfaceFCall ForeignCall IfaceType
| IfaceTick IfaceTickish IfaceExpr -- from Tick tickish E
+-- | Apply an expression to a (possibly empty) list of arguments, maintaining
+-- the invariants of 'IfaceApp' and 'IfaceApps'.
+-- See Note [Iface applications].
+mkIfaceApp :: IfaceExpr -> [IfaceExpr] -> IfaceExpr
+mkIfaceApp fun args = go fun args
+ where
+ go (IfaceApp f a) as = go f (a : as)
+ go (IfaceApps f fs) as = go f (fs ++ as)
+
+ go f [] = f
+ go f [a] = IfaceApp f a
+ go f as = IfaceApps f as
data IfaceTickish
= IfaceHpcTick Module Int -- from HpcTick x
@@ -745,6 +763,30 @@ data IfaceTopBndrInfo = IfLclTopBndr IfLclName IfaceType IfaceIdInfo IfaceIdDeta
data IfaceMaybeRhs = IfUseUnfoldingRhs | IfRhs IfaceExpr
{-
+Note [Iface applications]
+~~~~~~~~~~~~~~~~~~~~~~~~~
+A Core application chain (f a1 a2 ... an) could be represented by a chain of
+n nested IfaceApp nodes like Core does. However this is generally a worse
+representation for *serialization* which is the main purpose of the Iface type.
+
+So we keep the single argument constructor as it's fairly common, and add one
+to represent multiple arguments:
+
+ * IfaceApp f a -- exactly one argument
+ * IfaceApps f [a1,..] -- two or more arguments
+
+with two invariants:
+
+ (1) The argument list of an IfaceApps has at least two elements.
+ (A one-argument application is an IfaceApp, and a zero-argument
+ "application" is just the head itself.)
+
+ (2) The head of an IfaceApp or IfaceApps is never itself an IfaceApp or
+ IfaceApps: application chains are fully flattened.
+
+The smart constructor 'mkIfaceApp' establishes both invariants; producers
+should use it rather than building IfaceApps directly.
+
Note [Empty case alternatives]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In Iface syntax an IfaceCase does not record the types of the alternatives,
@@ -1797,7 +1839,8 @@ pprIfaceExpr _ (IfaceLitRubbish tc r)
<> (case tc of { TypeLike -> empty; ConstraintLike -> text "[c]" })
<> parens (ppr r)
-pprIfaceExpr add_par app@(IfaceApp _ _) = add_par (pprIfaceApp app [])
+pprIfaceExpr add_par app@(IfaceApp _ _) = add_par (pprIfaceApp app [])
+pprIfaceExpr add_par app@(IfaceApps _ _) = add_par (pprIfaceApp app [])
pprIfaceExpr add_par i@(IfaceLam _ _)
= add_par (sep [char '\\' <+> sep (map pprIfaceLamBndr bndrs) <+> arrow,
@@ -1869,9 +1912,13 @@ pprIfaceTickish (IfaceBreakpoint (BreakpointId m ix) fvs)
------------------
pprIfaceApp :: IfaceExpr -> [SDoc] -> SDoc
-pprIfaceApp (IfaceApp fun arg) args = pprIfaceApp fun $
+-- NB: IfaceApps must print exactly like the equivalent IfaceApp chain, so
+-- that --show-iface output does not depend on which one the producer emitted.
+pprIfaceApp (IfaceApp fun arg) args = pprIfaceApp fun $
nest 2 (pprParendIfaceExpr arg) : args
-pprIfaceApp fun args = sep (pprParendIfaceExpr fun : args)
+pprIfaceApp (IfaceApps fun as) args = pprIfaceApp fun $
+ map (nest 2 . pprParendIfaceExpr) as ++ args
+pprIfaceApp fun args = sep (pprParendIfaceExpr fun : args)
------------------
instance Outputable IfaceConAlt where
@@ -2170,6 +2217,7 @@ freeNamesIfExpr (IfaceCo co) = freeNamesIfCoercion co
freeNamesIfExpr (IfaceTuple _ as) = fnList freeNamesIfExpr as
freeNamesIfExpr (IfaceLam (b,_) body) = freeNamesIfBndr b &&& freeNamesIfExpr body
freeNamesIfExpr (IfaceApp f a) = freeNamesIfExpr f &&& freeNamesIfExpr a
+freeNamesIfExpr (IfaceApps f as) = freeNamesIfExpr f &&& fnList freeNamesIfExpr as
freeNamesIfExpr (IfaceCast e co) = freeNamesIfExpr e &&& freeNamesIfCoercion co
freeNamesIfExpr (IfaceTick t e) = freeNamesIfTickish t &&& freeNamesIfExpr e
freeNamesIfExpr (IfaceECase e ty) = freeNamesIfExpr e &&& freeNamesIfType ty
@@ -2830,17 +2878,46 @@ infixl 9 .<<|.
x .<<|. b = (if b then (`setBit` 0) else id) (x `shiftL` 1)
{-# INLINE (.<<|.) #-}
+-- Encoding shortcuts:
+-- Since only IfaceDataAlt can have binders
+-- we can skip the binder list for DEFAULT and Literal alternatives.
instance Binary IfaceAlt where
put_ bh (IfaceAlt a b c) = do
put_ bh a
- put_ bh b
+ case a of
+ IfaceDataAlt {} -> put_ bh b
+ _ -> assertPpr (null b) (ppr a $$ ppr b) $ return ()
put_ bh c
get bh = do
a <- get bh
- b <- get bh
+ b <- case a of
+ IfaceDataAlt {} -> get bh
+ _ -> return []
c <- get bh
return (IfaceAlt a b c)
+{- Note [IfaceExpr encoding shortcuts]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We use a full byte to encode the constructor tag for `IfaceExpr`.
+This leaves room to encode additional information. Concretely we
+use:
+
+0 .. 14: "Simple" constructor tags.
+15 .. 22: "IfaceApps", encoding the constructor *and* arity.
+ 23: "IfaceCase" for a case with a single default alternative.
+
+Note [Binary encoding of IfaceApps]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+For IfaceApps we use the following scheme:
+
+ * arity 2..8: one byte encoding the arity as (15 + (n-2))
+ Which is followed by the head expression and then exactly `arity` arguments.
+
+ * arity > 8: tag 22, and we serialize the argument count as a ULEB128, followed by the
+ head expression and arguments.
+
+This saves us one byte per application with `2 <= arity <= 8`.
+-}
instance Binary IfaceExpr where
put_ bh (IfaceLcl aa) = do
putByte bh 0
@@ -2864,6 +2941,12 @@ instance Binary IfaceExpr where
putByte bh 5
put_ bh ag
put_ bh ah
+ -- See Note [IfaceExpr encoding shortcuts]
+ put_ bh (IfaceCase ai aj [IfaceAlt IfaceDefaultAlt [] ak]) = do
+ putByte bh 23
+ put_ bh ai
+ put_ bh aj
+ put_ bh ak
put_ bh (IfaceCase ai aj ak) = do
putByte bh 6
put_ bh ai
@@ -2899,6 +2982,17 @@ instance Binary IfaceExpr where
putByte bh 14
put_ bh r
put_ bh torc
+ -- See Note [Iface applications] and Note [Binary encoding of IfaceApps]
+ -- and Note [IfaceExpr encoding shortcuts]
+ put_ bh (IfaceApps fun args) = do
+ let !n = length args
+ massertPpr (n >= 2) (text "put_ IfaceApps" <+> ppr n)
+ if n <= maxIfaceAppsTagArity
+ then putByte bh (fromIntegral (ifaceAppsTag0 + n - 2))
+ else do putByte bh (fromIntegral ifaceAppsBigTag)
+ put_ bh n
+ put_ bh fun
+ mapM_ (put_ bh) args
get bh = do
h <- getByte bh
case h of
@@ -2944,7 +3038,41 @@ instance Binary IfaceExpr where
14 -> do r <- get bh
torc <- get bh
return (IfaceLitRubbish torc r)
+ -- Tags 15..21 encode an IfaceApps of arity 2..8 in the tag itself;
+ -- tag 22 is followed by an explicit (LEB128) argument count.
+ -- See Note [Binary encoding of IfaceApps]
+ 15 -> getApps 2
+ 16 -> getApps 3
+ 17 -> getApps 4
+ 18 -> getApps 5
+ 19 -> getApps 6
+ 20 -> getApps 7
+ 21 -> getApps 8
+ 22 -> do n <- get bh
+ getApps n
+ -- case scrut of bndr { DEFAULT -> rhs}
+ 23 -> do ai <- get bh
+ aj <- get bh
+ ak <- get bh
+ return (IfaceCase ai aj [IfaceAlt IfaceDefaultAlt [] ak])
_ -> panic ("get IfaceExpr " ++ show h)
+ where
+ getApps :: Int -> IO IfaceExpr
+ getApps n = do fun <- get bh
+ args <- replicateM n (get bh)
+ return (IfaceApps fun args)
+-- | Tag used for an 'IfaceApps' with exactly two arguments and start
+-- of the ifaceApps tag range.
+ifaceAppsTag0 :: Int
+ifaceAppsTag0 = 15
+
+-- | Highest arity encoded directly in tag byte.
+maxIfaceAppsTagArity :: Int
+maxIfaceAppsTagArity = 8
+
+-- | Tag for an 'IfaceApps' whose arity is serialized as ULEB128.
+ifaceAppsBigTag :: Int
+ifaceAppsBigTag = 22
instance Binary IfaceTickish where
put_ bh (IfaceHpcTick m ix) = do
@@ -3211,6 +3339,7 @@ instance NFData IfaceExpr where
IfaceTuple sort exprs -> rnf sort `seq` rnf exprs
IfaceLam bndr expr -> rnf bndr `seq` rnf expr
IfaceApp e1 e2 -> rnf e1 `seq` rnf e2
+ IfaceApps e es -> rnf e `seq` rnf es
IfaceCase e nm alts -> rnf e `seq` rnf nm `seq` rnf alts
IfaceECase e ty -> rnf e `seq` rnf ty
IfaceLet bind e -> rnf bind `seq` rnf e
=====================================
compiler/GHC/Iface/Type.hs
=====================================
@@ -1073,7 +1073,18 @@ pprIfaceTyConBinders suppress_sig = sep . map go
where
ppr_bndr = pprIfaceTvBndr bndr suppress_sig
+-- | IfaceBndr shortcuts:
+--
+-- In the vast majority of cases binder multiplicity is `Many` so storing it is
+-- a pure waste of space. Instead of storing (Many, Name, Ty) we simply store
+-- (Name,Ty) in the common case where multiplicity == Many.
instance Binary IfaceBndr where
+ put_ bh (IfaceIdBndr (mult, name, ty))
+ -- The implicit Many shortcut.
+ | mult == many_ty = do
+ putByte bh 2
+ put_ bh name
+ put_ bh ty
put_ bh (IfaceIdBndr aa) = do
putByte bh 0
put_ bh aa
@@ -1085,8 +1096,11 @@ instance Binary IfaceBndr where
case h of
0 -> do aa <- get bh
return (IfaceIdBndr aa)
- _ -> do ab <- get bh
+ 1 -> do ab <- get bh
return (IfaceTvBndr ab)
+ _ -> do name <- get bh
+ ty <- get bh
+ return (IfaceIdBndr (many_ty, name, ty))
instance Binary IfaceOneShot where
put_ bh IfaceNoOneShot =
=====================================
compiler/GHC/IfaceToCore.hs
=====================================
@@ -1446,6 +1446,7 @@ tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bnd
ifTopFreeName (IfaceType (IfaceTyConApp tc _ )) = Just (ifaceTyConName tc)
ifTopFreeName (IfaceType (IfaceTupleTy s _ ts)) = Just (tupleTyConName s (length (appArgsIfaceTypes ts)))
ifTopFreeName (IfaceApp f _) = ifTopFreeName f
+ ifTopFreeName (IfaceApps f _) = ifTopFreeName f
ifTopFreeName (IfaceExt n) = Just n
ifTopFreeName _ = Nothing
@@ -1682,6 +1683,9 @@ tcIfaceExpr (IfaceLam (bndr, os) body)
tcIfaceExpr (IfaceApp fun arg)
= App <$> tcIfaceExpr fun <*> tcIfaceExpr arg
+tcIfaceExpr (IfaceApps fun args)
+ = mkApps <$> tcIfaceExpr fun <*> mapM tcIfaceExpr args
+
tcIfaceExpr (IfaceECase scrut ty)
= do { scrut' <- tcIfaceExpr scrut
; ty' <- tcIfaceType ty
=====================================
compiler/GHC/Types/Literal.hs
=====================================
@@ -167,7 +167,7 @@ data LitNumType
| LitNumWord16 -- ^ @Word16#@ - exactly 16 bits
| LitNumWord32 -- ^ @Word32#@ - exactly 32 bits
| LitNumWord64 -- ^ @Word64#@ - exactly 64 bits
- deriving (Data,Enum,Eq,Ord)
+ deriving (Data,Enum,Eq,Ord,Bounded)
-- | Indicate if a numeric literal type supports negative numbers
litNumIsSigned :: LitNumType -> Bool
@@ -259,6 +259,38 @@ for more details.
-}
+{-
+Note [Binary Literal encoding]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Rather than write `LitNumType` into it's own tag byte we encode it in the
+surplus space of the `Literal` tag space.
+
+This means for `Literal` tag 0 .. 5 are the non-num literals.
+Literals 6 .. (maxBound LitNumType) encode the LitNumType.
+
+We could use the `LitNumType` information to slightly improve the encoding of
+the actual values too. But we just write/read them at Integer for simplicity for
+now.
+-}
+
+-- | The 'Binary' tag byte of @'LitNumber' nt _@.
+--
+-- These continue the tags of the non-numeric 'Literal' constructors. The
+-- mapping is total and part of the interface file format.
+-- See Note [Binary Literal encoding].
+litNumTypeTag :: LitNumType -> Word8
+litNumTypeTag nt =
+ -- 6 .. 16
+ 6 + (fromIntegral $ fromEnum nt)
+
+-- | The inverse of 'litNumTypeTag'. 'Nothing' for a tag which isn't the tag
+-- of a numeric literal. See Note [Binary Literal encoding].
+litNumTypeOfTag :: Word8 -> Maybe LitNumType
+litNumTypeOfTag tag
+ | tag >= 6 && tag <= 16
+ = Just (toEnum $ (fromIntegral tag) - 6)
+ | otherwise = Nothing
+
instance Binary Literal where
put_ bh (LitChar aa) = do putByte bh 0; put_ bh aa
put_ bh (LitString ab) = do putByte bh 1; put_ bh ab
@@ -269,9 +301,10 @@ instance Binary Literal where
= do putByte bh 5
put_ bh aj
put_ bh fod
+ -- The LitNumType is part of the tag byte.
+ -- See Note [Binary Literal encoding]
put_ bh (LitNumber nt i)
- = do putByte bh 6
- put_ bh nt
+ = do putByte bh (litNumTypeTag nt)
put_ bh i
put_ _ lit@(LitRubbish {}) = pprPanic "Binary LitRubbish" (ppr lit)
-- We use IfaceLitRubbish; see Note [Rubbish literals], item (6)
@@ -296,11 +329,11 @@ instance Binary Literal where
aj <- get bh
fod <- get bh
return (LitLabel aj fod)
- 6 -> do
- nt <- get bh
- i <- get bh
- return (LitNumber nt i)
- _ -> pprPanic "Binary:Literal" (int (fromIntegral h))
+ _ | Just nt <- litNumTypeOfTag h
+ -> do i <- get bh
+ return (LitNumber nt i)
+ | otherwise
+ -> pprPanic "Binary:Literal" (int (fromIntegral h))
instance NFData Literal where
rnf (LitChar c) = rnf c
=====================================
compiler/GHC/Types/Unique.hs
=====================================
@@ -393,7 +393,7 @@ unpkUnique u = case unpkUniqueGrimily u of
isValidKnownKeyUnique :: Unique -> Bool
isValidKnownKeyUnique u =
case unpkUniqueGrimily u of
- (c, x) -> ord c < 0xff && x <= (1 `shiftL` 22)
+ (c, x) -> ord c < 0xff && x < (1 `shiftL` 22)
{-
************************************************************************
=====================================
compiler/GHC/Utils/Binary.hs
=====================================
@@ -148,7 +148,7 @@ import GHCi.FFI
import GHCi.Message
import Control.DeepSeq
-import Control.Monad ( when, (<$!>), unless, forM_, void )
+import Control.Monad ( when, unless, forM_, void )
import Foreign hiding (bit, setBit, clearBit, shiftL, shiftR, void)
import Data.Array
import Data.Array.Base (unsafeFreezeIOArray)
@@ -173,7 +173,6 @@ import Data.Proxy
import Data.Set ( Set )
import qualified Data.Set as Set
import Data.Time hiding ( Nominal )
-import Data.List (unfoldr)
import System.IO as IO
import System.IO.Error ( mkIOError, eofErrorType )
import Type.Reflection ( Typeable, SomeTypeRep(..) )
@@ -181,6 +180,7 @@ import Type.Reflection.Unsafe
import qualified Type.Reflection as Refl
import GHC.Real ( Ratio(..) )
import GHC.Float
+
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import GHC.ByteOrder
@@ -805,6 +805,7 @@ getULEB128 bh =
{-# SPECIALISE putSLEB128 :: WriteBinHandle -> Int64 -> IO () #-}
{-# SPECIALISE putSLEB128 :: WriteBinHandle -> Int32 -> IO () #-}
{-# SPECIALISE putSLEB128 :: WriteBinHandle -> Int16 -> IO () #-}
+{-# SPECIALISE putSLEB128 :: WriteBinHandle -> Integer -> IO () #-}
putSLEB128 :: forall a. (Integral a, Bits a) => WriteBinHandle -> a -> IO ()
putSLEB128 bh initial = go initial
where
@@ -1123,86 +1124,92 @@ instance Binary IsBootInterface where
False -> NotBoot
{-
-Finally - a reasonable portable Integer instance.
-
-We used to encode values in the Int32 range as such,
-falling back to a string of all things. In either case
-we stored a tag byte to discriminate between the two cases.
-
-This made some sense as it's highly portable but also not very
-efficient.
-
-However GHC stores a surprisingly large number of large Integer
-values. In the examples looked at between 25% and 50% of Integers
-serialized were outside of the Int32 range.
+Note [Integer serialisation]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We simply encode Integer as SLEB128 unconditionally.
-Consider a value like `2724268014499746065`, some sort of hash
-actually generated by GHC.
-In the old scheme this was encoded as a list of 19 chars. This
-gave a size of 77 Bytes, one for the length of the list and 76
-since we encode chars as Word32 as well.
+This is a tradeoff:
+It allows shorter encodings for the common case of small values. And we don't need
+to prefix the string with a byte carrying any information about size or sign.
-We can easily do better. The new plan is:
+However it means large Integer values will pay some overhead. Their encoding can
+go from 9 (1 prefix, 8 value) to 10 bytes. Such values will also end up encoding
+into a `Integer` accumulator rather than a simple Word64#.
-* Start with a tag byte
- * 0 => Int64 (LEB128 encoded)
- * 1 => Negative large integer
- * 2 => Positive large integer
-* Followed by the value:
- * Int64 is encoded as usual
- * Large integers are encoded as a list of bytes (Word8).
- We use Data.Bits which defines a bit order independent of the representation.
- Values are stored LSB first.
+In practice interface files have enough small values to make this tradeoff worthwhile.
+We could also restore this benefit by using one or two *bits* rather than a full
+byte for the prefix. I imagine this would be worthwhile in runtime, but I've not
+gone as for for the sake of avoiding complexity.
-This means our example value `2724268014499746065` is now only 10 bytes large.
-* One byte tag
-* One byte for the length of the [Word8] list.
-* 8 bytes for the actual date.
-The new scheme also does not depend in any way on
-architecture specific details.
-
-We still use this scheme even with LEB128 available,
-as it has less overhead for truly large numbers. (> maxBound :: Int64)
-
-The instance is used for in Binary Integer and Binary Rational in GHC.Types.Literal
-}
instance Binary Integer where
+ -- See Note [Integer serialisation]
put_ bh i
- | i >= lo64 && i <= hi64 = do
- putWord8 bh 0
- put_ bh (fromIntegral i :: Int64)
- | otherwise = do
- if i < 0
- then putWord8 bh 1
- else putWord8 bh 2
- put_ bh (unroll $ abs i)
- where
- lo64 = fromIntegral (minBound :: Int64)
- hi64 = fromIntegral (maxBound :: Int64)
- get bh = do
- int_kind <- getWord8 bh
- case int_kind of
- 0 -> fromIntegral <$!> (get bh :: IO Int64)
- -- Large integer
- 1 -> negate <$!> getInt
- 2 -> getInt
- _ -> panic "Binary Integer - Invalid byte"
- where
- getInt :: IO Integer
- getInt = roll <$!> (get bh :: IO [Word8])
-
-unroll :: Integer -> [Word8]
-unroll = unfoldr step
- where
- step 0 = Nothing
- step i = Just (fromIntegral i, i `shiftR` 8)
+ | i >= toInteger (minBound :: Int)
+ , i <= toInteger (maxBound :: Int)
+ = putSLEB128 bh (fromInteger i :: Int)
+ | otherwise
+ = putSLEB128 bh i
+ get bh = getSLEB128Integer bh
-roll :: [Word8] -> Integer
-roll = foldl' unstep 0 . reverse
+-- | Read an SLEB128 encoded 'Integer'.
+--
+-- Unlike 'getSLEB128' this doesn't require a 'FiniteBits' instance, which
+-- 'Integer' lacks. See Note [Integer serialisation].
+getSLEB128Integer :: ReadBinHandle -> IO Integer
+getSLEB128Integer bh = go_word 0 0
where
- unstep a b = a `shiftL` 8 .|. fromIntegral b
+ -- Accumulate in a Word64 for as long as possible
+ go_word :: Int -> Word64 -> IO Integer
+ go_word !shift !acc = do
+ byte <- getByte bh
+ let !byteVal = clearBit byte 7
+ let more = testBit byte 7
+ let !shift' = shift + 7 -- bits read *after* this step
+ -- Check if the payload still fits in the accumulator,
+ -- if not swap to a Integer accumulator.
+ if shift' <= 64
+ then do
+ let !acc' = acc .|. (fromIntegral byteVal `unsafeShiftL` shift)
+ if more
+ then go_word shift' acc'
+ else return $! signExtendWord shift' acc' (testBit byte 6)
+ else do
+ -- They don't, so from here on out we use Integer arithmetic.
+ let !acc' = toInteger acc .|. (toInteger byteVal `shiftL` shift)
+ if more
+ then go_big shift' acc'
+ else return $! signExtendInteger shift' acc' (testBit byte 6)
+
+ go_big :: Int -> Integer -> IO Integer
+ go_big !shift !acc = do
+ byte <- getByte bh
+ let !acc' = acc .|. (toInteger (clearBit byte 7) `shiftL` shift)
+ let !more = testBit byte 7
+ let !shift' = shift + 7
+ if more
+ then go_big shift' acc'
+ else return $! signExtendInteger shift' acc' (testBit byte 6)
+
+ -- Sign extend a value of which we read `shift` bits into a Word64.
+ -- `shift` is always <= 64 here, so the result always fits into an Int64.
+ signExtendWord :: Int -> Word64 -> Bool -> Integer
+ signExtendWord !shift !acc signed
+ | not signed
+ = toInteger acc
+ | shift < 64
+ -- set high bits not encoded in the payload
+ = toInteger (fromIntegral (acc .|. (complement 0 `unsafeShiftL` shift)) :: Int64)
+ | otherwise
+ = toInteger (fromIntegral acc :: Int64)
+
+ -- Sign extend into an Integer.
+ signExtendInteger :: Int -> Integer -> Bool -> Integer
+ signExtendInteger !shift !acc signed
+ | signed = acc - (1 `shiftL` shift)
+ | otherwise = acc
{-
=====================================
testsuite/tests/utils/should_run/Binary_Literal.hs
=====================================
@@ -0,0 +1,280 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+-- LLM generated test. So if it's weird it's for no good reason.
+--
+-- Property tests for the 'Binary' instance of 'Literal' in GHC.Types.Literal.
+--
+-- We check that
+-- * arbitrary literals round trip through 'put_' and 'get',
+-- * a whole batch of literals written into one buffer reads back in order,
+-- that is the reader consumes exactly the bytes the writer produced,
+-- * and, since numeric literals carry an 'Integer', that the SLEB128 based
+-- 'Binary Integer' instance agrees with a reference implementation.
+module Main (main) where
+
+import GHC.Data.FastString
+import GHC.Platform ( genericPlatform )
+import GHC.Types.Basic ( FunctionOrData(..) )
+import GHC.Types.Literal
+import GHC.Types.Literal.Floating
+import GHC.Utils.Binary
+
+import Control.Monad ( replicateM )
+import Data.Bits
+import qualified Data.ByteString as BS
+import Data.Ratio ( (%) )
+import Data.Word
+import GHC.Float ( castFloatToWord32, castWord32ToFloat
+ , castDoubleToWord64, castWord64ToDouble )
+import Numeric ( showHex )
+import System.IO.Unsafe ( unsafePerformIO )
+
+import MiniQuickCheck
+
+--------------------------------------------------------------------------------
+-- Encoding and decoding
+
+-- | 'LitLabel' contains a 'FastString', which the 'Binary' instance writes
+-- through a table in the handle's user data. Interface files fill this in with
+-- a deduplication table. We only need something that round trips, so we write
+-- the bytes of the string inline.
+withFastStringWriter :: WriteBinHandle -> WriteBinHandle
+withFastStringWriter = addWriterToUserData (BinaryWriter (\bh fs -> put_ bh (bytesFS fs)))
+
+withFastStringReader :: ReadBinHandle -> ReadBinHandle
+withFastStringReader = addReaderToUserData (BinaryReader (\bh -> mkFastStringByteString <$> get bh))
+
+-- | Serialise the values and also return the position after the last of them.
+encodeAll :: Binary a => [a] -> (BS.ByteString, Bin ())
+encodeAll xs = unsafePerformIO $ do
+ bh <- withFastStringWriter <$> openBinMem 1024
+ mapM_ (put_ bh) xs
+ end <- tellBinWriter bh
+ bs <- withBinBuffer bh (return . BS.copy)
+ return (bs, end)
+
+encode :: Binary a => a -> BS.ByteString
+encode x = fst (encodeAll [x])
+
+-- | Read back @n@ values and check that doing so consumed exactly the bytes
+-- the writer produced, no more and no less.
+decodeAll :: Binary a => Int -> (BS.ByteString, Bin ()) -> [a]
+decodeAll n (bs, end) = unsafePerformIO $ do
+ bh <- withFastStringReader <$> unsafeUnpackBinBuffer bs
+ xs <- replicateM n (get bh)
+ end' <- tellBinReader bh
+ if end' == end
+ then return xs
+ else fail $ "reader stopped at " ++ show end' ++ ", writer at " ++ show end
+
+roundTrip :: Binary a => [a] -> [a]
+roundTrip xs = decodeAll (length xs) (encodeAll xs)
+
+roundTrip1 :: Binary a => a -> a
+roundTrip1 x = case roundTrip [x] of
+ [x'] -> x'
+ _ -> error "roundTrip1"
+
+--------------------------------------------------------------------------------
+-- Literals with structural equality and a Show instance
+
+-- | 'Literal' has neither a 'Show' instance nor an 'Eq' instance which compares
+-- all fields: 'LitLabel' ignores the 'FunctionOrData' and 'LitFloating'
+-- identifies the different representations of the same value. For a
+-- serialisation test we want the stricter notion.
+newtype Lit = Lit Literal
+
+instance Show Lit where
+ show (Lit l) = showLit l
+
+instance Eq Lit where
+ Lit a == Lit b = eqLit a b
+
+eqLit :: Literal -> Literal -> Bool
+eqLit (LitLabel fs1 fod1) (LitLabel fs2 fod2)
+ = fs1 == fs2 && fod1 == fod2
+eqLit (LitFloating ty1 v1) (LitFloating ty2 v2)
+ -- 'Eq LitFloating' compares NaNs bitwise but identifies different
+ -- representations of the same value; the derived 'Show' distinguishes the
+ -- representations but not NaN payloads. Together they compare structurally.
+ = ty1 == ty2 && v1 == v2 && show v1 == show v2
+eqLit a b = a == b
+
+showLit :: Literal -> String
+showLit lit = case lit of
+ LitChar c -> "LitChar " ++ show c
+ LitNumber nt i -> "LitNumber " ++ showLitNumType nt ++ " " ++ show i
+ LitString bs -> "LitString " ++ show bs
+ LitNullAddr -> "LitNullAddr"
+ LitRubbish {} -> "LitRubbish"
+ LitFloating ty v -> "LitFloating " ++ show ty ++ " (" ++ show v ++ ") " ++ bits ty v
+ LitLabel fs fod -> "LitLabel " ++ show (bytesFS fs) ++ " " ++ showFod fod
+ where
+ -- The bit pattern is needed to tell apart NaNs.
+ bits LitFloat v = "0x" ++ showHex (castFloatToWord32 (litFloatingToHostFloat v)) ""
+ bits LitDouble v = "0x" ++ showHex (castDoubleToWord64 (litFloatingToHostDouble v)) ""
+
+ showFod IsFunction = "IsFunction"
+ showFod IsData = "IsData"
+
+showLitNumType :: LitNumType -> String
+showLitNumType nt = case nt of
+ LitNumBigNat -> "LitNumBigNat"
+ LitNumInt -> "LitNumInt"
+ LitNumInt8 -> "LitNumInt8"
+ LitNumInt16 -> "LitNumInt16"
+ LitNumInt32 -> "LitNumInt32"
+ LitNumInt64 -> "LitNumInt64"
+ LitNumWord -> "LitNumWord"
+ LitNumWord8 -> "LitNumWord8"
+ LitNumWord16 -> "LitNumWord16"
+ LitNumWord32 -> "LitNumWord32"
+ LitNumWord64 -> "LitNumWord64"
+
+--------------------------------------------------------------------------------
+-- Generators
+
+-- | A number in @[0, n)@. Uses the high bits of the LCG state, which are the
+-- more random ones.
+choose :: Int -> Gen Int
+choose n = (`mod` n) . fromIntegral . (`shiftR` 32) <$> arbitraryWord64
+
+oneOf :: [Gen a] -> Gen a
+oneOf gens = do
+ i <- choose (length gens)
+ gens !! i
+
+listOf :: Int -> Gen a -> Gen [a]
+listOf maxLen gen = do
+ n <- choose (maxLen + 1)
+ replicateM n gen
+
+-- | 'MiniQuickCheck's 'Integer' instance generates values of up to 192 bits,
+-- which rarely hit the boundaries of the SLEB128 encoding. So we mix in small
+-- values and values around powers of two.
+genInteger :: Gen Integer
+genInteger = oneOf
+ [ arbitrary
+ , fromIntegral . subtract 300 <$> choose 601
+ , do k <- choose 200
+ d <- subtract 2 <$> choose 5
+ neg <- arbitrary
+ let v = 2 ^ k + toInteger d
+ return (if neg then negate v else v)
+ ]
+
+genLitNumType :: Gen LitNumType
+genLitNumType = oneOf (map pure [LitNumBigNat ..])
+
+-- | Numeric literals are always in range for their type, see
+-- Note [Word/Int underflow/overflow] in GHC.Types.Literal. The encoding is
+-- free to rely on that, so we generate only such literals.
+genLitNumber :: Gen Literal
+genLitNumber = do
+ nt <- genLitNumType
+ i <- genInteger
+ -- 'mkLitNumberWrap' wraps into the range of the fixed width types but
+ -- refuses negative 'BigNat's.
+ let i' | LitNumBigNat <- nt = abs i
+ | otherwise = i
+ return (mkLitNumberWrap genericPlatform nt i')
+
+-- | Random bit patterns, so that we also get infinities, negative zero,
+-- subnormals and NaNs with various payloads.
+genFloat :: Gen Float
+genFloat = castWord32ToFloat <$> arbitrary
+
+genDouble :: Gen Double
+genDouble = castWord64ToDouble <$> arbitrary
+
+genRational :: Gen Rational
+genRational = do
+ n <- genInteger
+ NonZero d <- arbitrary @(NonZero Integer)
+ return (n % d)
+
+genLitFloating :: Gen LitFloating
+genLitFloating = oneOf
+ [ floatToLitFloating <$> genFloat
+ , doubleToLitFloating <$> genDouble
+ , rationalToLitFloating <$> genRational
+ ]
+
+genLitFloatingType :: Gen LitFloatingType
+genLitFloatingType = oneOf [ pure LitFloat, pure LitDouble ]
+
+genByteString :: Gen BS.ByteString
+genByteString = BS.pack <$> listOf 64 arbitrary
+
+genFunctionOrData :: Gen FunctionOrData
+genFunctionOrData = oneOf [ pure IsFunction, pure IsData ]
+
+-- | Any literal except 'LitRubbish', which has no 'Binary' encoding, see
+-- Note [Rubbish literals] in GHC.Types.Literal.
+genLiteral :: Gen Literal
+genLiteral = oneOf
+ [ LitChar <$> arbitrary
+ , genLitNumber
+ , LitString <$> genByteString
+ , pure LitNullAddr
+ , LitFloating <$> genLitFloatingType <*> genLitFloating
+ , LitLabel <$> (mkFastStringByteString <$> genByteString) <*> genFunctionOrData
+ ]
+
+instance Arbitrary Lit where
+ arbitrary = Lit <$> genLiteral
+
+newtype Lits = Lits [Lit]
+ deriving (Eq, Show)
+
+instance Arbitrary Lits where
+ arbitrary = Lits <$> listOf 32 arbitrary
+
+newtype I = I Integer
+ deriving (Eq, Show)
+
+instance Arbitrary I where
+ arbitrary = I <$> genInteger
+
+--------------------------------------------------------------------------------
+-- Properties
+
+-- | Reference implementation of the SLEB128 encoding.
+slebRef :: Integer -> [Word8]
+slebRef = go
+ where
+ go val =
+ let byte = fromIntegral (val .&. 0x7f) :: Word8
+ val' = val `shiftR` 7
+ signBit = testBit byte 6
+ done = (val' == 0 && not signBit) || (val' == -1 && signBit)
+ in if done
+ then [byte]
+ else setBit byte 7 : go val'
+
+prop_literalRoundTrip :: Lit -> PropertyCheck
+prop_literalRoundTrip (Lit l) = Lit (roundTrip1 l) === Lit l
+
+prop_literalBatchRoundTrip :: Lits -> PropertyCheck
+prop_literalBatchRoundTrip (Lits ls) = Lits (map Lit (roundTrip [ l | Lit l <- ls ])) === Lits ls
+
+prop_integerRoundTrip :: I -> PropertyCheck
+prop_integerRoundTrip (I i) = roundTrip1 i === i
+
+prop_integerEncoding :: I -> PropertyCheck
+prop_integerEncoding (I i) = BS.unpack (encode i) === slebRef i
+
+tests :: Test
+tests = Group "Binary"
+ [ Group "Literal"
+ [ Property "round trip" prop_literalRoundTrip
+ , Property "batch round trip" prop_literalBatchRoundTrip
+ ]
+ , Group "Integer"
+ [ Property "round trip" prop_integerRoundTrip
+ , Property "SLEB128 encoding" prop_integerEncoding
+ ]
+ ]
+
+main :: IO ()
+main = runTestsMain (Iterations 1000) tests
=====================================
testsuite/tests/utils/should_run/Binary_Literal.stdout
=====================================
@@ -0,0 +1,11 @@
+Group Binary
+ Group Literal
+ Running round trip
+ Passed 1000 iterations
+ Running batch round trip
+ Passed 1000 iterations
+ Group Integer
+ Running round trip
+ Passed 1000 iterations
+ Running SLEB128 encoding
+ Passed 1000 iterations
=====================================
testsuite/tests/utils/should_run/all.T
=====================================
@@ -1 +1,6 @@
test('T15953', [ignore_stdout, js_skip], makefile_test, [])
+
+# Property tests for the 'Binary Literal' instance, which also exercises
+# GHCs 'Binary Integer' instance.
+test('Binary_Literal', [mini_quickcheck], multimod_compile_and_run,
+ ['Binary_Literal', '-package ghc'])
=====================================
utils/haddock/haddock-api/src/Haddock/InterfaceFile.hs
=====================================
@@ -60,6 +60,7 @@ import Text.ParserCombinators.ReadP (readP_to_S)
import qualified Data.Text as T
import Haddock.Options (Visibility (..))
+import qualified Data.Bits as Bits
data InterfaceFile = InterfaceFile
{ ifLinkEnv :: LinkEnv
@@ -143,7 +144,7 @@ binaryInterfaceMagic = 0xD0Cface
--
binaryInterfaceVersion :: Word16
#if MIN_VERSION_ghc(9,11,0) && !MIN_VERSION_ghc(10,2,0)
-binaryInterfaceVersion = 47
+binaryInterfaceVersion = 48
binaryInterfaceVersionCompatibility :: [Word16]
binaryInterfaceVersionCompatibility = [binaryInterfaceVersion]
@@ -274,7 +275,7 @@ putName
do
(symtab_map, symtab_tbl) <- readIORef symtab_map_ref
case lookupNameEnv symtab_map name of
- Just off -> put_ bh (fromIntegral off :: Word32)
+ Just off -> putNameIndex (fromIntegral off :: Word32)
Nothing -> do
off <- freshIndex
let mod' = nameModule name
@@ -283,8 +284,10 @@ putName
let !symtab_map' = extendNameEnv symtab_map name off
let !symtab_tbl' = extendModuleEnv symtab_tbl mod' ((off, name):mod_nms)
writeIORef symtab_map_ref $! (symtab_map', symtab_tbl')
- put_ bh (fromIntegral off :: Word32)
+ putNameIndex (fromIntegral off)
where
+ putNameIndex :: Word32 -> IO ()
+ putNameIndex off = put_ bh (off `Bits.shiftL` 1)
freshIndex :: IO Int
freshIndex = do
off <- readFastMutInt symtab_next
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/205f69360afc46d093c46424d62c367…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/205f69360afc46d093c46424d62c367…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/dcoutts/io-manager-selectbis] 13 commits: ci: Actually pass --ignore-perf-failures to the testsuite driver
by Duncan Coutts (@dcoutts) 15 Sep '26
by Duncan Coutts (@dcoutts) 15 Sep '26
15 Sep '26
Duncan Coutts pushed to branch wip/dcoutts/io-manager-selectbis at Glasgow Haskell Compiler / GHC
Commits:
4e9297ea by Simon Jakobi at 2026-09-11T08:32:45-04:00
ci: Actually pass --ignore-perf-failures to the testsuite driver
684c0018d9 changed the IGNORE_PERF_FAILURES handling to append to
RUNTEST_ARGS with bash array syntax, but the three use sites still
expand RUNTEST_ARGS as a scalar, which yields only the first array
element. The appended flag was therefore dropped in every job, so
perf improvements kept failing Marge Bot batches and master pipelines,
contrary to #19562.
Append as a string instead, matching the existing --force-colors
append in test_hadrian.
Fixes #27563.
Assisted-by: Claude Fable 5.1
- - - - -
4f78dfdf by Simon Jakobi at 2026-09-11T08:33:24-04:00
testsuite: Give T26537 a 1.5x compile timeout
Its -fregs-graph compile step tends to time out in unoptimized builds
(#27188, #27776).
Assisted-by: Claude Fable 5.1
- - - - -
130286e3 by Alan Zimmerman at 2026-09-11T08:34:08-04:00
EPA: Remove ListBanana / ListParens from AnnListBrackets
This is a step towards making AnnList only represent
lists of items which can have either braces or layout.
- - - - -
a9827d13 by Simon Jakobi at 2026-09-11T18:53:32-04:00
Reject ~, UNPACK and multiplicity annotations on type data fields
Only `!` was rejected so far. `~`, UNPACK and multiplicity annotations
were silently accepted. None of them make sense at the type level, so
restriction (R3) of Note [Type data declarations] now covers all of
them.
Fixes #27732.
Assisted-by: Claude Fable 5.1
- - - - -
c71d5e23 by Alan Zimmerman at 2026-09-11T18:54:11-04:00
EPA: Add a Note for the exact print main loop
- - - - -
7a108e43 by Simon Jakobi at 2026-09-12T18:35:59-04:00
FastString: Drop mkFastStringWith's constructor callback
All three callers passed the same callback, a partial application of
mkNewFastStringShortByteString to the string being interned. That
partial application is allocated as a closure before the table lookup,
on the common hit path too, although the callback is needed only after
a miss.
Drop the parameter and call mkNewFastStringShortByteString directly
after a miss. Since nothing is passed "with" anymore, rename the
function to internSB.
Suggested by Simon PJ in #27528:
https://gitlab.haskell.org/ghc/ghc/-/work_items/27528#note_687031
Assisted-by: Claude Fable 5
- - - - -
82c73b22 by Alan Zimmerman at 2026-09-12T18:36:38-04:00
EPA: More targeted HsDo exact print annotation
HsDo is multi-purpose, as encoded in its HsDoFlavour field. Some of
these are in a layout context (DoExpr, MDoExpr), others are not
(ListComp, MonadComp).
We are moving towards using AnnList only in layout contexts, so we
switch the HsDo TTG annotation from holding an AnnList for this, to
holding
Either (EpToken "[", EpToken "]") AnnList
This also allows us to trim down AnnListBrackets to only have braces
or None, thereby opening the door for unification with the existing
layout context data type EpLayout.
- - - - -
0794a23f by Duncan Coutts at 2026-09-15T09:07:30+01:00
Refactor (and rename) removeFromQueues, to simplify I/O managers
Rename it to unblockAndAppendToRunQueue which better reflects what it is
intended to do.
The post-condition for unblockAndAppendToRunQueue is that the TSO is on
the run queue or it is in the process of migrating to another cap.
Previously it achieved that by always directly adding the TSO to the run
queue itself.
But this actually made things more complicated for the I/O managers,
because it meant they needed a separate code path for notifying for
cancellation compared to notifying for completion. The general
notification code would always add the TSO to the run queue itself.
So the improvement is to allow different cases in
unblockAndAppendToRunQueue to achieve the same outcome in different
ways: either directly adding to the run queue or calling helper
functions that do so themselves.
This then allows the new I/O managers to share code between the sync and
async cancellation, and to reuse their notifyIOCompletion helpers for
cancellation. This avoids a source of bugs where the completion path may
be updated but the cancellation path may be forgotten, or similarly in
future for sync/async operations.
Update all the existing in-RTS I/O managers, and the posix timeout code.
- - - - -
0576c701 by Duncan Coutts at 2026-09-15T09:07:30+01:00
Document that awaitCompletedTimeoutsOrIO expects an empty run queue
This was true before but implicit and not relied on much. It's better to
be explicit, and allow things to depend on it.
- - - - -
3bff01ae by Duncan Coutts at 2026-09-15T09:07:30+01:00
Store the I/O opcode and fd in the StgAsyncIOOp
This will be useful in several I/O managers and it is handy for logging
and debugging.
It also doesn't increase the size of the StgAsyncIOOp structure. There
was enough spare padding space already.
Update the poll I/O manager to set the new fields.
Add a helper function to convert the enum IOReadOrWrite into the enum
IOOpCode. Also change IOReadOrWrite to be an enum without a typedef, for
consistency with other enumerations in IOManager.h
- - - - -
29f0905b by Duncan Coutts at 2026-09-15T09:07:30+01:00
Add a new I/O manager based on select()
Yes, this is the second such I/O manager, but it is a modern
re-implementation based on the new in-RTS I/O manager infrastructure. So
it is cleaner and faster than the old select I/O manager.
Why do we need another I/O manager based on select? Why isn't the poll()
one good enough as a baseline portable unix I/O manager? Because macOS.
Apple Inc. is why we cannot have nice things.
The man page for poll on macOS documents the fact that it does not work.
At least, it does not work for all files. Specifically, it does not work
for device files. Whereas macOS select() does work for device files.
Aaaaarg!
We _do_ want to deprecate and remove the old select I/O manager, but due to
macOS we cannot do that until we have a replacement. This is that
replacement. Until of course a nice new k-queue I/O manager arrives,
which could become the new default for macOS and FreeBSD.
Interestingly, this select I/O manager is actually faster than the poll
one, on Linix, in some circumstances: specifically when many Haskell
threads are waiting on the same fd. The poll I/O manager does O(n) work
for n threads waiting on I/O, whereas the select one does O(fds) work
for the number of fds that threads are waiting on. Usually this is 1:1,
so it's not noticable, but one can concoct extreme benchmarks to show
the difference.
- - - - -
5c4fc551 by Duncan Coutts at 2026-09-15T09:07:30+01:00
Minor updates in the poll I/O manager to keep in sync with select
This keeps it in sync with select one. The changes are based on code review
while implementing the new select I/O manager. The two I/O managers are so
similar in structure that it makes sense to try to minimise the diff between
them. This should aid understanding, and fixes to both in future.
- - - - -
aaf0ab42 by Duncan Coutts at 2026-09-15T09:07:30+01:00
Document the new select I/O manager in the user guide
in the RTS section about I/O managers.
And add a changelog entry.
- - - - -
54 changed files:
- .gitlab/ci.sh
- + changelog.d/27732
- + changelog.d/select-io-manager
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Errors/Types.hs
- docs/users_guide/exts/type_data.rst
- docs/users_guide/runtime_control.rst
- libraries/base/src/GHC/RTS/Flags.hs
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc
- rts/IOManager.c
- rts/IOManager.h
- rts/IOManagerInternals.h
- rts/RaiseAsync.c
- rts/configure.ac
- rts/include/rts/Flags.h
- rts/include/rts/storage/Closures.h
- rts/posix/Poll.c
- rts/posix/Poll.h
- + rts/posix/SelectBis.c
- + rts/posix/SelectBis.h
- rts/posix/Timeout.c
- rts/posix/Timeout.h
- rts/rts.cabal
- testsuite/tests/codeGen/should_run/all.T
- testsuite/tests/ghc-api/T25121_status.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/printer/Test20297.stdout
- + testsuite/tests/type-data/should_fail/T27732a.hs
- + testsuite/tests/type-data/should_fail/T27732a.stderr
- + testsuite/tests/type-data/should_fail/T27732b.hs
- + testsuite/tests/type-data/should_fail/T27732b.stderr
- + testsuite/tests/type-data/should_fail/T27732c.hs
- + testsuite/tests/type-data/should_fail/T27732c.stderr
- + testsuite/tests/type-data/should_fail/T27732d.hs
- + testsuite/tests/type-data/should_fail/T27732d.stderr
- + testsuite/tests/type-data/should_fail/T27732e.hs
- + testsuite/tests/type-data/should_fail/T27732e.stderr
- + testsuite/tests/type-data/should_fail/T27732f.hs
- + testsuite/tests/type-data/should_fail/T27732f.stderr
- testsuite/tests/type-data/should_fail/TDStrictnessGADT.stderr
- testsuite/tests/type-data/should_fail/TDStrictnessH98.stderr
- testsuite/tests/type-data/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Utils.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2c4ecfe6853a7632180425ae35aceb…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2c4ecfe6853a7632180425ae35aceb…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 3 commits: rts: handle large CONSTR closures in compacting GC
by Marge Bot (@marge-bot) 15 Sep '26
by Marge Bot (@marge-bot) 15 Sep '26
15 Sep '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
1d07a0f6 by Luite Stegeman at 2026-09-15T03:47:20-04:00
rts: handle large CONSTR closures in compacting GC
The function update_fwd_large in the compacting GC could run into
an unexpected object with the following error:
internal error: update_fwd_large: unknown/strange object 1
Closure type 1 is CONSTR. This patch adds cases for CONSTR and
CONSTR_NOCAF.
This is the same problem as #27434 (large AP closures, fixed by
cca0d58963), which missed this case.
Fixes #27649
- - - - -
9f202e51 by Luite Stegeman at 2026-09-15T03:47:21-04:00
testsuite: fix T27434 test with compacting GC
Ensure that the interpreter is actually run with the compacting GC
- - - - -
7113ad52 by Luite Stegeman at 2026-09-15T03:47:24-04:00
rts: initialise the stack frame header for mask_frame and apply_mask_frame
We must leave the stack in consistent state before jumping to
mask_frame or apply_mask_frame because they may result. Failing
to do so could lead to a crash if there were waiting exceptions.
Fixes #27651
- - - - -
10 changed files:
- + changelog.d/fix-compacting-gc-constr-27649
- + changelog.d/fix-control0-mask-trampoline
- rts/ContinuationOps.cmm
- rts/sm/Compact.c
- + testsuite/tests/rts/T27649.hs
- + testsuite/tests/rts/T27649.stdout
- testsuite/tests/rts/all.T
- + testsuite/tests/rts/continuations/T27651.hs
- + testsuite/tests/rts/continuations/T27651.stdout
- testsuite/tests/rts/continuations/all.T
Changes:
=====================================
changelog.d/fix-compacting-gc-constr-27649
=====================================
@@ -0,0 +1,14 @@
+section: rts
+synopsis: Fix "unknown/strange object 1" crash in compacting GC
+issues: #27649
+mrs: !16482
+
+description {
+Fix a crash in the compacting garbage collector when collecting large
+data constructor closures, as allocated by the bytecode interpreter for
+constructors with several hundred fields. Affected programs (run in GHCi,
+or via ``ghc -e`` or ``runghc``) crashed with an internal error of the
+form "update_fwd_large: unknown/strange object 1" when run with the
+compacting GC (``+RTS -c``, or compaction enabled automatically by a
+``-M`` heap limit).
+}
=====================================
changelog.d/fix-control0-mask-trampoline
=====================================
@@ -0,0 +1,13 @@
+section: rts
+synopsis: Fix a crash when capturing or resuming a delimited continuation that adjusts the async exception masking state
+issues: #27651
+mrs: !16484
+
+description: {
+Capturing a continuation with ``control0#`` from inside ``mask`` or
+``uninterruptibleMask`` left an uninitialised word on the stack while
+restoring the masking state. When the thread had a pending asynchronous
+exception (e.g. from ``throwTo``), raising it walked over that word and
+crashed with a segmentation fault. Resuming such a continuation had the
+same defect.
+}
=====================================
rts/ContinuationOps.cmm
=====================================
@@ -148,6 +148,7 @@ stg_control0zh_ll // explicit stack
// and jump to the frame’s entry code.
Sp_adj(-3); // Note -3, not -2, because `mask_frame` will
// try to pop itself off the stack when it returns!
+ Sp(0) = mask_frame; // Can't be omitted, see #27651
Sp(1) = stg_ap_pv_info;
Sp(2) = cont;
R1 = f;
@@ -230,6 +231,7 @@ stg_CONTINUATION_apply // explicit stack
// Now we just set up the stack so that `apply_mask_frame` will apply `io`
// when it returns and jump to it.
Sp_adj(-2);
+ Sp(0) = apply_mask_frame; // Can't be omitted, see #27651
Sp(1) = stg_ap_v_info;
R1 = io;
jump %ENTRY_CODE(apply_mask_frame) [R1];
=====================================
rts/sm/Compact.c
=====================================
@@ -573,6 +573,13 @@ update_fwd_large( bdescr *bd )
continue;
}
+ case CONSTR:
+ case CONSTR_NOCAF:
+ {
+ thread_obj(info, p);
+ continue;
+ }
+
case MUT_ARR_PTRS_CLEAN:
case MUT_ARR_PTRS_DIRTY:
case MUT_ARR_PTRS_FROZEN_CLEAN:
=====================================
testsuite/tests/rts/T27649.hs
=====================================
@@ -0,0 +1,27 @@
+-- Test that the compacting GC can handle large CONSTR closures.
+--
+-- The bytecode interpreter allocates data constructors with allocate(),
+-- so a constructor with enough fields becomes a large object (BF_LARGE).
+-- update_fwd_large in rts/sm/Compact.c must therefore handle CONSTR.
+-- This test only exercises the interpreter (ghci way): compiled code
+-- bump-allocates constructors in the nursery and never hits this path.
+module Main where
+
+import System.Mem (performMajorGC)
+import Control.Monad (forM, forM_)
+
+data Big = Big Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int Int
+
+{-# NOINLINE mkBig #-}
+mkBig :: Int -> Big
+mkBig seed = Big (seed + 0) (seed + 1) (seed + 2) (seed + 3) (seed + 4) (seed + 5) (seed + 6) (seed + 7) (seed + 8) (seed + 9) (seed + 10) (seed + 11) (seed + 12) (seed + 13) (seed + 14) (seed + 15) (seed + 16) (seed + 17) (seed + 18) (seed + 19) (seed + 20) (seed + 21) (seed + 22) (seed + 23) (seed + 24) (seed + 25) (seed + 26) (seed + 27) (seed + 28) (seed + 29) (seed + 30) (seed + 31) (seed + 32) (seed + 33) (seed + 34) (seed + 35) (seed + 36) (seed + 37) (seed + 38) (seed + 39) (seed + 40) (seed + 41) (seed + 42) (seed + 43) (seed + 44) (seed + 45) (seed + 46) (seed + 47) (seed + 48) (seed + 49) (seed + 50) (seed + 51) (seed + 52) (seed + 53) (seed + 54) (seed + 55) (seed + 56) (seed + 57) (seed + 58) (seed + 59) (seed + 60) (seed + 61) (seed + 62) (seed + 63) (seed + 64) (seed + 65) (seed + 66) (seed + 67) (seed + 68) (seed + 69) (seed + 70) (seed + 71) (seed + 72) (seed + 73) (seed + 74) (seed + 75) (seed + 76) (seed + 77) (seed + 78) (seed + 79) (seed + 80) (seed + 81) (seed + 82) (seed + 83) (seed + 84) (seed + 85) (seed + 86) (seed + 87) (seed + 88) (seed + 89) (seed + 90) (seed + 91) (seed + 92) (seed + 93) (seed + 94) (seed + 95) (seed + 96) (seed + 97) (seed + 98) (seed + 99) (seed + 100) (seed + 101) (seed + 102) (seed + 103) (seed + 104) (seed + 105) (seed + 106) (seed + 107) (seed + 108) (seed + 109) (seed + 110) (seed + 111) (seed + 112) (seed + 113) (seed + 114) (seed + 115) (seed + 116) (seed + 117) (seed + 118) (seed + 119) (seed + 120) (seed + 121) (seed + 122) (seed + 123) (seed + 124) (seed + 125) (seed + 126) (seed + 127) (seed + 128) (seed + 129) (seed + 130) (seed + 131) (seed + 132) (seed + 133) (seed + 134) (seed + 135) (seed + 136) (seed + 137) (seed + 138) (seed + 139) (seed + 140) (seed + 141) (seed + 142) (seed + 143) (seed + 144) (seed + 145) (seed + 146) (seed + 147) (seed + 148) (seed + 149) (seed + 150) (seed + 151) (seed + 152) (seed + 153) (seed + 154) (seed + 155) (seed + 156) (seed + 157) (seed + 158) (seed + 159) (seed + 160) (seed + 161) (seed + 162) (seed + 163) (seed + 164) (seed + 165) (seed + 166) (seed + 167) (seed + 168) (seed + 169) (seed + 170) (seed + 171) (seed + 172) (seed + 173) (seed + 174) (seed + 175) (seed + 176) (seed + 177) (seed + 178) (seed + 179) (seed + 180) (seed + 181) (seed + 182) (seed + 183) (seed + 184) (seed + 185) (seed + 186) (seed + 187) (seed + 188) (seed + 189) (seed + 190) (seed + 191) (seed + 192) (seed + 193) (seed + 194) (seed + 195) (seed + 196) (seed + 197) (seed + 198) (seed + 199) (seed + 200) (seed + 201) (seed + 202) (seed + 203) (seed + 204) (seed + 205) (seed + 206) (seed + 207) (seed + 208) (seed + 209) (seed + 210) (seed + 211) (seed + 212) (seed + 213) (seed + 214) (seed + 215) (seed + 216) (seed + 217) (seed + 218) (seed + 219) (seed + 220) (seed + 221) (seed + 222) (seed + 223) (seed + 224) (seed + 225) (seed + 226) (seed + 227) (seed + 228) (seed + 229) (seed + 230) (seed + 231) (seed + 232) (seed + 233) (seed + 234) (seed + 235) (seed + 236) (seed + 237) (seed + 238) (seed + 239) (seed + 240) (seed + 241) (seed + 242) (seed + 243) (seed + 244) (seed + 245) (seed + 246) (seed + 247) (seed + 248) (seed + 249) (seed + 250) (seed + 251) (seed + 252) (seed + 253) (seed + 254) (seed + 255) (seed + 256) (seed + 257) (seed + 258) (seed + 259) (seed + 260) (seed + 261) (seed + 262) (seed + 263) (seed + 264) (seed + 265) (seed + 266) (seed + 267) (seed + 268) (seed + 269) (seed + 270) (seed + 271) (seed + 272) (seed + 273) (seed + 274) (seed + 275) (seed + 276) (seed + 277) (seed + 278) (seed + 279) (seed + 280) (seed + 281) (seed + 282) (seed + 283) (seed + 284) (seed + 285) (seed + 286) (seed + 287) (seed + 288) (seed + 289) (seed + 290) (seed + 291) (seed + 292) (seed + 293) (seed + 294) (seed + 295) (seed + 296) (seed + 297) (seed + 298) (seed + 299) (seed + 300) (seed + 301) (seed + 302) (seed + 303) (seed + 304) (seed + 305) (seed + 306) (seed + 307) (seed + 308) (seed + 309) (seed + 310) (seed + 311) (seed + 312) (seed + 313) (seed + 314) (seed + 315) (seed + 316) (seed + 317) (seed + 318) (seed + 319) (seed + 320) (seed + 321) (seed + 322) (seed + 323) (seed + 324) (seed + 325) (seed + 326) (seed + 327) (seed + 328) (seed + 329) (seed + 330) (seed + 331) (seed + 332) (seed + 333) (seed + 334) (seed + 335) (seed + 336) (seed + 337) (seed + 338) (seed + 339) (seed + 340) (seed + 341) (seed + 342) (seed + 343) (seed + 344) (seed + 345) (seed + 346) (seed + 347) (seed + 348) (seed + 349) (seed + 350) (seed + 351) (seed + 352) (seed + 353) (seed + 354) (seed + 355) (seed + 356) (seed + 357) (seed + 358) (seed + 359) (seed + 360) (seed + 361) (seed + 362) (seed + 363) (seed + 364) (seed + 365) (seed + 366) (seed + 367) (seed + 368) (seed + 369) (seed + 370) (seed + 371) (seed + 372) (seed + 373) (seed + 374) (seed + 375) (seed + 376) (seed + 377) (seed + 378) (seed + 379) (seed + 380) (seed + 381) (seed + 382) (seed + 383) (seed + 384) (seed + 385) (seed + 386) (seed + 387) (seed + 388) (seed + 389) (seed + 390) (seed + 391) (seed + 392) (seed + 393) (seed + 394) (seed + 395) (seed + 396) (seed + 397) (seed + 398) (seed + 399) (seed + 400) (seed + 401) (seed + 402) (seed + 403) (seed + 404) (seed + 405) (seed + 406) (seed + 407) (seed + 408) (seed + 409) (seed + 410) (seed + 411) (seed + 412) (seed + 413) (seed + 414) (seed + 415) (seed + 416) (seed + 417) (seed + 418) (seed + 419) (seed + 420) (seed + 421) (seed + 422) (seed + 423) (seed + 424) (seed + 425) (seed + 426) (seed + 427) (seed + 428) (seed + 429) (seed + 430) (seed + 431) (seed + 432) (seed + 433) (seed + 434) (seed + 435) (seed + 436) (seed + 437) (seed + 438) (seed + 439) (seed + 440) (seed + 441) (seed + 442) (seed + 443) (seed + 444) (seed + 445) (seed + 446) (seed + 447) (seed + 448) (seed + 449) (seed + 450) (seed + 451) (seed + 452) (seed + 453) (seed + 454) (seed + 455) (seed + 456) (seed + 457) (seed + 458) (seed + 459) (seed + 460) (seed + 461) (seed + 462) (seed + 463) (seed + 464) (seed + 465) (seed + 466) (seed + 467) (seed + 468) (seed + 469) (seed + 470) (seed + 471) (seed + 472) (seed + 473) (seed + 474) (seed + 475) (seed + 476) (seed + 477) (seed + 478) (seed + 479) (seed + 480) (seed + 481) (seed + 482) (seed + 483) (seed + 484) (seed + 485) (seed + 486) (seed + 487) (seed + 488) (seed + 489) (seed + 490) (seed + 491) (seed + 492) (seed + 493) (seed + 494) (seed + 495) (seed + 496) (seed + 497) (seed + 498) (seed + 499)
+
+sumBig :: Big -> Int
+sumBig (Big a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 a31 a32 a33 a34 a35 a36 a37 a38 a39 a40 a41 a42 a43 a44 a45 a46 a47 a48 a49 a50 a51 a52 a53 a54 a55 a56 a57 a58 a59 a60 a61 a62 a63 a64 a65 a66 a67 a68 a69 a70 a71 a72 a73 a74 a75 a76 a77 a78 a79 a80 a81 a82 a83 a84 a85 a86 a87 a88 a89 a90 a91 a92 a93 a94 a95 a96 a97 a98 a99 a100 a101 a102 a103 a104 a105 a106 a107 a108 a109 a110 a111 a112 a113 a114 a115 a116 a117 a118 a119 a120 a121 a122 a123 a124 a125 a126 a127 a128 a129 a130 a131 a132 a133 a134 a135 a136 a137 a138 a139 a140 a141 a142 a143 a144 a145 a146 a147 a148 a149 a150 a151 a152 a153 a154 a155 a156 a157 a158 a159 a160 a161 a162 a163 a164 a165 a166 a167 a168 a169 a170 a171 a172 a173 a174 a175 a176 a177 a178 a179 a180 a181 a182 a183 a184 a185 a186 a187 a188 a189 a190 a191 a192 a193 a194 a195 a196 a197 a198 a199 a200 a201 a202 a203 a204 a205 a206 a207 a208 a209 a210 a211 a212 a213 a214 a215 a216 a217 a218 a219 a220 a221 a222 a223 a224 a225 a226 a227 a228 a229 a230 a231 a232 a233 a234 a235 a236 a237 a238 a239 a240 a241 a242 a243 a244 a245 a246 a247 a248 a249 a250 a251 a252 a253 a254 a255 a256 a257 a258 a259 a260 a261 a262 a263 a264 a265 a266 a267 a268 a269 a270 a271 a272 a273 a274 a275 a276 a277 a278 a279 a280 a281 a282 a283 a284 a285 a286 a287 a288 a289 a290 a291 a292 a293 a294 a295 a296 a297 a298 a299 a300 a301 a302 a303 a304 a305 a306 a307 a308 a309 a310 a311 a312 a313 a314 a315 a316 a317 a318 a319 a320 a321 a322 a323 a324 a325 a326 a327 a328 a329 a330 a331 a332 a333 a334 a335 a336 a337 a338 a339 a340 a341 a342 a343 a344 a345 a346 a347 a348 a349 a350 a351 a352 a353 a354 a355 a356 a357 a358 a359 a360 a361 a362 a363 a364 a365 a366 a367 a368 a369 a370 a371 a372 a373 a374 a375 a376 a377 a378 a379 a380 a381 a382 a383 a384 a385 a386 a387 a388 a389 a390 a391 a392 a393 a394 a395 a396 a397 a398 a399 a400 a401 a402 a403 a404 a405 a406 a407 a408 a409 a410 a411 a412 a413 a414 a415 a416 a417 a418 a419 a420 a421 a422 a423 a424 a425 a426 a427 a428 a429 a430 a431 a432 a433 a434 a435 a436 a437 a438 a439 a440 a441 a442 a443 a444 a445 a446 a447 a448 a449 a450 a451 a452 a453 a454 a455 a456 a457 a458 a459 a460 a461 a462 a463 a464 a465 a466 a467 a468 a469 a470 a471 a472 a473 a474 a475 a476 a477 a478 a479 a480 a481 a482 a483 a484 a485 a486 a487 a488 a489 a490 a491 a492 a493 a494 a495 a496 a497 a498 a499) = a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 + a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32 + a33 + a34 + a35 + a36 + a37 + a38 + a39 + a40 + a41 + a42 + a43 + a44 + a45 + a46 + a47 + a48 + a49 + a50 + a51 + a52 + a53 + a54 + a55 + a56 + a57 + a58 + a59 + a60 + a61 + a62 + a63 + a64 + a65 + a66 + a67 + a68 + a69 + a70 + a71 + a72 + a73 + a74 + a75 + a76 + a77 + a78 + a79 + a80 + a81 + a82 + a83 + a84 + a85 + a86 + a87 + a88 + a89 + a90 + a91 + a92 + a93 + a94 + a95 + a96 + a97 + a98 + a99 + a100 + a101 + a102 + a103 + a104 + a105 + a106 + a107 + a108 + a109 + a110 + a111 + a112 + a113 + a114 + a115 + a116 + a117 + a118 + a119 + a120 + a121 + a122 + a123 + a124 + a125 + a126 + a127 + a128 + a129 + a130 + a131 + a132 + a133 + a134 + a135 + a136 + a137 + a138 + a139 + a140 + a141 + a142 + a143 + a144 + a145 + a146 + a147 + a148 + a149 + a150 + a151 + a152 + a153 + a154 + a155 + a156 + a157 + a158 + a159 + a160 + a161 + a162 + a163 + a164 + a165 + a166 + a167 + a168 + a169 + a170 + a171 + a172 + a173 + a174 + a175 + a176 + a177 + a178 + a179 + a180 + a181 + a182 + a183 + a184 + a185 + a186 + a187 + a188 + a189 + a190 + a191 + a192 + a193 + a194 + a195 + a196 + a197 + a198 + a199 + a200 + a201 + a202 + a203 + a204 + a205 + a206 + a207 + a208 + a209 + a210 + a211 + a212 + a213 + a214 + a215 + a216 + a217 + a218 + a219 + a220 + a221 + a222 + a223 + a224 + a225 + a226 + a227 + a228 + a229 + a230 + a231 + a232 + a233 + a234 + a235 + a236 + a237 + a238 + a239 + a240 + a241 + a242 + a243 + a244 + a245 + a246 + a247 + a248 + a249 + a250 + a251 + a252 + a253 + a254 + a255 + a256 + a257 + a258 + a259 + a260 + a261 + a262 + a263 + a264 + a265 + a266 + a267 + a268 + a269 + a270 + a271 + a272 + a273 + a274 + a275 + a276 + a277 + a278 + a279 + a280 + a281 + a282 + a283 + a284 + a285 + a286 + a287 + a288 + a289 + a290 + a291 + a292 + a293 + a294 + a295 + a296 + a297 + a298 + a299 + a300 + a301 + a302 + a303 + a304 + a305 + a306 + a307 + a308 + a309 + a310 + a311 + a312 + a313 + a314 + a315 + a316 + a317 + a318 + a319 + a320 + a321 + a322 + a323 + a324 + a325 + a326 + a327 + a328 + a329 + a330 + a331 + a332 + a333 + a334 + a335 + a336 + a337 + a338 + a339 + a340 + a341 + a342 + a343 + a344 + a345 + a346 + a347 + a348 + a349 + a350 + a351 + a352 + a353 + a354 + a355 + a356 + a357 + a358 + a359 + a360 + a361 + a362 + a363 + a364 + a365 + a366 + a367 + a368 + a369 + a370 + a371 + a372 + a373 + a374 + a375 + a376 + a377 + a378 + a379 + a380 + a381 + a382 + a383 + a384 + a385 + a386 + a387 + a388 + a389 + a390 + a391 + a392 + a393 + a394 + a395 + a396 + a397 + a398 + a399 + a400 + a401 + a402 + a403 + a404 + a405 + a406 + a407 + a408 + a409 + a410 + a411 + a412 + a413 + a414 + a415 + a416 + a417 + a418 + a419 + a420 + a421 + a422 + a423 + a424 + a425 + a426 + a427 + a428 + a429 + a430 + a431 + a432 + a433 + a434 + a435 + a436 + a437 + a438 + a439 + a440 + a441 + a442 + a443 + a444 + a445 + a446 + a447 + a448 + a449 + a450 + a451 + a452 + a453 + a454 + a455 + a456 + a457 + a458 + a459 + a460 + a461 + a462 + a463 + a464 + a465 + a466 + a467 + a468 + a469 + a470 + a471 + a472 + a473 + a474 + a475 + a476 + a477 + a478 + a479 + a480 + a481 + a482 + a483 + a484 + a485 + a486 + a487 + a488 + a489 + a490 + a491 + a492 + a493 + a494 + a495 + a496 + a497 + a498 + a499
+
+main :: IO ()
+main = do
+ bigs <- forM [1..100] (return . mkBig)
+ performMajorGC
+ forM_ [1..3] (const performMajorGC)
+ print (sum (map sumBig bigs))
=====================================
testsuite/tests/rts/T27649.stdout
=====================================
@@ -0,0 +1 @@
+15000000
=====================================
testsuite/tests/rts/all.T
=====================================
@@ -699,8 +699,20 @@ test('resizeMutableByteArrayInPlace', [req_cmm, extra_ways(['optasm', 'sanity'])
test('T27123', [when(have_profiling(), extra_ways(['prof']))], compile_and_run, ['-O'])
+# T27434 and T27649 test the compacting GC on large closures (AP and
+# CONSTR respectively) that only the bytecode interpreter allocates, so
+# they must run in the ghci way. In the ghci way extra_run_opts only
+# sets the interpreted program's argv (via :set args), so enable
+# compaction with GHCRTS to make it reach the RTS of the GHCi process
+# itself (#27615).
test('T27434',
- extra_ways(['compacting_gc']),
+ [only_ways(['ghci']),
+ cmd_prefix('GHCRTS=-c ')],
+ compile_and_run, [''])
+
+test('T27649',
+ [only_ways(['ghci']),
+ cmd_prefix('GHCRTS=-c ')],
compile_and_run, [''])
test('T19048',
=====================================
testsuite/tests/rts/continuations/T27651.hs
=====================================
@@ -0,0 +1,91 @@
+-- When capturing or resuming a continuation adjusts the async exception
+-- masking state, the RTS trampolines through a mask/unmask frame, and the
+-- stack must be well-formed at that point: with a blocked exception
+-- pending, the eager raise in stg_unmaskAsyncExceptionszh_ret walks the
+-- whole stack.
+--
+-- Phase 1 exercises the capture side (stg_control0zh_ll): control0# runs
+-- inside uninterruptibleMask_ while another thread has queued an
+-- exception via throwTo, so the capture unmasks with the exception
+-- pending. The frame evaluated between the unmask frame and the prompt
+-- keeps raw Int# payload live so that a stale word on the stack cannot
+-- masquerade as a valid frame by accident.
+--
+-- Phase 2 exercises the resume side (stg_CONTINUATION_apply): the
+-- continuation is captured while unmasked (inside mask/restore), so
+-- resuming it unmasks, and it is applied from a thread that is masked
+-- with an exception pending.
+import Control.Concurrent
+import Control.Exception
+import Control.Monad
+
+import ContIO
+
+data Boom = Boom deriving Show
+instance Exception Boom
+
+{-# NOINLINE useInts #-}
+useInts :: Int -> Int -> Int -> Int -> Int -> Int
+useInts a b c d e = a + b * c + d * e
+
+rounds :: Int
+rounds = 150
+
+phase1 :: Int -> IO ()
+phase1 i = do
+ mv <- newEmptyMVar
+ done <- newEmptyMVar
+ let !p = i * 7919 + 3 -- raw ints to live in the continuation frame
+ !q = i * 104729 + 7
+ !u = i * 1299709 + 11
+ !v = i * 15485863 + 13
+ a <- forkIO $
+ handle (\Boom -> void (tryPutMVar done (Left Boom))) $ do
+ tag <- newPromptTag
+ r <- prompt tag $ do
+ x <- uninterruptibleMask_ $ do
+ putMVar mv ()
+ threadDelay 2000 -- let the thrower queue its exception
+ control0 tag (\_k -> pure (42 :: Int))
+ -- continuation frame between the unmask frame and the
+ -- prompt frame, carrying raw Int# payload:
+ pure (useInts x p q u v)
+ void (tryPutMVar done (Right r))
+ takeMVar mv
+ _ <- forkIO $ throwTo a Boom
+ void (takeMVar done)
+
+phase2 :: Int -> IO ()
+phase2 i = do
+ mv <- newEmptyMVar
+ done <- newEmptyMVar
+ kvar <- newEmptyMVar
+ let !p = i * 7919 + 3
+ !q = i * 104729 + 7
+ !u = i * 1299709 + 11
+ !v = i * 15485863 + 13
+ -- Capture a continuation whose resumption unmasks: the capture happens
+ -- inside restore, so its apply_mask_frame is the unmask frame.
+ _ <- forkIO $ do
+ tag <- newPromptTag
+ _ <- prompt tag $ mask $ \restore -> do
+ x <- restore (control0 tag (\k -> putMVar kvar k >> pure 0))
+ pure (useInts x p q u v)
+ pure ()
+ k <- takeMVar kvar
+ a <- forkIO $
+ handle (\Boom -> void (tryPutMVar done (Left Boom))) $ do
+ r <- uninterruptibleMask_ $ do
+ putMVar mv ()
+ threadDelay 2000 -- let the thrower queue its exception
+ k (pure 42) -- resuming unmasks with the exception pending
+ void (tryPutMVar done (Right r))
+ takeMVar mv
+ _ <- forkIO $ throwTo a Boom
+ void (takeMVar done)
+
+main :: IO ()
+main = do
+ forM_ [1 .. rounds] phase1
+ forM_ [1 .. rounds] phase2
+ putStrLn "ok"
=====================================
testsuite/tests/rts/continuations/T27651.stdout
=====================================
@@ -0,0 +1 @@
+ok
=====================================
testsuite/tests/rts/continuations/all.T
=====================================
@@ -9,3 +9,4 @@ test('cont_nondet_handler', [extra_files(['ContIO.hs'])], multimod_compile_and_r
test('cont_stack_overflow', [extra_files(['ContIO.hs'])], multimod_compile_and_run, ['cont_stack_overflow', '-with-rtsopts "-ki1k -kc2k -kb256"'])
test('T23513', [extra_files(['ContIO.hs'])], multimod_compile_and_run, ['T23513', ''])
+test('T27651', [extra_files(['ContIO.hs'])], multimod_compile_and_run, ['T27651', ''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3b1f7b57fa3513cbc8d324328f8274…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3b1f7b57fa3513cbc8d324328f8274…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
Zubin pushed to branch wip/9.14.2-rc2 at Glasgow Haskell Compiler / GHC
Commits:
9e6272cb by Zubin Duggal at 2026-09-15T13:12:45+05:30
Prepare 9.14.2-rc2
-------------------------
Metric Decrease:
T4029
-------------------------
- - - - -
24 changed files:
- − changelog.d/27626
- − changelog.d/27627
- − changelog.d/27703
- − changelog.d/27704
- − changelog.d/27717
- − changelog.d/T26423
- − changelog.d/T26716
- − changelog.d/T27202
- − changelog.d/T27308
- − changelog.d/T27314.md
- − changelog.d/T27360
- − changelog.d/T27440
- − changelog.d/T27455
- − changelog.d/T27583
- − changelog.d/T27586
- − changelog.d/T27639
- − changelog.d/T27657
- − changelog.d/T27705
- − changelog.d/arm_ncg_fixes_T27430
- − changelog.d/fix-parallel-gc-selector-race-27477
- − changelog.d/llvm-23
- − changelog.d/unit-index
- docs/users_guide/9.14.2-notes.rst
- libraries/base/changelog.md
Changes:
=====================================
changelog.d/27626 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where an argument used only by a function's stable unfolding
- could still be marked absent, resulting in a runtime crash.
-mrs: !16503
-issues: #27626
=====================================
changelog.d/27627 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where an absent constraint argument could be replaced by an
- error thunk, which GHC then evaluated, crashing the program.
-mrs: !16519
-issues: #27627
=====================================
changelog.d/27703 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where the specialiser could drop an argument that the
- function's stable unfolding still used, resulting in a runtime crash.
-mrs: !16519
-issues: #27703
=====================================
changelog.d/27704 deleted
=====================================
@@ -1,6 +0,0 @@
-section: compiler
-synopsis: Fix a bug where a class declared abstractly in an hs-boot file was
- assumed not to be unary, so GHC speculatively evaluated a dictionary that
- could be bottom, crashing the program.
-mrs: !16519
-issues: #27704
=====================================
changelog.d/27717 deleted
=====================================
@@ -1,6 +0,0 @@
-section: compiler
-synopsis: Fix a bug where -fspec-eval-dictfun could speculatively evaluate a
- looping dictionary whose recursion went through an hs-boot import, hanging
- the program.
-mrs: !16519
-issues: #27717
=====================================
changelog.d/T26423 deleted
=====================================
@@ -1,15 +0,0 @@
-section: compiler
-synopsis: Introduce ``ExternalUnitDatabases`` and ``ExternalUnitDatabaseCache`` to cache unit databases.
-issues: #26423
-mrs: !16115
-
-description: {
- Cache the ``UnitDatabase`` in memory in ``ExternalUnitDatabases`` to avoid constantly reading
- the same ``UnitDatabase`` from disk with multiple home units.
-
- Allows to share the on-disk representation of ``UnitInfo`` across the whole ``UnitEnv``.
- We cache a mutable version of ``ExternalUnitDatabases`` as ``ExternalUnitDatabaseCache``
- in ``UnitEnv``.
- This allows us more easily to change the ``packageDBFlags`` and reading new package databases
- from disk if required, but cache everything that has been read from disk before.
-}
=====================================
changelog.d/T26716 deleted
=====================================
@@ -1,15 +0,0 @@
-section: rts
-synopsis: Fix design of TSO blocking info, fixing a use-after-free bug
-issues: #26716 #26717
-mrs: !15519
-description: {
- Experimental work on ASAN support for GHC (MR !15168) revealed a
- use-after-free bug when using the combination of the new poll I/O
- manager with the compacting GC. The ultimate cause is that a TSO's
- `block_info` (used by I/O managers and many other parts of the RTS)
- is sometimes a GC pointer and sometimes not, but without a consistent
- and easy-to-follow rule for when this is the case. The solution has
- been to clean up and enforce that the TSO's `why_blocked` enumeration
- is a proper tag for the `block_info`, and to use an encoding that
- determines precisely when the `block_info` is a GC pointer or not.
-}
=====================================
changelog.d/T27202 deleted
=====================================
@@ -1,13 +0,0 @@
-section: ghci
-synopsis: Fix regression to honour module targets in nested directories into GHCi after startup.
-issues: #27202 #27640
-mrs: !15980 !16591
-
-description: {
- Fix a regression that made it impossible to import modules using `:load <Mod>` and `:add <Mod>` after GHCi startup.
- GHCi wasn't honouring the `-i<directory>` argument if given via `ghci -i<directory>`.
-
- Further, we fix a bug while setting up package database stacks for GHCi that was uncovered during this fix.
- By underspecifying the version of dependencies, import modules from dependencies were ambiguous, even though
- they shouldn't have been!
-}
=====================================
changelog.d/T27308 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-synopsis: Drop `preloadClosure` from `UnitState`
-issues: #27308
-mrs: !16108
-
-description: {
- Drop `preloadClosure` from `UnitState` as it is always set to the empty set.
- This allows to simplify the `UnitState` and related functions.
-}
-
=====================================
changelog.d/T27314.md deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27314
-mrs: !16118
-synopsis:
- Fix spurious ``-Wincomplete-uni-patterns`` warning under ``-finfo-table-map``.
-description:
- The pattern-match checker now ignores ticks when comparing scrutinees in
- its CoreMap, so long-distance information is no longer lost across
- function-application scrutinees because debug source annotations
- (e.g. SourceNotes added by ``-finfo-table-map``) were inserted.
=====================================
changelog.d/T27360 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27360
-mrs: !16161
-synopsis:
- Recognise ``considerAccessible`` under ticks (``-g``, ``-finfo-table-map``, ``-fhpc`` etc)
-description:
- The pattern-match checker now properly recognises ``considerAccessible`` even
- when it is surrounded by ticks (e.g. debug info ticks with ``-g``, with
- ``-finfo-table-map``, etc). This ensures it works as advertised, suppressing
- redundant pattern-match warnings, even when it occurs under a tick.
=====================================
changelog.d/T27440 deleted
=====================================
@@ -1,8 +0,0 @@
-section: compiler
-issues: #27440
-mrs: !16434
-synopsis:
- Fix a panic on ``@ty`` in a pattern synonym RHS
-description:
- An invisible type argument (``@ty``) in the right-hand side of an implicitly
- bidirectional pattern synonym no longer causes a panic.
=====================================
changelog.d/T27455 deleted
=====================================
@@ -1,8 +0,0 @@
-section: base
-issues: #27455
-mrs: !16274
-synopsis:
- Don't drop `ExceptionContext` in `SomeException(toException)`
-description:
- Previously the implementation of ``Exception(toException)`` given to `SomeException` would inappropriately drop the carried `ExceptionContext`. Now ``toException = id``, faithfully implementing the semantics proposed in :ref:`CLC Proposal #200 <https://github.com/haskell/core-libraries-committee/issues/200>`.
-
=====================================
changelog.d/T27583 deleted
=====================================
@@ -1,9 +0,0 @@
-section: compiler
-issues: #27583
-mrs: !16434
-synopsis:
- Fix spurious out-of-scope errors from ``type ty`` in a pattern synonym RHS
-description:
- A required type argument with an explicit namespace specifier (``type ty``)
- in the right-hand side of an implicitly bidirectional pattern synonym no
- longer reports variables bound by the pattern as out of scope.
=====================================
changelog.d/T27586 deleted
=====================================
@@ -1,9 +0,0 @@
-section: compiler
-issues: #27586
-mrs: !16440
-synopsis:
- Fix a panic on a required type argument in a pattern synonym RHS
-description:
- An argument of a pattern synonym that is matched against a required type
- argument in the right-hand side no longer causes a panic; it is reported as
- an illegal term-level use of a type variable.
=====================================
changelog.d/T27639 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27639
-mrs: !16474
-synopsis:
- Stop representation-polymorphism checks from producing a coercion that fails
- Core Lint.
-description:
- The representation-polymorphism check that is done when subsumption performs
- eta-expansion now composes the coercions it builds in the correct order,
- avoiding a Core Lint failure.
=====================================
changelog.d/T27657 deleted
=====================================
@@ -1,9 +0,0 @@
-section: base
-issues: #27657
-mrs: !16508
-synopsis:
- Fix ``retry`` and async exception delivery inside a ``catchSTM`` handler
-description:
- ``catchSTM``\'s ``WhileHandling`` annotation used ``catch#``, leaving an IO
- ``CATCH_FRAME`` inside the transaction. Use ``catchSTM#``, which is the
- correct way to catch exceptions inside STM.
=====================================
changelog.d/T27705 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fixed an issue that caused the specializer to sometimes loop on recursive dictionary superclasses.
-issues: #27705
-mrs: !16559
-
=====================================
changelog.d/arm_ncg_fixes_T27430 deleted
=====================================
@@ -1,18 +0,0 @@
-section: compiler
-issues: #27430 #27539 #27538 #27537 #27550 #27565 #27533
-mrs: !16255
-synopsis:
- A series of fixes to the ARM64 ncg, related to handling of primitive
- 8/16bit types and simd.
-description:
- A series of related fixes to the ncg fixing:
-
- Fixed sign extension for subword values returned from unsafe ffi calls.
- Clarify and lint for invalid conversions of int8/int16 -> float/double conversions.
- Fix incorrect clobbering of local variables when comparing signed subword values.
- Fix incorrect use of 32bit reads/stores for 8/16bit wide reads/stores.
- Fix zero extension on function entry if arguments are passed at word-width
- but used at subword-widths.
- Fix broadcast# for non-literal arguments (arm64 only).
- Fix rare assembler errors caused by overflowing literals, by properly checking
- whether a constant is a viable immediate argument.
=====================================
changelog.d/fix-parallel-gc-selector-race-27477 deleted
=====================================
@@ -1,10 +0,0 @@
-section: rts
-synopsis: Fix a parallel GC race on weakly-ordered architectures (AArch64) that could crash or silently corrupt the heap
-description:
- On weakly-ordered architectures such as AArch64 programs using
- could crash during parallel garbage collection (segmentation fault
- or ``internal error: eval_thunk_selector: strange selectee <n>``) or
- continue running with silently corrupted heap data, due to a missing
- memory barrier in the parallel GC.
-mrs: !16488
-issues: #27477
=====================================
changelog.d/llvm-23 deleted
=====================================
@@ -1,4 +0,0 @@
-section: llvm-backend
-synopsis: Bump LlvmMaxVersion to support LLVM 23.x releases.
-issues: #27764
-mrs: !16617
=====================================
changelog.d/unit-index deleted
=====================================
@@ -1,14 +0,0 @@
-section: compiler
-synopsis: Use global ``UnitIndex`` to deduplicate ``UnitInfo``s over multiple home units
-issues: #27500 #26423 #27748
-mrs: !16115 !16598
-
-description: {
- The ``UnitState`` used to be duplicated for all ``HomeUnitEnv``, not sharing any of the ``UnitInfo``s.
- This can lead to excessive memory usage with multiple home units and large package databases.
-
- Our solution to this problem is deduplicating ``UnitInfo``s globally across the whole ``UnitEnv``.
- We store this information in the ``UnitIndex`` which contains data global to all ``UnitState``s.
- All processed ``UnitInfo``s and the ``WiredMap`` are stored in there, and in the future, we might
- move more fields from ``UnitState`` to ``UnitIndex``.
-}
=====================================
docs/users_guide/9.14.2-notes.rst
=====================================
@@ -87,13 +87,30 @@ Compiler
- Make the order of usages deterministic (:ghc-ticket:`26877`)
- Fix the interaction of ExplicitLevelImports with qualified imports (:ghc-ticket:`26616`, :ghc-ticket:`27385`)
- Rename ZonkAny to UnusedType and add pretty printing logic for it (:ghc-ticket:`27390`)
+- Cache unit databases and use a global ``UnitIndex`` to deduplicate
+ ``UnitInfo``\s across multiple home units, reducing memory usage
+ (:ghc-ticket:`26423`, :ghc-ticket:`27500`, :ghc-ticket:`27748`)
+- Drop ``preloadClosure`` from ``UnitState`` (:ghc-ticket:`27308`)
+- Fix a bug where an argument used only by a function's stable unfolding could still be marked absent, resulting in a runtime crash. (:ghc-ticket:`27626`)
+- Fix a bug where an absent constraint argument could be replaced by an error thunk, which GHC then evaluated, crashing the program. (:ghc-ticket:`27627`)
+- Fix a bug where the specialiser could drop an argument that the function's stable unfolding still used, resulting in a runtime crash. (:ghc-ticket:`27703`)
+- Fix a bug where a class declared abstractly in an hs-boot file was assumed not to be unary, so GHC speculatively evaluated a dictionary that could be bottom, crashing the program. (:ghc-ticket:`27704`)
+- Fix a bug where ``-fspec-eval-dictfun`` could speculatively evaluate a looping dictionary whose recursion went through an hs-boot import, hanging the program. (:ghc-ticket:`27717`)
+- Fix a panic on ``@ty`` in a pattern synonym RHS (:ghc-ticket:`27440`)
+- Fix spurious out-of-scope errors from ``type ty`` in a pattern synonym RHS (:ghc-ticket:`27583`)
+- Fix a panic on a required type argument in a pattern synonym RHS (:ghc-ticket:`27586`)
+- Stop representation-polymorphism checks from producing a coercion that fails Core Lint. (:ghc-ticket:`27639`)
+- Fixed an issue that caused the specializer to sometimes loop on recursive dictionary superclasses. (:ghc-ticket:`27705`)
+- Bumped the maximum supported LLVM version to 23 (:ghc-ticket:`27764`)
+- Recognise ``considerAccessible`` under ticks (``-g``, ``-finfo-table-map``, ``-fhpc`` etc) (:ghc-ticket:`27360`)
+- Fix spurious ``-Wincomplete-uni-patterns`` warning under ``-finfo-table-map``. (:ghc-ticket:`27314`)
GHCi
~~~~
- Added the ``-fimport-loaded-targets`` flag, which automatically imports all loaded targets into the GHCi session (:ghc-ticket:`26866`)
- Added support for custom external interpreter commands, allowing GHC API clients to extend the external interpreter with their own message handlers (:ghc-ticket:`26652`)
-- Fix regression to allow loading modules into the GHCi after startup (:ghc-ticket:`27202`)
+- Fix regression to allow loading modules into the GHCi after startup (:ghc-ticket:`27202`, :ghc-ticket:`27640`)
- Fixed the GHCi prompt and session home units to use a consistent package database stack, avoiding spurious ambiguous-import errors for home unit dependencies (:ghc-ticket:`27202`)
- Fixed the order in which ``:info`` lists instances, which previously depended on the order in which interface files happened to be loaded (:ghc-ticket:`27532`)
@@ -128,6 +145,9 @@ Runtime System
- Fix several black hole handling bugs that could lead to deadlocks or crashes in multithreaded programs. These could show up as the program hanging or "END_TSO_QUEUE object entered" errors (:ghc-ticket:`26922`, :ghc-ticket:`26936`)
- Rethrow exceptions in overlapped IO when using the WinIO IO manager (:ghc-ticket:`27283`)
- Fix "unknown/strange object 24 crash" in compacting GC (:ghc-ticket:`27434`)
+- Fix a possible use-after-free bug with TSOs (:ghc-ticket:`26716`, :ghc-ticket:`26717`)
+- Fix a parallel GC race on weakly-ordered architectures (AArch64) that could crash or silently corrupt the heap (:ghc-ticket:`27477`)
+- Fix stack corruption when returning large unboxed tuples in GHCi (:ghc-ticket:`27633`)
Code Generation
~~~~~~~~~~~~~~~
@@ -139,6 +159,10 @@ Code Generation
- Fix module finalizers on multiple platforms (:ghc-ticket:`27072`)
- Fix miscompiled %load_relaxed primop, add missing %store_relaxed (:ghc-ticket:`27483`)
- Fix redundant AP thunk codegen when not using -ticky-ap-thunk (:ghc-ticket:`27502`)
+- A number of fixes to the ARM64 ncg, fixing a number of bugs, including
+ incorrect runtime results when using subword operations
+ (:ghc-ticket:`27430`, :ghc-ticket:`27539`, :ghc-ticket:`27538`,
+ :ghc-ticket:`27537`, :ghc-ticket:`27550`, :ghc-ticket:`27533`)
Bytecode Compiler
~~~~~~~~~~~~~~~~~
@@ -151,6 +175,8 @@ Bytecode Compiler
~~~~~~~~~~~~~~~~
- Added ``@since`` annotation to ``System.Info.fullCompilerVersion`` (:ghc-ticket:`26973`)
+- Don't drop ``ExceptionContext`` in ``SomeException(toException)`` (:ghc-ticket:`27455`)
+- Fix ``retry`` and async exception delivery inside a ``catchSTM`` handler (:ghc-ticket:`27657`)
``ghc-heap`` library
~~~~~~~~~~~~~~~~~~~~
=====================================
libraries/base/changelog.md
=====================================
@@ -8,6 +8,7 @@
* Hide implementation details of `throw` and `throwSTM` from exception stack traces ([CLC proposal #387](https://github.com/haskell/core-libraries-committee/issues/387), [#26808](https://gitlab.haskell.org/ghc/ghc/-/issues/26808))
* GHC internals re-exported from `GHC.Num` have been deprecated and will be removed after one major release ([CLC proposal #360](https://github.com/haskell/core-libraries-committee/issues/360))
* The implementation of `toException` in `SomeException`'s `Exception` instance no longer drops exception context, in keeping with the behavior originally proposed in [CLC Proposal #200](https://github.com/haskell/core-libraries-committee/issues/200).
+ * Fix `retry` and async exception delivery inside a `catchSTM` handler ([#27657](https://gitlab.haskell.org/ghc/ghc/-/issues/27657))
## 4.22.0.0 *December 2025*
* Shipped with GHC 9.14.1
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9e6272cb9980ec4d3bc2fa8f04a2ecb…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9e6272cb9980ec4d3bc2fa8f04a2ecb…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/T27629] 22 commits: rts: fix ctoi_tuple_spill_words getting out of sync
by Simon Peyton Jones (@simonpj) 15 Sep '26
by Simon Peyton Jones (@simonpj) 15 Sep '26
15 Sep '26
Simon Peyton Jones pushed to branch wip/T27629 at Glasgow Haskell Compiler / GHC
Commits:
192be0b6 by Luite Stegeman at 2026-09-07T19:43:36-04:00
rts: fix ctoi_tuple_spill_words getting out of sync
Fix a few places that were not updating ctoi_tuple_spill_words
correctly, leading to corruption/crashes when dealing with large
unboxed tuples in bytecode:
- captureContinuationAndAbort
- findRetryFrameHelper/findAtomicallyFrameHelper
- interpretBCO bci_BRK_FUN
fixes #27633
- - - - -
604eb43c by Simon Jakobi at 2026-09-07T19:44:15-04:00
Hadrian: don't capture the testsuite driver's output (#27780)
a6061455d54 switched the Testsuite RunTest case from Shake's cmd to the
cmd' wrapper. cmd' always captures stdout and stderr, and since the
caller asks for Exit, it returns without dumping what it captured. As a
result the testsuite output no longer appears in CI job logs: failures,
performance metrics and the summary were lost with the job.
Use cmdExe, the uncaptured cmd, as the other plain-cmd sites in that
commit do.
Fixes #27780.
Assisted-by: Claude Fable 5.1
- - - - -
06eee015 by Luite Stegeman at 2026-09-08T06:03:06+02:00
rts: Fix missing memory barrier in eval_thunk_selector (#27477)
unchain_thunk_selectors() was missing an ACQUIRE_LOAD for the
indirectee, leading to segfaults and corruption during GC on
weakly-ordered architectures.
Fixes #27477
- - - - -
f8b2bd8f by Alan Zimmerman at 2026-09-08T09:39:12-04:00
EPA Fix HsCmdDo exact print with comments
Exact printing of HsCmdDo was ignoring the location for the do
statements, and this is an annotation that can have comments in it.
Update it so we print the statements as a unit, including any
comments.
Also add the result of auditing that we capture comments in all needed
places, noting that the remaining Anno SrcSpan instances are benign.
- - - - -
430967ab by Duncan Coutts at 2026-09-09T11:07:01+01:00
Reorder cmm decls in HeapStackCheck for a better logical grouping
And put more section headers in to deliniate the groups.
We're about to add more here, so better to organise it first.
- - - - -
344080fd by Duncan Coutts at 2026-09-09T11:07:01+01:00
Add raisePrimIOException and add it to RTS<->ghc-internal API
The raisePrimIOException is a new helper function that I/O primops will
use to help them report I/O errors. This is implemented in Haskell
(since that's a lot easier), but has a calling convention that is
easy(ish) to use from Cmm in the I/O primops.
So we add it to the RTS API struct, and since we'll use it from Cmm we
also need a field accessor macro for cmm (in deriveConstants).
See the Note about how we cannot have nice things due to async
exceptions and thunks preventing us from using catch.
- - - - -
cfdb3399 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Add new blocking functions for I/O primops
See the Note [Thread blocking for new I/O primops],
and the Note [Calling convention for raisePrimIOException].
The point is, it will allow us to report synchronous exceptions from I/O
primops, and do so much more flexibly.
Previously the I/O managers could only report async exceptions and only
nullary exceptions. This was OK historically, but no good as we add
more I/O managers and expand the range of I/O operations we support.
- - - - -
f09c09d8 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Change the encoding of results from the I/O manager to I/O primops
Previously we just had async continue or heap overflow.
We now extend what we can report with synchronous success, and
synchronous failure with an errno.
See Note [Encoding of result of I/O manager operations]
We don't use these two new cases yet, but we will. In particular an
epoll I/O manager needs to be able to report synchronous success or
failure for waitRead#/waitWrite#.
- - - - -
30f074d9 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Switch waitRead/Write# to use new blocking return frames
and update the I/O managers to set the result before resuming the
blocked threads.
This makes it possible for I/O managers to report synchronous exceptions
from the I/O primops, but that will be done in a subsequent commit.
- - - - -
a8786ced by Duncan Coutts at 2026-09-09T11:07:01+01:00
Switch Poll and Select I/O managers to report sync exceptions
rather than using raiseAsync with blockedOnBadFD_closure.
This uses the new mechanism in the blocking frame return code to report
synchronous exceptions.
- - - - -
7a9df79a by Duncan Coutts at 2026-09-09T11:07:01+01:00
Remove now-unused blockedOnBadFD
It was previously thrown by the select and poll I/O managers, but now
they use raisePrimIOException (with an EBADF errno).
- - - - -
6b0424e3 by Duncan Coutts at 2026-09-09T11:07:01+01:00
Improve the docs for delay# waitRead# and waitWrite#
Document that the waitRead/Write# can throw exceptions (this was true
before too), and that all of them are async exception cancellation
points.
- - - - -
afeb2c30 by Duncan Coutts at 2026-09-09T20:08:58-04:00
Enable printf warnings for trace functions and fix resulting warnings
Most of the existing printf-style functions are annotated with
attributes to enable gcc/clang warnings for the printf format string,
but several trace functions in Trace.h were missing this annotation.
Enable them, and fix the resulting warnings.
- - - - -
9a442c93 by Alan Zimmerman at 2026-09-09T20:09:36-04:00
EPA: Exact print ConDeclGADT without custom enterAnn
!16321 brought in explicit capture of parens in a ConDeclGADT.
The ExactPrint update introduced a modification of the fundamental
function in exact printing, `enterAnn`, by splitting it into a version
allowing injection of functionality normally handled by the
ExactPrint class methods.
This commit refactors that code, to restore the prior `enterAnn`
version, by following the convention in ExactPrint of introducing a
helper data structure with its own `ExactPrint` instance to achieve
the same effect.
- - - - -
4e9297ea by Simon Jakobi at 2026-09-11T08:32:45-04:00
ci: Actually pass --ignore-perf-failures to the testsuite driver
684c0018d9 changed the IGNORE_PERF_FAILURES handling to append to
RUNTEST_ARGS with bash array syntax, but the three use sites still
expand RUNTEST_ARGS as a scalar, which yields only the first array
element. The appended flag was therefore dropped in every job, so
perf improvements kept failing Marge Bot batches and master pipelines,
contrary to #19562.
Append as a string instead, matching the existing --force-colors
append in test_hadrian.
Fixes #27563.
Assisted-by: Claude Fable 5.1
- - - - -
4f78dfdf by Simon Jakobi at 2026-09-11T08:33:24-04:00
testsuite: Give T26537 a 1.5x compile timeout
Its -fregs-graph compile step tends to time out in unoptimized builds
(#27188, #27776).
Assisted-by: Claude Fable 5.1
- - - - -
130286e3 by Alan Zimmerman at 2026-09-11T08:34:08-04:00
EPA: Remove ListBanana / ListParens from AnnListBrackets
This is a step towards making AnnList only represent
lists of items which can have either braces or layout.
- - - - -
a9827d13 by Simon Jakobi at 2026-09-11T18:53:32-04:00
Reject ~, UNPACK and multiplicity annotations on type data fields
Only `!` was rejected so far. `~`, UNPACK and multiplicity annotations
were silently accepted. None of them make sense at the type level, so
restriction (R3) of Note [Type data declarations] now covers all of
them.
Fixes #27732.
Assisted-by: Claude Fable 5.1
- - - - -
c71d5e23 by Alan Zimmerman at 2026-09-11T18:54:11-04:00
EPA: Add a Note for the exact print main loop
- - - - -
7a108e43 by Simon Jakobi at 2026-09-12T18:35:59-04:00
FastString: Drop mkFastStringWith's constructor callback
All three callers passed the same callback, a partial application of
mkNewFastStringShortByteString to the string being interned. That
partial application is allocated as a closure before the table lookup,
on the common hit path too, although the callback is needed only after
a miss.
Drop the parameter and call mkNewFastStringShortByteString directly
after a miss. Since nothing is passed "with" anymore, rename the
function to internSB.
Suggested by Simon PJ in #27528:
https://gitlab.haskell.org/ghc/ghc/-/work_items/27528#note_687031
Assisted-by: Claude Fable 5
- - - - -
82c73b22 by Alan Zimmerman at 2026-09-12T18:36:38-04:00
EPA: More targeted HsDo exact print annotation
HsDo is multi-purpose, as encoded in its HsDoFlavour field. Some of
these are in a layout context (DoExpr, MDoExpr), others are not
(ListComp, MonadComp).
We are moving towards using AnnList only in layout contexts, so we
switch the HsDo TTG annotation from holding an AnnList for this, to
holding
Either (EpToken "[", EpToken "]") AnnList
This also allows us to trim down AnnListBrackets to only have braces
or None, thereby opening the door for unification with the existing
layout context data type EpLayout.
- - - - -
64c267e3 by Simon Peyton Jones at 2026-09-15T08:37:31+01:00
Re-introduce the "weird SpecDict" case
In this commit
commit f80375dd4945350a1d784e436975b48b9c736eaf
Author: Simon Peyton Jones <simon.peytonjones(a)gmail.com>
Date: Sun Jun 29 15:26:58 2025 +0100
Refactor of Specialise.hs
I removed a test for a dictionary with unbound type variables. This
turned out to be wrong; see #27629.
So this MR re-introduces it.
- - - - -
97 changed files:
- .gitlab/ci.sh
- + changelog.d/27732
- + changelog.d/T27629
- + changelog.d/fix-parallel-gc-selector-race-27477
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Extension/Pass.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Errors/Types.hs
- docs/users_guide/exts/type_data.rst
- hadrian/src/Builder.hs
- libraries/ghc-internal/include/RtsIfaceSymbols.h
- libraries/ghc-internal/src/GHC/Internal/Conc/IO.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Thread.hs
- rts/Capability.c
- rts/Continuation.c
- rts/HeapStackCheck.cmm
- rts/IOManager.c
- rts/IOManager.h
- rts/IOManagerInternals.h
- rts/Interpreter.c
- rts/Messages.c
- rts/Prelude.h
- rts/PrimOps.cmm
- rts/Printer.c
- rts/STM.c
- rts/Schedule.c
- rts/Sparks.c
- rts/StableName.c
- rts/ThreadPaused.c
- rts/Threads.c
- rts/Trace.h
- rts/include/rts/RtsToHsIface.h
- rts/include/stg/MiscClosures.h
- rts/posix/Poll.c
- rts/posix/Poll.h
- rts/posix/Select.c
- rts/posix/Timeout.c
- rts/sm/Compact.c
- rts/sm/Evac.c
- rts/sm/GC.c
- rts/sm/GCUtils.c
- rts/sm/MBlock.c
- rts/sm/NonMoving.c
- rts/sm/NonMovingMark.c
- rts/sm/Storage.c
- rts/sm/Sweep.c
- + testsuite/tests/bytecode/T27633/Obj.hs
- + testsuite/tests/bytecode/T27633/T27633a.hs
- + testsuite/tests/bytecode/T27633/T27633a.stdout
- + testsuite/tests/bytecode/T27633/T27633b.hs
- + testsuite/tests/bytecode/T27633/T27633b.stdout
- + testsuite/tests/bytecode/T27633/all.T
- testsuite/tests/codeGen/should_run/all.T
- testsuite/tests/ghc-api/T25121_status.stdout
- + testsuite/tests/ghci.debugger/scripts/T27633c.hs
- + testsuite/tests/ghci.debugger/scripts/T27633c.script
- + testsuite/tests/ghci.debugger/scripts/T27633c.stdout
- + testsuite/tests/ghci.debugger/scripts/T27633c_obj.hs
- testsuite/tests/ghci.debugger/scripts/all.T
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/printer/Test20297.stdout
- + testsuite/tests/rts/T27477.hs
- + testsuite/tests/rts/T27477.stdout
- testsuite/tests/rts/all.T
- testsuite/tests/simplCore/should_compile/Makefile
- + testsuite/tests/simplCore/should_compile/T27629.hs
- + testsuite/tests/simplCore/should_compile/T27629.stderr
- + testsuite/tests/simplCore/should_compile/T27629Plugin.hs
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/type-data/should_fail/T27732a.hs
- + testsuite/tests/type-data/should_fail/T27732a.stderr
- + testsuite/tests/type-data/should_fail/T27732b.hs
- + testsuite/tests/type-data/should_fail/T27732b.stderr
- + testsuite/tests/type-data/should_fail/T27732c.hs
- + testsuite/tests/type-data/should_fail/T27732c.stderr
- + testsuite/tests/type-data/should_fail/T27732d.hs
- + testsuite/tests/type-data/should_fail/T27732d.stderr
- + testsuite/tests/type-data/should_fail/T27732e.hs
- + testsuite/tests/type-data/should_fail/T27732e.stderr
- + testsuite/tests/type-data/should_fail/T27732f.hs
- + testsuite/tests/type-data/should_fail/T27732f.stderr
- testsuite/tests/type-data/should_fail/TDStrictnessGADT.stderr
- testsuite/tests/type-data/should_fail/TDStrictnessH98.stderr
- testsuite/tests/type-data/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Utils.hs
- utils/deriveConstants/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e4f13ef9707208cdbf70a4d49c5f3d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e4f13ef9707208cdbf70a4d49c5f3d…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc] Pushed new branch wip/sjakobi/faststring-internsb-core
by Simon Jakobi (@sjakobi) 15 Sep '26
by Simon Jakobi (@sjakobi) 15 Sep '26
15 Sep '26
Simon Jakobi pushed new branch wip/sjakobi/faststring-internsb-core at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/sjakobi/faststring-internsb-c…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
Zubin pushed to branch wip/9.14.2-rc2 at Glasgow Haskell Compiler / GHC
Commits:
53454240 by Zubin Duggal at 2026-09-15T12:09:10+05:30
Prepare 9.14.2-rc2
-------------------------
Metric Decrease:
T4029
-------------------------
- - - - -
24 changed files:
- − changelog.d/27626
- − changelog.d/27627
- − changelog.d/27703
- − changelog.d/27704
- − changelog.d/27717
- − changelog.d/T26423
- − changelog.d/T26716
- − changelog.d/T27202
- − changelog.d/T27308
- − changelog.d/T27314.md
- − changelog.d/T27360
- − changelog.d/T27440
- − changelog.d/T27455
- − changelog.d/T27583
- − changelog.d/T27586
- − changelog.d/T27639
- − changelog.d/T27657
- − changelog.d/T27705
- − changelog.d/arm_ncg_fixes_T27430
- − changelog.d/fix-parallel-gc-selector-race-27477
- − changelog.d/llvm-23
- − changelog.d/unit-index
- docs/users_guide/9.14.2-notes.rst
- libraries/base/changelog.md
Changes:
=====================================
changelog.d/27626 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where an argument used only by a function's stable unfolding
- could still be marked absent, resulting in a runtime crash.
-mrs: !16503
-issues: #27626
=====================================
changelog.d/27627 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where an absent constraint argument could be replaced by an
- error thunk, which GHC then evaluated, crashing the program.
-mrs: !16519
-issues: #27627
=====================================
changelog.d/27703 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fix a bug where the specialiser could drop an argument that the
- function's stable unfolding still used, resulting in a runtime crash.
-mrs: !16519
-issues: #27703
=====================================
changelog.d/27704 deleted
=====================================
@@ -1,6 +0,0 @@
-section: compiler
-synopsis: Fix a bug where a class declared abstractly in an hs-boot file was
- assumed not to be unary, so GHC speculatively evaluated a dictionary that
- could be bottom, crashing the program.
-mrs: !16519
-issues: #27704
=====================================
changelog.d/27717 deleted
=====================================
@@ -1,6 +0,0 @@
-section: compiler
-synopsis: Fix a bug where -fspec-eval-dictfun could speculatively evaluate a
- looping dictionary whose recursion went through an hs-boot import, hanging
- the program.
-mrs: !16519
-issues: #27717
=====================================
changelog.d/T26423 deleted
=====================================
@@ -1,15 +0,0 @@
-section: compiler
-synopsis: Introduce ``ExternalUnitDatabases`` and ``ExternalUnitDatabaseCache`` to cache unit databases.
-issues: #26423
-mrs: !16115
-
-description: {
- Cache the ``UnitDatabase`` in memory in ``ExternalUnitDatabases`` to avoid constantly reading
- the same ``UnitDatabase`` from disk with multiple home units.
-
- Allows to share the on-disk representation of ``UnitInfo`` across the whole ``UnitEnv``.
- We cache a mutable version of ``ExternalUnitDatabases`` as ``ExternalUnitDatabaseCache``
- in ``UnitEnv``.
- This allows us more easily to change the ``packageDBFlags`` and reading new package databases
- from disk if required, but cache everything that has been read from disk before.
-}
=====================================
changelog.d/T26716 deleted
=====================================
@@ -1,15 +0,0 @@
-section: rts
-synopsis: Fix design of TSO blocking info, fixing a use-after-free bug
-issues: #26716 #26717
-mrs: !15519
-description: {
- Experimental work on ASAN support for GHC (MR !15168) revealed a
- use-after-free bug when using the combination of the new poll I/O
- manager with the compacting GC. The ultimate cause is that a TSO's
- `block_info` (used by I/O managers and many other parts of the RTS)
- is sometimes a GC pointer and sometimes not, but without a consistent
- and easy-to-follow rule for when this is the case. The solution has
- been to clean up and enforce that the TSO's `why_blocked` enumeration
- is a proper tag for the `block_info`, and to use an encoding that
- determines precisely when the `block_info` is a GC pointer or not.
-}
=====================================
changelog.d/T27202 deleted
=====================================
@@ -1,13 +0,0 @@
-section: ghci
-synopsis: Fix regression to honour module targets in nested directories into GHCi after startup.
-issues: #27202 #27640
-mrs: !15980 !16591
-
-description: {
- Fix a regression that made it impossible to import modules using `:load <Mod>` and `:add <Mod>` after GHCi startup.
- GHCi wasn't honouring the `-i<directory>` argument if given via `ghci -i<directory>`.
-
- Further, we fix a bug while setting up package database stacks for GHCi that was uncovered during this fix.
- By underspecifying the version of dependencies, import modules from dependencies were ambiguous, even though
- they shouldn't have been!
-}
=====================================
changelog.d/T27308 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-synopsis: Drop `preloadClosure` from `UnitState`
-issues: #27308
-mrs: !16108
-
-description: {
- Drop `preloadClosure` from `UnitState` as it is always set to the empty set.
- This allows to simplify the `UnitState` and related functions.
-}
-
=====================================
changelog.d/T27314.md deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27314
-mrs: !16118
-synopsis:
- Fix spurious ``-Wincomplete-uni-patterns`` warning under ``-finfo-table-map``.
-description:
- The pattern-match checker now ignores ticks when comparing scrutinees in
- its CoreMap, so long-distance information is no longer lost across
- function-application scrutinees because debug source annotations
- (e.g. SourceNotes added by ``-finfo-table-map``) were inserted.
=====================================
changelog.d/T27360 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27360
-mrs: !16161
-synopsis:
- Recognise ``considerAccessible`` under ticks (``-g``, ``-finfo-table-map``, ``-fhpc`` etc)
-description:
- The pattern-match checker now properly recognises ``considerAccessible`` even
- when it is surrounded by ticks (e.g. debug info ticks with ``-g``, with
- ``-finfo-table-map``, etc). This ensures it works as advertised, suppressing
- redundant pattern-match warnings, even when it occurs under a tick.
=====================================
changelog.d/T27440 deleted
=====================================
@@ -1,8 +0,0 @@
-section: compiler
-issues: #27440
-mrs: !16434
-synopsis:
- Fix a panic on ``@ty`` in a pattern synonym RHS
-description:
- An invisible type argument (``@ty``) in the right-hand side of an implicitly
- bidirectional pattern synonym no longer causes a panic.
=====================================
changelog.d/T27455 deleted
=====================================
@@ -1,8 +0,0 @@
-section: base
-issues: #27455
-mrs: !16274
-synopsis:
- Don't drop `ExceptionContext` in `SomeException(toException)`
-description:
- Previously the implementation of ``Exception(toException)`` given to `SomeException` would inappropriately drop the carried `ExceptionContext`. Now ``toException = id``, faithfully implementing the semantics proposed in :ref:`CLC Proposal #200 <https://github.com/haskell/core-libraries-committee/issues/200>`.
-
=====================================
changelog.d/T27583 deleted
=====================================
@@ -1,9 +0,0 @@
-section: compiler
-issues: #27583
-mrs: !16434
-synopsis:
- Fix spurious out-of-scope errors from ``type ty`` in a pattern synonym RHS
-description:
- A required type argument with an explicit namespace specifier (``type ty``)
- in the right-hand side of an implicitly bidirectional pattern synonym no
- longer reports variables bound by the pattern as out of scope.
=====================================
changelog.d/T27586 deleted
=====================================
@@ -1,9 +0,0 @@
-section: compiler
-issues: #27586
-mrs: !16440
-synopsis:
- Fix a panic on a required type argument in a pattern synonym RHS
-description:
- An argument of a pattern synonym that is matched against a required type
- argument in the right-hand side no longer causes a panic; it is reported as
- an illegal term-level use of a type variable.
=====================================
changelog.d/T27639 deleted
=====================================
@@ -1,10 +0,0 @@
-section: compiler
-issues: #27639
-mrs: !16474
-synopsis:
- Stop representation-polymorphism checks from producing a coercion that fails
- Core Lint.
-description:
- The representation-polymorphism check that is done when subsumption performs
- eta-expansion now composes the coercions it builds in the correct order,
- avoiding a Core Lint failure.
=====================================
changelog.d/T27657 deleted
=====================================
@@ -1,9 +0,0 @@
-section: base
-issues: #27657
-mrs: !16508
-synopsis:
- Fix ``retry`` and async exception delivery inside a ``catchSTM`` handler
-description:
- ``catchSTM``\'s ``WhileHandling`` annotation used ``catch#``, leaving an IO
- ``CATCH_FRAME`` inside the transaction. Use ``catchSTM#``, which is the
- correct way to catch exceptions inside STM.
=====================================
changelog.d/T27705 deleted
=====================================
@@ -1,5 +0,0 @@
-section: compiler
-synopsis: Fixed an issue that caused the specializer to sometimes loop on recursive dictionary superclasses.
-issues: #27705
-mrs: !16559
-
=====================================
changelog.d/arm_ncg_fixes_T27430 deleted
=====================================
@@ -1,18 +0,0 @@
-section: compiler
-issues: #27430 #27539 #27538 #27537 #27550 #27565 #27533
-mrs: !16255
-synopsis:
- A series of fixes to the ARM64 ncg, related to handling of primitive
- 8/16bit types and simd.
-description:
- A series of related fixes to the ncg fixing:
-
- Fixed sign extension for subword values returned from unsafe ffi calls.
- Clarify and lint for invalid conversions of int8/int16 -> float/double conversions.
- Fix incorrect clobbering of local variables when comparing signed subword values.
- Fix incorrect use of 32bit reads/stores for 8/16bit wide reads/stores.
- Fix zero extension on function entry if arguments are passed at word-width
- but used at subword-widths.
- Fix broadcast# for non-literal arguments (arm64 only).
- Fix rare assembler errors caused by overflowing literals, by properly checking
- whether a constant is a viable immediate argument.
=====================================
changelog.d/fix-parallel-gc-selector-race-27477 deleted
=====================================
@@ -1,10 +0,0 @@
-section: rts
-synopsis: Fix a parallel GC race on weakly-ordered architectures (AArch64) that could crash or silently corrupt the heap
-description:
- On weakly-ordered architectures such as AArch64 programs using
- could crash during parallel garbage collection (segmentation fault
- or ``internal error: eval_thunk_selector: strange selectee <n>``) or
- continue running with silently corrupted heap data, due to a missing
- memory barrier in the parallel GC.
-mrs: !16488
-issues: #27477
=====================================
changelog.d/llvm-23 deleted
=====================================
@@ -1,4 +0,0 @@
-section: llvm-backend
-synopsis: Bump LlvmMaxVersion to support LLVM 23.x releases.
-issues: #27764
-mrs: !16617
=====================================
changelog.d/unit-index deleted
=====================================
@@ -1,14 +0,0 @@
-section: compiler
-synopsis: Use global ``UnitIndex`` to deduplicate ``UnitInfo``s over multiple home units
-issues: #27500 #26423 #27748
-mrs: !16115 !16598
-
-description: {
- The ``UnitState`` used to be duplicated for all ``HomeUnitEnv``, not sharing any of the ``UnitInfo``s.
- This can lead to excessive memory usage with multiple home units and large package databases.
-
- Our solution to this problem is deduplicating ``UnitInfo``s globally across the whole ``UnitEnv``.
- We store this information in the ``UnitIndex`` which contains data global to all ``UnitState``s.
- All processed ``UnitInfo``s and the ``WiredMap`` are stored in there, and in the future, we might
- move more fields from ``UnitState`` to ``UnitIndex``.
-}
=====================================
docs/users_guide/9.14.2-notes.rst
=====================================
@@ -87,13 +87,30 @@ Compiler
- Make the order of usages deterministic (:ghc-ticket:`26877`)
- Fix the interaction of ExplicitLevelImports with qualified imports (:ghc-ticket:`26616`, :ghc-ticket:`27385`)
- Rename ZonkAny to UnusedType and add pretty printing logic for it (:ghc-ticket:`27390`)
+- Cache unit databases and use a global ``UnitIndex`` to deduplicate
+ ``UnitInfo``\s across multiple home units, reducing memory usage
+ (:ghc-ticket:`26423`, :ghc-ticket:`27500`, :ghc-ticket:`27748`)
+- Drop ``preloadClosure`` from ``UnitState`` (:ghc-ticket:`27308`)
+- Fix a bug where an argument used only by a function's stable unfolding could still be marked absent, resulting in a runtime crash. (:ghc-ticket:`27626`)
+- Fix a bug where an absent constraint argument could be replaced by an error thunk, which GHC then evaluated, crashing the program. (:ghc-ticket:`27627`)
+- Fix a bug where the specialiser could drop an argument that the function's stable unfolding still used, resulting in a runtime crash. (:ghc-ticket:`27703`)
+- Fix a bug where a class declared abstractly in an hs-boot file was assumed not to be unary, so GHC speculatively evaluated a dictionary that could be bottom, crashing the program. (:ghc-ticket:`27704`)
+- Fix a bug where ``-fspec-eval-dictfun`` could speculatively evaluate a looping dictionary whose recursion went through an hs-boot import, hanging the program. (:ghc-ticket:`27717`)
+- Fix a panic on ``@ty`` in a pattern synonym RHS (:ghc-ticket:`27440`)
+- Fix spurious out-of-scope errors from ``type ty`` in a pattern synonym RHS (:ghc-ticket:`27583`)
+- Fix a panic on a required type argument in a pattern synonym RHS (:ghc-ticket:`27586`)
+- Stop representation-polymorphism checks from producing a coercion that fails Core Lint. (:ghc-ticket:`27639`)
+- Fixed an issue that caused the specializer to sometimes loop on recursive dictionary superclasses. (:ghc-ticket:`27705`)
+- Bumped the maximum supported LLVM version to 23 (:ghc-ticket:`27764`)
+- Recognise ``considerAccessible`` under ticks (``-g``, ``-finfo-table-map``, ``-fhpc`` etc) (:ghc-ticket:`27360`)
+- Fix spurious ``-Wincomplete-uni-patterns`` warning under ``-finfo-table-map``. (:ghc-ticket:`27314`)
GHCi
~~~~
- Added the ``-fimport-loaded-targets`` flag, which automatically imports all loaded targets into the GHCi session (:ghc-ticket:`26866`)
- Added support for custom external interpreter commands, allowing GHC API clients to extend the external interpreter with their own message handlers (:ghc-ticket:`26652`)
-- Fix regression to allow loading modules into the GHCi after startup (:ghc-ticket:`27202`)
+- Fix regression to allow loading modules into the GHCi after startup (:ghc-ticket:`27202`, :ghc-ticket:`27640`)
- Fixed the GHCi prompt and session home units to use a consistent package database stack, avoiding spurious ambiguous-import errors for home unit dependencies (:ghc-ticket:`27202`)
- Fixed the order in which ``:info`` lists instances, which previously depended on the order in which interface files happened to be loaded (:ghc-ticket:`27532`)
@@ -128,6 +145,9 @@ Runtime System
- Fix several black hole handling bugs that could lead to deadlocks or crashes in multithreaded programs. These could show up as the program hanging or "END_TSO_QUEUE object entered" errors (:ghc-ticket:`26922`, :ghc-ticket:`26936`)
- Rethrow exceptions in overlapped IO when using the WinIO IO manager (:ghc-ticket:`27283`)
- Fix "unknown/strange object 24 crash" in compacting GC (:ghc-ticket:`27434`)
+- Fix a possible use-after-free bug with TSOs (:ghc-ticket:`26716`, :ghc-ticket:`26717`)
+- Fix a parallel GC race on weakly-ordered architectures (AArch64) that could crash or silently corrupt the heap (:ghc-ticket:`27477`)
+- Fix stack corruption when returning large unboxed tuples in GHCi (:ghc-ticket:`27633`)
Code Generation
~~~~~~~~~~~~~~~
@@ -139,6 +159,10 @@ Code Generation
- Fix module finalizers on multiple platforms (:ghc-ticket:`27072`)
- Fix miscompiled %load_relaxed primop, add missing %store_relaxed (:ghc-ticket:`27483`)
- Fix redundant AP thunk codegen when not using -ticky-ap-thunk (:ghc-ticket:`27502`)
+- A number of fixes to the ARM64 ncg, fixing a number of bugs, including
+ incorrect runtime results when using subword operations
+ (:ghc-ticket:`27430`, :ghc-ticket:`27539`, :ghc-ticket:`27538`,
+ :ghc-ticket:`27537`, :ghc-ticket:`27550`, :ghc-ticket:`27533`)
Bytecode Compiler
~~~~~~~~~~~~~~~~~
@@ -151,6 +175,8 @@ Bytecode Compiler
~~~~~~~~~~~~~~~~
- Added ``@since`` annotation to ``System.Info.fullCompilerVersion`` (:ghc-ticket:`26973`)
+- Don't drop ``ExceptionContext`` in ``SomeException(toException)`` (:ghc-ticket:`27455`)
+- Fix ``retry`` and async exception delivery inside a ``catchSTM`` handler (:ghc-ticket:`27657`)
``ghc-heap`` library
~~~~~~~~~~~~~~~~~~~~
=====================================
libraries/base/changelog.md
=====================================
@@ -8,6 +8,7 @@
* Hide implementation details of `throw` and `throwSTM` from exception stack traces ([CLC proposal #387](https://github.com/haskell/core-libraries-committee/issues/387), [#26808](https://gitlab.haskell.org/ghc/ghc/-/issues/26808))
* GHC internals re-exported from `GHC.Num` have been deprecated and will be removed after one major release ([CLC proposal #360](https://github.com/haskell/core-libraries-committee/issues/360))
* The implementation of `toException` in `SomeException`'s `Exception` instance no longer drops exception context, in keeping with the behavior originally proposed in [CLC Proposal #200](https://github.com/haskell/core-libraries-committee/issues/200).
+ * Fix `retry` and async exception delivery inside a `catchSTM` handler ([#27657](https://gitlab.haskell.org/ghc/ghc/-/issues/27657))
## 4.22.0.0 *December 2025*
* Shipped with GHC 9.14.1
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5345424072f8acd9c9f26fd25978f37…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5345424072f8acd9c9f26fd25978f37…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/10.0.1-backports] 63 commits: UniqueDFM: alter should preserve insertion order
by Zubin (@wz1000) 15 Sep '26
by Zubin (@wz1000) 15 Sep '26
15 Sep '26
Zubin pushed to branch wip/10.0.1-backports at Glasgow Haskell Compiler / GHC
Commits:
8b72edc9 by Zubin Duggal at 2026-09-08T10:21:56+05:30
UniqueDFM: alter should preserve insertion order
Before it always inserting new elements at the end.
This is problematic because instances get inserted into the map with
`alterF`, which can change ordering of how instances are printed
with `:info` depending on the order in which we consult interfaces
I expect `alter id k = id` and `alter (fmap f) k = adjust f k`. Moving keys to
the end breaks that (`adjust` already preserves position).
Fixes #27532
(cherry picked from commit f6f2343fbbfdfd8aaed9babf5983e3e24c08ca85)
- - - - -
062e5785 by Duncan Coutts at 2026-09-08T10:21:56+05:30
Add missing updateRemembSetPushClosure in poll I/O manager
For the non-moving GC.
(cherry picked from commit daf2bd6f71b7ee309374dddf0d4793bbc0ed066d)
- - - - -
cc1eb8e3 by Duncan Coutts at 2026-09-08T10:21:56+05:30
Eliminate STM_AWOKEN
It was used as nullary closure for the block_info.closure in the case of
a thread being awoken after an STM transaction.
However, while it was written, it was never read, so contributed nothing
to the behaviour. Furthermore, in the only place it was set (in
tryWakeupThread) the why_blocked was immediately overwritten by the
NotBlocked status, and the block_info was updated accordingly (by
appendToRunQueue).
So it didn't even serve a purpose of clarifying an intermediate state,
there really was no such intermediate state.
Cleaning this up will allow the BlockedOnSTM case to follow the same
pattern as the other why_blocked cases that do not use the block_info,
and in turn this reduces the number of different categories.
(cherry picked from commit 4d798b17c9b83f280c102ca7f96047bc0ad52df1)
- - - - -
c34ae859 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Document that eventlog thread stop code ThreadBlocked is no longer used
It has not been used since GHC 7.0.x (2011). In 7.2 all the BlockedOn*
codes were added, and these were and are used instead of ThreadBlocked.
(cherry picked from commit e1cece79a6c8e53796188acd543a8b565b18a3fb)
- - - - -
cf74b881 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Add a proper mapping to eventlog external thread stop status
That is the mapping from rts-internal codes, to the coes used in the
status field in the eventlog EVENT_STOP_THREAD event.
See issue #9003 for what goes wrong when we mess this up. In that
ticket, people note that we should really not require the internal
tso->why_blocked codes to leak into the external eventlog thread stop
codes. The same principle applies to the StgThreadReturnCode.
This change properly separates them, and explicitly maps between them
using a pair of (compact, constant) tables. These tables are pretty
small (with no alignment constraints) and will soon shrink so it seems
a sensible tradeoff.
We also introduce and use proper EVENT_STOP_THREAD constants in the
event log format header. Previously there was not specification in the
code for these (only in the docs): the values were encoded into the
conversion code.
This will allow us to renumber the internal why_blockd codes without
breaking the eventlog output.
(cherry picked from commit 795db1151237be5a3d0d2cdccb4c43309b587cdf)
- - - - -
90e5014e by Duncan Coutts at 2026-09-08T10:21:57+05:30
Remove unused tso->block_info.wakeup member
Presumably it was used once, but not now.
(cherry picked from commit 6f1c8efa1b4c78273daca99f9dda0a7e3d771330)
- - - - -
4ca77c35 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Document StgTSOBlockInfo to say what cases use what members
In principle, tso->why_blocked is the tag for the StgTSOBlockInfo union,
so we should be able to say for each union member the why_blocked cases
that use that member.
(cherry picked from commit 740b88a980c4aa7f28fcf3aa89f7df8aea2813a9)
- - - - -
593b66d8 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Add a tso->block_info.mvar member and use it
in preference to the generic block_info.closure union member, with
casts.
The plan is that when we know what case we're in (via tso->why_blocked)
then we can always access the correct union member, and so we will only
need to access block_info.closure for generic cases where we don't know
or don't care.
(cherry picked from commit 5b92eae2638db71ff8725295ec2a8ca254c0720b)
- - - - -
0d5049f0 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Add a tso->block_info.unused member and use it
in preference to the generic block_info.closure union member, with
casts.
The plan is that when we know what case we're in (via tso->why_blocked)
then we can always access the correct union member, and so we will only
need to access block_info.closure for generic cases where we don't know
or don't care.
(cherry picked from commit d931715fbea83ccd402d280965a5d096a9f72949)
- - - - -
887d90b4 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Avoid storing to tso->block_info.closure
In one case we can use a specific union member (.prev) instead. In
several cases the stores were in fact redundant because of subsequent
overwrites.
In scavengeTSO we replace setting tso->block_info.closure to a valid
closure, with an assertion that the block_info.unused is already set to
END_TSO_QUEUE which is a valid (static) closure.
(cherry picked from commit 47e28ebbb4e22ad2ddb27c3f4acc5df291276743)
- - - - -
584a8405 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Renumber the tso->why_blocked constants
We can do this now because we have separated the internal values from
the external ones used in the eventlog.
This lets us put them back into a deliberate order and consolodate some
gaps.
More importantly, it is a prepation for a slightly more sophisticated
encoding.
(cherry picked from commit 96e4749d9f9b75e99d7b860325b92a5b3704e784)
- - - - -
da0c4f60 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Define constants for the existing stg_threadStatuszh return codes
The stg_threadStatuszh reuses the internal tso->why_blocked codes but
also extends them with a couple previously magic values. This is awkward
since we need to know what those magic values are so we don't
accidentally use those values to mean something else. By pulling a
definition up to where the why_blocked codes are defined we will be able
to avoid mistakenly assining those codes some meaning (or just changing
the BlockedThreadComplete, BlockedThreadKilled code if necessary).
(cherry picked from commit 8f62661c133338100803347084de3566e325e64c)
- - - - -
ce670c7f by Duncan Coutts at 2026-09-08T10:21:57+05:30
Extend the tso->why_blocked encoding to indicate block_info closures
We use some bit tricks to cheaply and generically test if a
tso->why_blocked tag implies that the corresponding tso->block_info will
contain a non-trivial valid closure (i.e. not just block_info.unused set
to END_TSO_QUEUE).
In particular we arrange for most why_blocked values to naturally have a
distinguishing bit, but for the BlockedOn{Read,Write,Delay} cases, they
can come in either non-closure or closure forms. We allow an additional
bit to distinguish these cases. The non-closure forms are only from
legacy I/O managers: select and win32-legacy. So this extra bit
mechanism will be able to be retired once the legacy I/O managers are
themselves retired.
This means in a few places we need to untag the why_blocked value before
inspecting it, but in most places we do not.
(cherry picked from commit 42c69ae2d58310c703abaa4ec933973fa9b136d3)
- - - - -
91bd23fd by Duncan Coutts at 2026-09-08T10:21:57+05:30
Use BlockInfoForceNonClosure in the select I/O manager
(cherry picked from commit 7c64632b46ac660fc0779ae96d9a05d11537b743)
- - - - -
e4d6fad6 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Use BlockInfoForceNonClosure in the win32-legacy I/O manager
for the BlockedOn{Read,Write} since these use the non-heap allocated
StgAsyncIOResult.
(cherry picked from commit 8fd7104a0d63208f8408a7e5cd185bd2020225c8)
- - - - -
0a19e878 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Enforce the why_blocked and block_info rules in checkTSO
We now check the cases wher IsBlockInfoClosure should hold, the cases
that are supposed to use block_info.unused == END_TSO_QUEUE, and which
cases are allowed to use BlockInfoForceNonClosure.
This partially enforces the use of why_blocked as a tag for the
block_info union. We could be stricter and check for the correct
expected info table for the closure cases.
(cherry picked from commit e0da603b8e24cfc633f29990be9ca7008f45b3c2)
- - - - -
f0365edc by Duncan Coutts at 2026-09-08T10:21:57+05:30
Use IsBlockInfoClosure to simplify several tests
In GC and generic traversal we need to know if we should look at the
block_info.closure or not. Now we can do just that using a cheap bit
test on the why_blocked tag.
This fixes issue 26717, where the problem was that some GC modes did not
know when to look at block_info.closure, because the poll I/O manager
uses a closure for BlockedOn{Read,Write} while the select I/O manager
uses a non-closure. Now this information is in the why_blocked tag
itself.
(cherry picked from commit 1dd0f381ab96d3f46e113c90858870e95bd3caba)
- - - - -
b3fcb405 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Remove the now-unused scavengeTSOIOManager
The GC no longer has to delegate to the I/O manager, since it can use
IsBlockInfoClosure to decide things itself.
(cherry picked from commit 7a00ffbc311e6ee53e8b1b9181e37c3795a7b884)
- - - - -
12dd977e by Duncan Coutts at 2026-09-08T10:21:57+05:30
Remove duplicate assertion
(cherry picked from commit 522a481f5f1e51a8bdd0902012bdc467535a0382)
- - - - -
73340ce0 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Follow atomic access rules more consistently for tso->why_blocked
The rule is this:
store block_info *before* why_blocked
store why_blocked using store release
load why_blocked using load acquire
load block_info *after* why_blocked
This is a an atomic store release / load acquire pair and (if the reads
are in a separate thread to the writes, and the read receives the value
stored) then this guarantees a full "happens before" relationship of
these stores and loads.
In some cases, we do not need a full load acquire, because we don't read
the block_info at all and so do not need any ordering. In this case we
just need an atomic relaxed load.
This was being followed in most places, but not all. If there's good
reason in any case that we don't need atomic access, then we should
document that in a comment. In the absence of that I think it's easier
to follow the rule everywhere.
(cherry picked from commit 0874d965ef1fec847561418857e63c067b91b0b7)
- - - - -
3d6a4321 by Duncan Coutts at 2026-09-08T10:21:57+05:30
Add a changelog entry
(cherry picked from commit 8f0bdbe138a2e1914cba7963b6931402f99c8710)
- - - - -
8e2dec3f by Cheng Shao at 2026-09-08T10:21:57+05:30
configure: bump LlvmMaxVersion to 23
This patch bumps `LlvmMaxVersion` to 23 to support LLVM 22.x releases.
(cherry picked from commit cc9cc6d5df7fb3845b1409fe708e1097896252a7)
- - - - -
b10f2f3d by Cheng Shao at 2026-09-08T10:21:57+05:30
changelog: add llvm 22.x support
(cherry picked from commit 2ea7ef8ef090fa44a0191271f644a0917908ef40)
- - - - -
41ba785d by fendor at 2026-09-08T10:21:57+05:30
Drop `preloadClosure` from `UnitState`
It is always hard-coded to the same value.
Backpack Unit instantiation isn't using it any more.
Allows us to simplify the API and get rid of `improveUnit`.
(cherry picked from commit fb5246adb7e10bd9ef07de314eaf98fbcfb729a1)
- - - - -
6508c435 by fendor at 2026-09-08T10:21:57+05:30
Introduce global unit database cache
As a first step for better sharing of `UnitInfo` across `UnitEnv`,
we introduce a new datatype called `ExternalUnitDatabases`.
It primarily serves as an in-memory representation of *all*
`UnitDatabase`s across `UnitEnv`. This means, if multiple `HomeUnitEnv`s
depend on the same database, one way or another, we make sure that we
don't parse from disk every time.
Instead, we store the in-memory representation in `ExternalUnitDatabases`.
`ExternalUnitDatabaseCache` is the equivalent of `ExternalUnitState` in
the `UnitEnv`. It is a mutable variable wrapping `ExternalUnitDatabases`.
The mutable `ExternalUnitDatabaseCache` is used in `initUnits` to make
sure we don't parse the same unit database multiple times.
Almost by accident, we change the semantics of `initUnits` to honour
modifications to `packageDBFlags`.
The inability to change `packageDBFlags` while also reusing the already
parsed `UnitDatabase`s was reported in #26423 as a bug.
Hence, we think this behaviour change is warranted and acceptable,
especially since it comes with a breaking change to the `initUnits` API.
Add regression test for #26423
Closes #26423
(cherry picked from commit 5d0ab71ac1d01c2ef19bf3146adb7dac8733dca5)
- - - - -
8efc8f46 by fendor at 2026-09-08T10:21:57+05:30
Introduce UnitIndex for global external unit caching
`UnitInfo`s have been observed to cause a lot of memory usage in #27500.
Especially with multiple home units, as the same (external) units are
processed from scratch, even though most of the time we end up with
exactly the same `UnitInfo`.
We introduce a `UnitEnv` global cache that allows us to store external
unit information that is used across all `HomeUnitEnv`s.
The most important change in this commit is the introduction of the `UnitIndex`.
It stores a global mapping of `UnitId` -> `UnitInfo`, and `initUnits`
always uses the cached `UnitInfo` entry to populate each
`HomeUnitEnv`'s `UnitState`.
This allows us to ensure the following property:
> Each `UnitInfo` should be alive exactly once in GHC.
All `UnitState`s should reference 'UnitInfo's stored in the 'UnitIndex'.
This ensured by calling 'initUnits' with the 'UnitIndex'.
In addition, the `ExternalUnitDatabases` may also hold a reference
to each on-disk representation of `UnitInfo`.
This means, we impose an hard upper bound on the number of `UnitInfo`s
alive in the GHC session:
> The number of alive `UnitInfo`s closure objects must be the
> sum of all loaded unit database times two.
We add performance regression tests that make sure the number of live
`UnitInfo` cannot exceed this threshold.
Closes #27500
-------------------------
Metric Decrease:
MultiComponentModules
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
mhu-perf
LinkableUsage02
-------------------------
These metrics increases are especially notable, as we are not even
sharing anything big but merely the global package database with 50
entries.
It shows how careful sharing of `UnitInfo` can improve memory usage.
We expect this to be much more notable when the whole cabal package
database is shared across multiple home units.
`LinkableUsage02` metric decreases on unreg and i386 platform, only.
---
Technical details
To share the `UnitInfo`s correctly, it is important that we extract
the `WireMap` into the `UnitIndex`. At the moment of writing, `WireMap`
must be globally the same for all `HomeUnitEnv`s.
This is important, as we could otherwise not cache the "fully-resolved"
`UnitInfo`, as we don't change the `UnitId` or `unitAbiHash` when
resolving wired-in units. Thus, there could be ambiguities, when the
`WireMap` is not the same for all `UnitState`s across the `UnitEnv`.
We consider a `UnitInfo` fully-resolved, if wired-in units have been
updated, the `UnitInfo` has been validated and variables in the unit
config, such as `${pkgroot}` have been resolved.
Updating the wired-in units requires the `WireMap` to be globally the
same.
(cherry picked from commit 6cce494a7ec43953c7a949e0d8ce712abfe73da7)
- - - - -
8e5b8026 by Ben Gamari at 2026-09-08T10:21:57+05:30
base: Don't drop exception context in SomeException(toException)
For reasons that are lost to time, the implementation of [CLC #200]
that was merged inappropriately dropped `ExceptionContext` in the
`toException` implementation given to `SomeException`.
Fix this infelicity.
[CLC #200]: https://github.com/haskell/core-libraries-committee/issues/200
(cherry picked from commit 2ab02c579a9625438f5281a258051cb32ba40004)
- - - - -
fe124985 by Vladislav Zavialov at 2026-09-08T10:21:57+05:30
Discard type arguments in tcPatToExpr (#27440, #27583)
The builder expression of an implicitly bidirectional pattern synonym must not
mention types written in the RHS:
* Invisible type arguments led to a panic (#27440)
* Required type arguments failed with out-of-scope variables (#27583)
Both are now discarded, following the precedent established by pattern
signatures (#9867).
Discarding type arguments takes some care: a type pattern cannot be told from a
value pattern by syntax alone, as the `type` keyword may be omitted. Consider:
data T a b c where
MkT :: forall a. forall b c -> a -> T a b c
pattern P :: x -> T x y z
pattern P x = MkT @a (type b) c x
In P's right-hand side, `@a` and `type b` are clearly type arguments, but what
about `c` and `x`? We can only tell by matching the patterns against MkT's
type. So tcPatToExpr now runs in TcM and matches the arguments against the
constructor's TyVarBinders using zipPatsBndrs, which is made public for this
purpose. The resulting builder is $bP x = MkT _ _ x.
See Note [Discarding types in the builder expression].
Test cases: T27440a T27440b T27440c T27440d T27440e
T27583a T27583b T27583c T27583d T27583e T27583f T27583g
Metric Increase: LinkableUsage02
Metric Decrease: T27336
Assisted-by: Claude Opus 5
(cherry picked from commit 4f98510802423dcd98fa62af77997189ee97a111)
- - - - -
9c15a8f2 by sheaf at 2026-09-08T10:21:57+05:30
mkWpFun_FRR: fix ordering of coercion composition
When the subsumption machinery generates an eta-expansion, we must
perform a representation polymorphism check to ensure the lambda binder
it introduces has a fixed runtime representation.
This is done in GHC.Tc.Utils.mkWpFun_FRR.
This check involves composing quite a few coercions, arising from
representation-polymorphism checks on both the actual and expected
argument types. These coercions are then chained using HsWrapper
composition, <.>. The ordering of composition was incorrect, leading to
the Core Lint failure reported in #27639. This commit fixes that.
Fixes #27639
(cherry picked from commit eb1dcd4d98548b7bc64c323dc352ddbf149a91ec)
- - - - -
58dab25f by Bernhard M. Wiedemann at 2026-09-08T10:21:57+05:30
driver: Link object files in a deterministic order
The object files handed to the linker come from the HomePackageTable,
which is ordered by the order in which modules finished compiling. With
-j1 that is the build plan order, with -jN it is whatever the scheduler
produced, so the same sources can link to different (but equivalent)
binaries.
The order reaches the output: .text and .rodata contributions are
concatenated in link order, so e.g. building the hdav executable of the
DAV package twice, once with -j1 and once with -j4, yields two binaries
that differ in ~100kB of section contents.
Sort the home modules by module before collecting their linkables,
guarded under `Opt_ObjectDeterminism` .
Fixes #27612
Signed-off-by: Bernhard M. Wiedemann <bwiedemann(a)suse.de>
(cherry picked from commit e8d1a0d68067ba344fdff816f6b84f0117ffdc59)
- - - - -
4ea95421 by Zubin Duggal at 2026-09-08T10:21:57+05:30
hadrian: Fix links to remaining doc sites to not use the package hash for haddock links
In 07267f79d91169f474cacc8bcd38d76a6e97887d we changed hadrian to not include the package hash in the haddock
directory. This patch takes care of a few remaining links that were missed in that patch
Fixes #27671
(cherry picked from commit 1446bb039a635f2b836be19f062cbffa568fe4c5)
- - - - -
d60805ba by Vladislav Zavialov at 2026-09-08T10:21:57+05:30
Fix tcLookupId panic with RequiredTypeArguments and PatternSynonyms (#27586)
The arguments declared on the left-hand side of a pattern synonym are looked up
as term variables bound by its right-hand side. Prior to this patch, that lookup
panicked with RequiredTypeArguments:
data T a where
MkT :: forall a -> T a
pattern P :: Int -> T Int
pattern P x = MkT x
On the RHS, `x` looks like a term argument, so the renamer binds it in the term
namespace. Only during type checking does it turn out to be a type variable, so
the lookup on the LHS finds an ATyVar rather than an ATcId. As the lookup was
done with tcLookupId, it resulted in a panic.
Now the arguments are looked up with tcLookupPatSynArg, which reports an illegal
term-level use of `x`, just as an ordinary function definition `f (MkT x) = x`
does.
Test cases: T27586a T27586b T27586c
Assisted-by: Claude Opus 5
(cherry picked from commit b757727a78613e7437a713058c24b94e10697f47)
- - - - -
76771258 by Zubin Duggal at 2026-09-08T10:21:57+05:30
DmdAnal: Fix maxDmdType
We need to eta expand the smaller DmdType using defaultArgDmd, like in lubDmdType.
Introduce zipDmdType as a common combinator to implement both maxDmdType and lubDmdType
uniformly.
fixes #27626
(cherry picked from commit e31885816b7c597ad89b05da64b21c5a241bf674)
- - - - -
e7dd0389 by Andreas Klebinger at 2026-09-08T10:21:57+05:30
cmm dumps: Add machop width info with -dppr-debug for infix ops.
(cherry picked from commit e9bbe8f924ec0b9d0772cf3d4f20aa6a25f28345)
- - - - -
7fd433bd by Andreas Klebinger at 2026-09-08T10:21:57+05:30
CmmLint: Check for unsupported MachOp widths
machOpArgReps now maps MachOp + Width to a list of supported
argument widths or Nothing if the given operation is not supported
at the given width.
This allows us to check for nonsensical combinations like FloatToInt
at Word16.
Similarly we now check that every address is actually wordwidth.
(cherry picked from commit 86e3a9d8d0a85b5c80dad212cf3ec8fbf1ba72e6)
- - - - -
19fa2b3a by Andreas Klebinger at 2026-09-08T10:21:57+05:30
arm64 ncg: The big subword truncation fix.
A set of slightly related fixes to arm subword handling:
Bitmask immediates:
Don't produce overflowing assembly literals.
There is still another bug here that causes us to miss some valid
literals but we will fix that later.
Improve subword truncation handling:
We now use a small set of helpers to truncate `Register` values rather
than truncating immediate `Reg` values which greatly simplifies the code
structure. This fixes a great many bugs to do with sign/zero extending subwords
or the lack thereof.
We now establish the invariant that subword values are zero-extended at
every site at which they come into "scope" of the ncg, and rely on the
invariant throughout rather than pessimistically inserting redundant
extensions in a hodgepodge manner at the use sites of these values.
This fixes at least the bugs described in issues #27533, #27430
#27537, #27538, #27539, and #27550. But likely more bugs yet not
found.
Subword ffi results:
Apply truncations when calling functions returning
subword values.
genCondJump:
Don't sign extend signed values in the input register as
it might map to a local variable, corrupting the value stored within.
Fix subword store/load instructions.:
We used to read those at 32bit width even for smaller values possibly
resulting in invalid memory access. Now we construct the suffix for
subword variants based on the instruction format for these.
(cherry picked from commit 13781cca5c24c2671d651fd2b13a561c7386fe3a)
- - - - -
7c8e5f86 by Andreas Klebinger at 2026-09-08T10:21:57+05:30
arm64 ncg: Fix MO_V_Broadcast for non-literals.
We now use OpReg instead of OpScalarAsVec as required since we broadcast a gp register.
Also adds a test. Fixes #27565.
(cherry picked from commit d8fa5d7cc060aa7d3bee8a68b922c85b626cbe8c)
- - - - -
9e035482 by Andreas Klebinger at 2026-09-08T10:21:57+05:30
Add some test cases covering bugs in the arm ncg.
* Test for #27430 (subword ffi results)
* #27537 - subword conversions
* #27538 - subwords used in conditional
* #27533 - single byte read
(cherry picked from commit 94822c951c2a6f77c7766720e0d4ff7d4afb7290)
- - - - -
81ed35d6 by Andreas Klebinger at 2026-09-08T10:21:57+05:30
cmmLint: Lint against MO_FS_Truncate subword use.
(cherry picked from commit dd1ba88a70f47bead722e9dae8e91f9a617258aa)
- - - - -
014df595 by Rodrigo Mesquita at 2026-09-08T10:21:58+05:30
rts: refactor to reduce THREADED_RTS in MSG_UPD_TSO_FLAGS
- No behavior change in this commit (well, a small optimization here
makes us do less work if the target TSO owned by the curr. capability)
- Move all THREADED_RTS CPP needed into `updThreadFlag`
- Merge MSG_SET_TSO_FLAGS and MSG_UNSET_TSO_FLAGS into MSG_UPD_TSO_FLAGS
plus a `set` bool field in the MessageUpdTSOFlag struct
Towards #27729
(cherry picked from commit bb3241717c8ee46e31fbdb3cfaed9736ba7257ea)
- - - - -
7c614470 by Rodrigo Mesquita at 2026-09-08T10:21:58+05:30
rts: Fix race condition in MSG_UPD_TSO_FLAGS execution
The code for processing the MSG_UPD_TSO_FLAGS message was not taking
into consideration that the TSO's owner might have moved in between that
capability receiving the message (since it was its previous owner) and
starting to process its inbox (a point at which it was no longer the
owner)
Added Note [TSO owner may change in between Msg being sent and received]
to explain this race and the pattern used to fix this, where we just
forward the message to the new owner.
Fixes #27729
(cherry picked from commit ed99b7b7bed699f3f2047672be7709c6d22b6df7)
- - - - -
5c2cc4ef by fendor at 2026-09-08T10:21:58+05:30
GHCi: Fix order of `PackageDBFlag`s for interactive home unit
`PackageDBFlag`s are stored in reverse order of cli specification.
When sorting the `PackageDBFlag`s by longest common prefix, we need thus
to reverse the package db stacks before calculating the prefix.
We make sure to reverse the package db stack for the interactive home
unit to uphold that later specified package dbs overwrite earlier ones.
Resolved and adds regression test for #27640
(cherry picked from commit 06fde293f2e8c80db11f4d01fcdfc482c1128db5)
- - - - -
d6f073c3 by fendor at 2026-09-08T10:21:58+05:30
Reuse the UnitIndexCache after initialising multiple home units
(cherry picked from commit 024c4d04a98f7e27b3dcb93f9b038f9b6b5a1ad9)
- - - - -
5170d064 by Andreas Klebinger at 2026-09-08T10:21:58+05:30
Specialise: Stop looping on recursive dictionaries in interestingDict
interestingDict now doesn't look through loopbreaker unfoldings.
Doing so would cause infinite loops on certain dictionaries.
Fixes #27705.
(cherry picked from commit 578bd18509f0d2aeb004231a197f7f3898f86a2a)
- - - - -
1cf16777 by Simon Peyton Jones at 2026-09-08T10:21:58+05:30
Never make an absent filler for a constraint type
mkAbsentFiller used isTerminatingType to decide, but that is not enough.
Consider
class Eq a => UC a where {}
let u :: UC Int -- UC Int is a "non-terminating type"
u = error "Absent"
let e :: Eq Int -- Eq Int is a "terminating type"
e = $p1UC u
We clearly must not make a filler for `e`, because we speculatively
evaluate it. But speculatively evaluating `e` forces `u`, so we must not
make one for `u` either.
Asking isDictTy instead is not enough either, because it does not catch a
constraint hidden behind an unreduced type family application:
type family F a :: Constraint
type instance F W = TC W
a :: F W => Int -> Int -- (F W) argument is absent
Oops! Entered absent arg Arg: irred
Type: F W
So play safe and use isPredTy: never make an absent filler for any
constraint-kinded type.
Fixes #27627
(cherry picked from commit 7bf546fc423e23cb649580016ee494efbfe144ab)
- - - - -
09bd3e50 by Zubin Duggal at 2026-09-08T10:21:58+05:30
Add tests for absent fillers at dictionary types
T27627 a unary class whose superclass is a non-unary class
T27627a ...whose superclass is a Constraint-kinded type family
T27627b ...whose superclass is a quantified constraint
T27627c a unary class applied to itself, (UC (UC (TC a)))
T27627e a (forall b. P b) dictionary that loops
(cherry picked from commit 5f474953d1880232b5e6c5741f08746e28cd25ab)
- - - - -
18f47fdb by Zubin Duggal at 2026-09-08T10:21:58+05:30
An abstract TyCon may hide a unary class
A class declared in an hs-boot file is an AbstractTyCon inside the
module loop, and compiling the real declaration may reveal it to be a
UnaryClassTyCon.
- isTerminatingType returned True for such AbstractTyCons
- IfaceToCore set the unary flag to False in the DFunId
So we could end up speculating bottom dictionaries because inside a module
loop we see an UnaryClassTyCon as an AbstractTyCon
Use isTerminatingTyCon, which returns False for an abstract TyCon.
The Bool in DFunId is now a cache for isTerminatingTyCon, set in
mkDFunIdDetails.
Fixes #27704
(cherry picked from commit cd5c6bcc0a59c7b4dc4627fdc7471dc7938d07c2)
- - - - -
01f1c9b9 by Zubin Duggal at 2026-09-08T10:21:58+05:30
Specialise: don't replace dead args with absent fillers
specHeader decides an argument is dead by calling isDeadBinder on a binder of
the /optimised RHS/, then applies the filler to the /stable unfolding/
template instead. The two may differ, so the argument can be dead in
the RHS and not in the template.
The specialised function's unfolding then has an absent filler, and any call
site that inlines it evaluates the error thunk.
Dropping dead args in the specialiser is rarely worth it, to quote Simon,
"The later worker/wrapper pass will pick up the dead arg later if it is really dead. Keeps the specialiser simpler."
So instead of trying to check if the arg really is dead in the stable unfolding,
just drop the logic for dropping dead args in the specialiser altogeher.
Fixes #27703
(cherry picked from commit abfc224a27cf499390efc5fe1348301fefebb910)
- - - - -
1b8c6bc7 by Zubin Duggal at 2026-09-08T10:21:58+05:30
CorePrep: don't speculate a call across an hs-boot edge
We take care not to evaluate things that might be bottom, like a
looping dictionary group, but our analysis is defeated by boot files.
We only track recursion within a module, so two dictionaries that
depend on each other across a module loop each look non-recursive, and
we might speculate them.
Any recursion we cannot see must cross an hs-boot edge, so refuse to
speculate calls that cross one.
Fixes #27717
(cherry picked from commit 1557fd1cfb802d2608cb5b138eab664564f57fb7)
- - - - -
c198530b by Cheng Shao at 2026-09-08T10:21:58+05:30
autoconf/ghc-toolchain: bump llvm upper bound to support llvm 23
This commit bumps llvm upper bound to support llvm 23.
(cherry picked from commit 56291fc550ec00784e46ec0c89ee65081090ae9f)
- - - - -
694978cc by Cheng Shao at 2026-09-08T10:21:58+05:30
rts: fix compilation issues with clang 23
clang 23 has broadened `-Wall`/`-Wextra` ranges, exposing some minor
issues in the rts when building with validate flavours:
- Unused locals
- `#pragma GCC diagnostic pop` mismatch
This commit fixes those.
(cherry picked from commit 20eb3f415f9e04a003322d1a49d95e0aaf1029f2)
- - - - -
bf050782 by Zubin Duggal at 2026-09-08T10:21:58+05:30
Bump directory submodule to 1.3.11.0
- - - - -
7f5ed2ff by Zubin Duggal at 2026-09-08T10:21:58+05:30
Bump os-string submodule to 2.0.11
- - - - -
224a2e39 by Zubin Duggal at 2026-09-08T10:21:58+05:30
Bump filepath submodule to 1.5.5.0
- - - - -
c9bd45bc by Zubin Duggal at 2026-09-08T10:21:58+05:30
Bump haskeline submodule to 0.8.5.0
- - - - -
42dcc16d by Zubin Duggal at 2026-09-08T10:21:58+05:30
Bump xhtml submodule to 3000.4.1.0
- - - - -
a882c355 by Zubin Duggal at 2026-09-08T10:21:58+05:30
Bump Win32 submodule to 2.14.2.2
- - - - -
92154e36 by Zubin Duggal at 2026-09-08T10:21:58+05:30
Bump time submodule to 1.16.0.1
- - - - -
dd70ed87 by Simon Peyton Jones at 2026-09-15T11:17:15+05:30
Move HsStatic free-var test to typechecker
A `static` form should have no free *term* variables, but it
can have free *type* variables. Alas, the renamer does not really know what
is a term variable and what is a type variable, because of required type
arguments. This patch moves the test to the typechecker, which does know.
Addresses #27664
(cherry picked from commit c673ecf057deee858acbbaa7e6c92078a818d6f2)
- - - - -
04e6be98 by sheaf at 2026-09-15T11:18:49+05:30
Preserve tick ordering in 'tickTickedExpr'
'GHC.Core.Utils.tickTickedExpr' tries to combine a tick 't1' into an
existing stack of ticks 't2s'. There are two situations:
1. 't1' is subsumed by a tick in 't2s': drop it.
2. A tick in 't2s' is subsumed by 't1', say 't2'.
This commit ensures that in case (2) we keep 't1' on the outside instead
of replacing 't2' at its position in the stack. This avoids re-ordering
source notes (which was the cause of #27749).
This fixes a regression introduced in 2dadf3b0d05.
Fixes #27749
(cherry picked from commit e28313e31a5acfa5c5b622ef0d02acc8f3d68934)
- - - - -
174d7448 by sheaf at 2026-09-15T11:20:08+05:30
Consistently prefer local source note ticks
GHC.Cmm.DebugBlock.cmmDebugGen (DWARF annotations) and
GHC.Stg.Debug.quickSourcePos (-finfo-table-map) both contained logic to
prioritise source note ticks from the current module.
This commit commons up this logic and propagates it to a third consumer:
IPE stack frames, in GHC.Driver.GenerateCgIPEStub.
See the new function GHC.Types.Tickish.bestSourceNote.
(cherry picked from commit 3172f557f9bbd5aa01b7ca6368f8abd670a58066)
- - - - -
51fd0497 by Luite Stegeman at 2026-09-15T11:50:06+05:30
rts: fix ctoi_tuple_spill_words getting out of sync
Fix a few places that were not updating ctoi_tuple_spill_words
correctly, leading to corruption/crashes when dealing with large
unboxed tuples in bytecode:
- captureContinuationAndAbort
- findRetryFrameHelper/findAtomicallyFrameHelper
- interpretBCO bci_BRK_FUN
fixes #27633
(cherry picked from commit 192be0b6b861725613a9be5cb1587fb8cdf68bd3)
- - - - -
d4cfcd13 by Luite Stegeman at 2026-09-15T11:50:15+05:30
rts: Fix missing memory barrier in eval_thunk_selector (#27477)
unchain_thunk_selectors() was missing an ACQUIRE_LOAD for the
indirectee, leading to segfaults and corruption during GC on
weakly-ordered architectures.
Fixes #27477
(cherry picked from commit 06eee015be4e361fe9cb33e8a608ab2ea1386b52)
- - - - -
322 changed files:
- + changelog.d/27532
- + changelog.d/27626
- + changelog.d/27627
- + changelog.d/27703
- + changelog.d/27704
- + changelog.d/27717
- + changelog.d/T26423
- + changelog.d/T26716
- changelog.d/T27202
- + changelog.d/T27308
- + changelog.d/T27440
- + changelog.d/T27455
- + changelog.d/T27583
- + changelog.d/T27586
- + changelog.d/T27639
- + changelog.d/T27705
- + changelog.d/T27749
- + changelog.d/T27764
- + changelog.d/arm_ncg_fixes_T27430
- + changelog.d/fix-parallel-gc-selector-race-27477
- + changelog.d/link-deterministic-order
- + changelog.d/llvm-22
- + changelog.d/llvm-23
- + changelog.d/unit-index
- compiler/GHC.hs
- compiler/GHC/Cmm/DebugBlock.hs
- compiler/GHC/Cmm/Expr.hs
- compiler/GHC/Cmm/Lint.hs
- compiler/GHC/Cmm/MachOp.hs
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- compiler/GHC/CmmToAsm/AArch64/Instr.hs
- compiler/GHC/CmmToAsm/AArch64/Ppr.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/GenerateCgIPEStub.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Stg/Debug.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/Literal.hs
- compiler/GHC/Types/Tickish.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Unique/DFM.hs
- compiler/GHC/Unit.hs
- compiler/GHC/Unit/Env.hs
- + compiler/GHC/Unit/External/Database.hs
- + compiler/GHC/Unit/External/Index.hs
- + compiler/GHC/Unit/External/ModuleOrigin.hs
- + compiler/GHC/Unit/External/Providers.hs
- + compiler/GHC/Unit/External/Query.hs
- + compiler/GHC/Unit/External/Substitution.hs
- + compiler/GHC/Unit/External/Validate.hs
- + compiler/GHC/Unit/External/Visibility.hs
- + compiler/GHC/Unit/External/Wired.hs
- compiler/GHC/Unit/Home/Graph.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/State.hs-boot
- compiler/GHC/Unit/Types.hs
- compiler/ghc.cabal.in
- configure.ac
- docs/index.html.in
- docs/users_guide/eventlog-formats.rst
- docs/users_guide/ghc_config.py.in
- ghc/GHCi/UI.hs
- ghc/ghc-bin.cabal.in
- hadrian/src/Rules/Generate.hs
- libraries/Win32
- libraries/base/changelog.md
- libraries/directory
- libraries/filepath
- libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc
- libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc
- libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs
- libraries/haskeline
- libraries/hpc
- libraries/os-string
- libraries/time
- libraries/unix
- libraries/xhtml
- rts/CloneStack.c
- rts/Continuation.c
- rts/IOManager.c
- rts/IOManager.h
- rts/Interpreter.c
- rts/Messages.c
- rts/PrimOps.cmm
- rts/ProfHeap.c
- rts/RaiseAsync.c
- rts/RaiseAsync.h
- rts/STM.c
- rts/Schedule.c
- rts/StgMiscClosures.cmm
- rts/Threads.c
- rts/Threads.h
- rts/Trace.c
- rts/Trace.h
- rts/TraverseHeap.c
- rts/eventlog/EventLog.c
- rts/include/Cmm.h
- rts/include/rts/Constants.h
- rts/include/rts/EventLogFormat.h
- rts/include/rts/storage/Closures.h
- rts/include/rts/storage/TSO.h
- rts/include/stg/MiscClosures.h
- rts/posix/Poll.c
- rts/posix/Select.c
- rts/posix/Timeout.c
- rts/prim/atomic.c
- rts/sm/Compact.c
- rts/sm/Evac.c
- rts/sm/NonMovingMark.c
- rts/sm/Sanity.c
- rts/sm/Scav.c
- rts/win32/AsyncMIO.c
- + testsuite/tests/bytecode/T27633/Obj.hs
- + testsuite/tests/bytecode/T27633/T27633a.hs
- + testsuite/tests/bytecode/T27633/T27633a.stdout
- + testsuite/tests/bytecode/T27633/T27633b.hs
- + testsuite/tests/bytecode/T27633/T27633b.stdout
- + testsuite/tests/bytecode/T27633/all.T
- + testsuite/tests/codeGen/should_run/T27430.hs
- + testsuite/tests/codeGen/should_run/T27430.stdout
- + testsuite/tests/codeGen/should_run/T27430_c.c
- + testsuite/tests/codeGen/should_run/T27533.hs
- + testsuite/tests/codeGen/should_run/T27533.stdout
- + testsuite/tests/codeGen/should_run/T27533_cmm.cmm
- + testsuite/tests/codeGen/should_run/T27537.hs
- + testsuite/tests/codeGen/should_run/T27537.stdout
- + testsuite/tests/codeGen/should_run/T27538.hs
- + testsuite/tests/codeGen/should_run/T27538.stdout
- testsuite/tests/codeGen/should_run/all.T
- + testsuite/tests/core-to-stg/T27627/Callee.hs
- + testsuite/tests/core-to-stg/T27627/Caller.hs
- + testsuite/tests/core-to-stg/T27627/Main.hs
- + testsuite/tests/core-to-stg/T27627/T27627.stdout
- + testsuite/tests/core-to-stg/T27627/all.T
- + testsuite/tests/core-to-stg/T27627a/Callee.hs
- + testsuite/tests/core-to-stg/T27627a/Caller.hs
- + testsuite/tests/core-to-stg/T27627a/Main.hs
- + testsuite/tests/core-to-stg/T27627a/T27627a.stdout
- + testsuite/tests/core-to-stg/T27627a/all.T
- + testsuite/tests/core-to-stg/T27627b/Callee.hs
- + testsuite/tests/core-to-stg/T27627b/Caller.hs
- + testsuite/tests/core-to-stg/T27627b/Main.hs
- + testsuite/tests/core-to-stg/T27627b/T27627b.stdout
- + testsuite/tests/core-to-stg/T27627b/all.T
- + testsuite/tests/core-to-stg/T27627c/Callee.hs
- + testsuite/tests/core-to-stg/T27627c/Caller.hs
- + testsuite/tests/core-to-stg/T27627c/Main.hs
- + testsuite/tests/core-to-stg/T27627c/T27627c.stdout
- + testsuite/tests/core-to-stg/T27627c/all.T
- + testsuite/tests/core-to-stg/T27627e.hs
- + testsuite/tests/core-to-stg/T27627e.stdout
- + testsuite/tests/core-to-stg/T27627f/Callee.hs
- + testsuite/tests/core-to-stg/T27627f/Caller.hs
- + testsuite/tests/core-to-stg/T27627f/Inst.hs
- + testsuite/tests/core-to-stg/T27627f/Main.hs
- + testsuite/tests/core-to-stg/T27627f/T27627f.stdout
- + testsuite/tests/core-to-stg/T27627f/all.T
- + testsuite/tests/core-to-stg/T27704/Callee.hs
- + testsuite/tests/core-to-stg/T27704/Callee.hs-boot
- + testsuite/tests/core-to-stg/T27704/Main.hs
- + testsuite/tests/core-to-stg/T27704/Mid.hs
- + testsuite/tests/core-to-stg/T27704/T27704.stdout
- + testsuite/tests/core-to-stg/T27704/all.T
- + testsuite/tests/core-to-stg/T27704a/Callee.hs
- + testsuite/tests/core-to-stg/T27704a/Callee.hs-boot
- + testsuite/tests/core-to-stg/T27704a/Main.hs
- + testsuite/tests/core-to-stg/T27704a/Mid.hs
- + testsuite/tests/core-to-stg/T27704a/T27704a.stdout
- + testsuite/tests/core-to-stg/T27704a/all.T
- + testsuite/tests/core-to-stg/T27717/Callee.hs
- + testsuite/tests/core-to-stg/T27717/Callee.hs-boot
- + testsuite/tests/core-to-stg/T27717/Main.hs
- + testsuite/tests/core-to-stg/T27717/Mid.hs
- + testsuite/tests/core-to-stg/T27717/T27717.stdout
- + testsuite/tests/core-to-stg/T27717/Ty.hs
- + testsuite/tests/core-to-stg/T27717/all.T
- testsuite/tests/core-to-stg/all.T
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- + testsuite/tests/dmdanal/should_run/M2.hs
- + testsuite/tests/dmdanal/should_run/T27626.hs
- + testsuite/tests/dmdanal/should_run/T27626.stdout
- testsuite/tests/dmdanal/should_run/all.T
- + testsuite/tests/driver/T26423/Hello.hs
- + testsuite/tests/driver/T26423/Makefile
- + testsuite/tests/driver/T26423/T26423.hs
- + testsuite/tests/driver/T26423/T26423.stderr
- + testsuite/tests/driver/T26423/T26423.stdout
- + testsuite/tests/driver/T26423/all.T
- + testsuite/tests/driver/T26423/test/Test.hs
- + testsuite/tests/driver/T26423/test/test.pkg
- + testsuite/tests/driver/TUnitInfo/Foo.hs
- + testsuite/tests/driver/TUnitInfo/Makefile
- + testsuite/tests/driver/TUnitInfo/all.T
- + testsuite/tests/driver/TUnitInfo/genMhu.sh
- + testsuite/tests/driver/TUnitInfo/generic-unit-info-space-mhu.stdout
- + testsuite/tests/driver/TUnitInfo/generic-unit-info-space-single.stdout
- + testsuite/tests/driver/TUnitInfo/generic-unit-info-space.hs
- + testsuite/tests/driver/TUnitInfo/generic-unit-info-space.stdout
- testsuite/tests/ghc-e/should_fail/T18441fail7.stderr
- testsuite/tests/ghc-e/should_run/ghc-e005.stderr
- + testsuite/tests/ghci.debugger/scripts/T27633c.hs
- + testsuite/tests/ghci.debugger/scripts/T27633c.script
- + testsuite/tests/ghci.debugger/scripts/T27633c.stdout
- + testsuite/tests/ghci.debugger/scripts/T27633c_obj.hs
- testsuite/tests/ghci.debugger/scripts/all.T
- testsuite/tests/ghci/T16793/T16793.stdout
- testsuite/tests/ghci/T18060/T18060.stdout
- + testsuite/tests/ghci/T27532/Makefile
- + testsuite/tests/ghci/T27532/T27532.stdout
- + testsuite/tests/ghci/T27532/T27532j4.stdout
- + testsuite/tests/ghci/T27532/a.script
- + testsuite/tests/ghci/T27532/all.T
- + testsuite/tests/ghci/T27532/b.script
- + testsuite/tests/ghci/T27532/genT27532Modules
- + testsuite/tests/ghci/prog-mhu007/Makefile
- + testsuite/tests/ghci/prog-mhu007/a/A.hs
- + testsuite/tests/ghci/prog-mhu007/all.T
- + testsuite/tests/ghci/prog-mhu007/b/B.hs
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.script
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg
- + testsuite/tests/ghci/prog-mhu007/unitA
- + testsuite/tests/ghci/prog-mhu007/unitB
- testsuite/tests/ghci/scripts/ListTuplePunsPpr.stdout
- testsuite/tests/ghci/scripts/T4175.stdout
- testsuite/tests/ghci/scripts/T8469.stdout
- testsuite/tests/ghci/scripts/T8535.stdout
- testsuite/tests/ghci/scripts/T9881.stdout
- testsuite/tests/ghci/scripts/ghci020.stdout
- testsuite/tests/ghci/scripts/ghci064.stdout
- testsuite/tests/ghci/should_run/T10145.stdout
- testsuite/tests/ghci/should_run/T18594.stdout
- testsuite/tests/partial-sigs/should_compile/ExtraConstraints3.stderr
- + testsuite/tests/patsyn/should_compile/T27440a.hs
- + testsuite/tests/patsyn/should_compile/T27440b.hs
- + testsuite/tests/patsyn/should_compile/T27440c.hs
- testsuite/tests/patsyn/should_compile/all.T
- + testsuite/tests/patsyn/should_fail/T27440d.hs
- + testsuite/tests/patsyn/should_fail/T27440d.stderr
- testsuite/tests/patsyn/should_fail/all.T
- testsuite/tests/rename/should_fail/RnStaticPointersFail01.stderr
- testsuite/tests/rename/should_fail/RnStaticPointersFail03.stderr
- testsuite/tests/rename/should_fail/T26545.stderr
- + testsuite/tests/rep-poly/T27639.hs
- testsuite/tests/rep-poly/all.T
- testsuite/tests/roles/should_compile/Roles14.stderr
- testsuite/tests/roles/should_compile/Roles3.stderr
- testsuite/tests/roles/should_compile/Roles4.stderr
- testsuite/tests/roles/should_compile/T8958.stderr
- + testsuite/tests/rts/T27477.hs
- + testsuite/tests/rts/T27477.stdout
- testsuite/tests/rts/all.T
- + testsuite/tests/simd/should_run/T27565.hs
- + testsuite/tests/simd/should_run/T27565.stdout
- testsuite/tests/simd/should_run/all.T
- testsuite/tests/simplCore/should_compile/T17966.stderr
- + testsuite/tests/simplCore/should_compile/T27749.hs
- + testsuite/tests/simplCore/should_compile/T27749.stderr
- testsuite/tests/simplCore/should_compile/T7785.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/simplCore/should_compile/spec004.hs
- testsuite/tests/simplCore/should_compile/spec004.stderr
- + testsuite/tests/simplCore/should_run/T27703/Lib.hs
- + testsuite/tests/simplCore/should_run/T27703/Main.hs
- + testsuite/tests/simplCore/should_run/T27703/T27703.stdout
- + testsuite/tests/simplCore/should_run/T27703/all.T
- + testsuite/tests/simplCore/should_run/T27705.hs
- + testsuite/tests/simplCore/should_run/T27705.stdout
- + testsuite/tests/simplCore/should_run/T27705_Inst.hs
- testsuite/tests/simplCore/should_run/all.T
- testsuite/tests/typecheck/should_compile/T18406b.stderr
- testsuite/tests/typecheck/should_compile/T18529.stderr
- + testsuite/tests/typecheck/should_compile/T27664.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_fail/T5300.stderr
- + testsuite/tests/vdq-rta/should_compile/T27583a.hs
- + testsuite/tests/vdq-rta/should_compile/T27583b.hs
- + testsuite/tests/vdq-rta/should_compile/T27583c.hs
- + testsuite/tests/vdq-rta/should_compile/T27583d.hs
- + testsuite/tests/vdq-rta/should_compile/T27583e.hs
- + testsuite/tests/vdq-rta/should_compile/T27583g.hs
- testsuite/tests/vdq-rta/should_compile/all.T
- + testsuite/tests/vdq-rta/should_fail/T27440e.hs
- + testsuite/tests/vdq-rta/should_fail/T27440e.stderr
- + testsuite/tests/vdq-rta/should_fail/T27583f.hs
- + testsuite/tests/vdq-rta/should_fail/T27583f.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586a.hs
- + testsuite/tests/vdq-rta/should_fail/T27586a.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586b.hs
- + testsuite/tests/vdq-rta/should_fail/T27586b.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586c.hs
- + testsuite/tests/vdq-rta/should_fail/T27586c.stderr
- testsuite/tests/vdq-rta/should_fail/all.T
- utils/haddock/haddock-api/src/Haddock.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2c3add313325058ccfa841c334d2fc…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2c3add313325058ccfa841c334d2fc…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0