[Git][ghc/ghc][wip/io-manager-deadlock-detection] Add idle GC mode for !HAVE_PREEMPTION
by Duncan Coutts (@dcoutts) 04 Sep '26
by Duncan Coutts (@dcoutts) 04 Sep '26
04 Sep '26
Duncan Coutts pushed to branch wip/io-manager-deadlock-detection at Glasgow Haskell Compiler / GHC
Commits:
e3f31b36 by Duncan Coutts at 2026-09-04T10:51:13+01:00
Add idle GC mode for !HAVE_PREEMPTION
We have to do idle GC (and thus deadlock detection) differently when we
do not have the ticker and the ability to interrupt the I/O manager
when it's blocking.
- - - - -
6 changed files:
- rts/IdleGC.c
- rts/IdleGC.h
- rts/Timer.c
- rts/posix/Poll.c
- rts/posix/Timeout.c
- rts/posix/Timeout.h
Changes:
=====================================
rts/IdleGC.c
=====================================
@@ -55,6 +55,8 @@
automatic GCs. Both timers must expire before an automatic GC is triggered.
See issue #11134 for additional detail.
+
+ See also Note [Deadlock detection].
*/
@@ -113,6 +115,8 @@ bool isIdleGcPending(void)
return (getRecentActivity() == ACTIVITY_INACTIVE);
}
+#if defined(THREADED_IDLEGC)
+
/* - countdown for minimum idle time before we start a GC (set by -I) */
static int idle_ticks_to_gc = 0;
@@ -170,6 +174,47 @@ void handleIdleGcTick(void)
}
}
+#else // !defined(THREADED_IDLEGC)
+
+/* Note [Idle GC without preemption]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On non-threaded platforms without pre-emption, e.g. wasm, we have to use a
+different design for scheduling idle GC (and thus deadlock detection, see
+Note [Deadlock detection]).
+
+Instead of a ticker thread that interrupts the idle capability after some delay,
+we arrange for the I/O manager to only sleep for a maximum of the idle GC delay
+time. The function getNextIdleGcDelayTime() returns this time, accounting for
+the interIdleGCWait.
+
+Then if that timeout is reached the I/O manager calls notifyIdleGcIdle(),
+which schedules an idle GC (by seting the recent activity state). The I/O
+manager must then behave as if it had been interrupted (as happens with the
+threaded idle GC design).
+*/
+
+static Time last_idle_gc_time = 0;
+
+Time getNextIdleGcDelayTime()
+{
+ Time now = getProcessElapsedTime();
+ Time delay =
+ stg_max (last_idle_gc_time + RtsFlags.GcFlags.interIdleGCWait - now,
+ RtsFlags.GcFlags.idleGCDelayTime);
+ ASSERT(delay >= 0);
+ return delay;
+}
+
+void notifyIdleGcIdle(bool deadlocked)
+{
+ if (RtsFlags.GcFlags.doIdleGC || deadlocked) {
+ setRecentActivity(ACTIVITY_INACTIVE);
+ }
+}
+
+#endif // defined(THREADED_IDLEGC)
+
void notifyIdleGcActive(void)
{
switch (getRecentActivity())
@@ -209,6 +254,9 @@ void notifyIdleGcDone(bool force_major)
setRecentActivity(ACTIVITY_DONE_GC);
#if !defined(PROFILING)
pauseTimer();
+#endif
+#if !defined(THREADED_IDLEGC)
+ last_idle_gc_time = getProcessElapsedTime();
#endif
break;
}
=====================================
rts/IdleGC.h
=====================================
@@ -10,6 +10,15 @@
#include "BeginPrivate.h"
+/* See Note [GC During Idle Time] */
+
+#if defined(HAVE_PREEMPTION)
+#define THREADED_IDLEGC
+#else
+/* See Note [Idle GC without preemption] */
+#endif
+
+
/* Are we in a state where we are want an idle GC to occur?
* Used in Capability globalWorkToDo() and Schedule scheduleDetectDeadlock.
*/
@@ -21,7 +30,19 @@ void notifyIdleGcActive(void);
/* Called from schedule(), specifically scheduleDoGC() */
void notifyIdleGcDone(bool force_major);
+#if defined(THREADED_IDLEGC)
+
/* Called from handle_tick() */
void handleIdleGcTick(void);
+#else // !defined(THREADED_IDLEGC)
+
+/* Called from I/O managers before waiting */
+Time getNextIdleGcDelayTime(void);
+
+/* Called from I/O managers after waiting */
+void notifyIdleGcIdle(bool deadlocked);
+
+#endif
+
#include "EndPrivate.h"
=====================================
rts/Timer.c
=====================================
@@ -68,7 +68,9 @@ handle_tick(int unused STG_UNUSED)
}
#endif
+#if defined(THREADED_IDLEGC)
handleIdleGcTick();
+#endif
}
void initTimer(void)
=====================================
rts/posix/Poll.c
=====================================
@@ -22,12 +22,18 @@
#include "rts/Time.h"
#include "RaiseAsync.h"
#include "Trace.h"
+#include "IdleGC.h"
#include "Poll.h"
#include "RtsSignals.h"
#include <limits.h>
#include <errno.h>
+
+#if !defined(THREADED_IDLEGC)
+#undef HAVE_DECL_PPOLL // for simplicity, always use poll when !THREADED_IDLEGC
+#endif
+
#if defined(HAVE_DECL_PPOLL) && HAVE_DECL_PPOLL == 1
/* We prefer the ppoll() function if available since it allows more precise
* timeouts. It is not in the posix standard however and some platforms
@@ -505,6 +511,17 @@ bool awaitCompletedTimeoutsOrIOPoll(CapIOManager *iomgr)
int timeout_ms = timeoutInMilliseconds(iomgr, wait, now);
#endif
+#if !defined(THREADED_IDLEGC)
+ /* Without threaded idle GC, poll() does not get interrupted for an
+ * idle GC. Instead we just limit our wait time to the idle gc delay
+ * time, and if that timeout is reached then we schedule an idle GC
+ * (see handleTimeoutForIdleGc below).
+ */
+ bool any_pending_io = nfds > 0;
+ int idlegc_status;
+ adjustTimeoutForIdleGc(any_pending_io, &timeout_ms, &idlegc_status);
+#endif
+
/* Check for I/O readiness, possibly waiting. */
#if defined(HAVE_DECL_PPOLL) && HAVE_DECL_PPOLL == 1
int res = ppoll(poll_table, nfds, timeout_ns, NULL);
@@ -533,6 +550,9 @@ bool awaitCompletedTimeoutsOrIOPoll(CapIOManager *iomgr)
#else
ASSERT(timeout_ms != -1);
#endif
+#if !defined(THREADED_IDLEGC)
+ handleIdleGcTimeout(idlegc_status, &interrupt);
+#endif
} else if (res > 0) {
int ncompletions = res;
=====================================
rts/posix/Timeout.c
=====================================
@@ -17,6 +17,7 @@
#include "Timeout.h"
#include "IOManagerInternals.h"
#include "TimeoutQueue.h"
+#include "IdleGC.h"
#include <limits.h>
@@ -135,7 +136,8 @@ static void notifyTimeoutCompletion(CapIOManager *iomgr, StgTimeout *timeout)
/* poll() expect a timeout in milliseconds, with special
* values of -1 for indefinite wait, and 0 for no waiting.
*/
-#if !(defined(HAVE_DECL_PPOLL) && HAVE_DECL_PPOLL == 1)
+#if !(defined(HAVE_DECL_PPOLL) && HAVE_DECL_PPOLL == 1) \
+ || !defined(THREADED_IDLEGC)
int timeoutInMilliseconds(CapIOManager *iomgr, bool wait, Time now)
{
if (!wait) {
@@ -220,5 +222,56 @@ struct timespec *timeoutInNanoseconds(CapIOManager *iomgr, bool wait,
}
#endif
+#if !defined(THREADED_IDLEGC)
+enum {
+ timeout_is_idlegc_delay = 1 << 0,
+ system_must_be_deadlocked = 1 << 1
+};
+
+/* Utilities for handling the non-threaded idle GC variation.
+ *
+ * See Note [Idle GC without preemption]
+ *
+ * Before calling poll()/select() etc, adjust the timeout to account for the
+ * idle GC delay time.
+ *
+ * If the timeout occurs, call handleIdleGcTimeout, which will schedule an idle
+ * GC if the timeout was reached.
+ *
+ * The idlegc_status must be passed from adjustTimeoutForIdleGc to
+ * handleIdleGcTimeout.
+ */
+void adjustTimeoutForIdleGc(bool any_pending_io,
+ int *timeout_ms /* in/out */,
+ int *idlegc_status /* out */)
+{
+ int idlegc_delay_ms = TimeToMS(getNextIdleGcDelayTime());
+
+ if (RTS_UNLIKELY(!any_pending_io && *timeout_ms == -1)) {
+ /* We must be deadlocked. Schedule an idle GC unconditionally. */
+ *timeout_ms = 0; /* Cause poll() to return res == 0 immediately. */
+ *idlegc_status = timeout_is_idlegc_delay
+ & system_must_be_deadlocked;
+
+ } else if (RTS_UNLIKELY(RtsFlags.GcFlags.doIdleGC &&
+ (idlegc_delay_ms < *timeout_ms || *timeout_ms == -1))) {
+ /* The idle GC delay will be the next timeout. */
+ *timeout_ms = idlegc_delay_ms;
+ *idlegc_status = timeout_is_idlegc_delay;
+
+ } else {
+ *idlegc_status = 0;
+ }
+}
+
+void handleIdleGcTimeout(int idlegc_status, bool *interrupt)
+{
+ if (idlegc_status & timeout_is_idlegc_delay) {
+ notifyIdleGcIdle(idlegc_status & system_must_be_deadlocked);
+ *interrupt = true;
+ }
+}
+#endif
+
#endif // defined(IOMGR_ENABLED_POLL)
=====================================
rts/posix/Timeout.h
=====================================
@@ -33,7 +33,8 @@ void processTimeoutCompletions(CapIOManager *iomgr, Time now);
* timeout in milliseconds, with special values of -1 for indefinite wait,
* and 0 for no waiting.
*/
-#if !(defined(HAVE_DECL_PPOLL) && HAVE_DECL_PPOLL == 1)
+#if !(defined(HAVE_DECL_PPOLL) && HAVE_DECL_PPOLL == 1) \
+ || !defined(THREADED_IDLEGC)
int timeoutInMilliseconds(CapIOManager *iomgr, bool wait, Time now);
#endif
@@ -46,5 +47,17 @@ struct timespec *timeoutInNanoseconds(CapIOManager *iomgr, bool wait,
Time now, struct timespec *tv);
#endif
+#if !defined(THREADED_IDLEGC)
+/* Utilities for handling the non-threaded idle GC variation.
+ *
+ * See Note [Idle GC without preemption]
+ */
+void adjustTimeoutForIdleGc(bool any_pending_io,
+ int *timeout_ms /* in/out */,
+ int *idlegc_status /* out */);
+
+void handleIdleGcTimeout(int idlegc_status, bool *interrupt);
+#endif
+
#include "EndPrivate.h"
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e3f31b3679ae1cc600189f1c99bea5f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e3f31b3679ae1cc600189f1c99bea5f…
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] 3 commits: Add -Wimplicit-field-strictness (#16836)
by Simon Peyton Jones (@simonpj) 04 Sep '26
by Simon Peyton Jones (@simonpj) 04 Sep '26
04 Sep '26
Simon Peyton Jones pushed to branch wip/T27629 at Glasgow Haskell Compiler / GHC
Commits:
9e7739ab by Simon Jakobi at 2026-09-03T13:45:43-04:00
Add -Wimplicit-field-strictness (#16836)
This opt-in warning fires when a data constructor field lacks an
explicit strictness annotation (`!` or `~`). It complements the
LazyFieldAnnotations extension (4762a8bf30f) from GHC proposal 752,
which makes `~` annotations available for this purpose.
Deciding which fields to report requires their levity, so the check
runs after typechecking. To keep the noise down, the diagnostic is
emitted once per data declaration, grouped by constructor.
Closes #16836.
Assisted-by: Claude Fable 5
- - - - -
6a44d591 by mangoiv at 2026-09-03T13:46:22-04:00
simplifier: remove a bogus `assert` in `rebuild_app'` in `GHC.CoreToStg.Prep.cpeApp`.
Prior to this commit
commit 08bc245be70d95801bc1138804ed1de9474fbdc0
Author: sheaf <sam.derbyshire(a)gmail.com>
Date: Sat Feb 28 16:30:43 2026 +0100
Clean up join points, casts & ticks
This commit shores up the logic dealing with casts and ticks occurring
in between a join point binding and a jump
any `PlaceRuntime` ticks we observed were profiling ticks, even though that
isn't necessary.
The more liberal rules in the above commit allow e.g. breakpoint ticks
(which are valid PlaceRuntime ticks) to legitimately appear in an argument
position.
Fixes #27556
- - - - -
66da220a by Simon Peyton Jones at 2026-09-04T09:31:19+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.
- - - - -
31 changed files:
- + changelog.d/27556
- + changelog.d/implicit-field-strictness-warning
- changelog.d/lazy-field-annotations
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/Tickish.hs
- docs/users_guide/exts/strict.rst
- docs/users_guide/using-warnings.rst
- testsuite/tests/simplCore/should_compile/Makefile
- + testsuite/tests/simplCore/should_compile/T27556.hs
- + testsuite/tests/simplCore/should_compile/T27556.script
- + 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/warnings/should_compile/T16836a.hs
- + testsuite/tests/warnings/should_compile/T16836a.stderr
- + testsuite/tests/warnings/should_compile/T16836b.hs
- + testsuite/tests/warnings/should_compile/T16836c.hs
- + testsuite/tests/warnings/should_compile/T16836c.stderr
- + testsuite/tests/warnings/should_compile/T16836d.hs
- + testsuite/tests/warnings/should_compile/T16836d.stderr
- testsuite/tests/warnings/should_compile/all.T
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/eed2f9cccb80bddaa047bab6f754b4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/eed2f9cccb80bddaa047bab6f754b4…
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:
1ec75528 by Zubin Duggal at 2026-09-04T10:55:54+05:30
Prepare 9.14.2-rc2
- - - - -
21 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/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/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/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/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,28 @@ 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`)
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 +143,7 @@ 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`)
Code Generation
~~~~~~~~~~~~~~~
@@ -139,6 +155,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 +171,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/1ec75528d360e85631a871ff147282e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1ec75528d360e85631a871ff147282e…
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/rafl/hpc-instances] 9 commits: hpc: WIP test
by Florian Ragwitz (@rafl) 04 Sep '26
by Florian Ragwitz (@rafl) 04 Sep '26
04 Sep '26
Florian Ragwitz pushed to branch wip/rafl/hpc-instances at Glasgow Haskell Compiler / GHC
Commits:
f2d8165d by Florian Ragwitz at 2026-09-03T13:18:32-07:00
hpc: WIP test
- - - - -
b59bce58 by Florian Ragwitz at 2026-09-03T13:18:32-07:00
hpc: Make instances available in TickTransEnv
- - - - -
3bce9b7d by Florian Ragwitz at 2026-09-03T13:18:32-07:00
hpc: Capture which method Ids belong to which dictionary function Id
- - - - -
7449851e by Florian Ragwitz at 2026-09-03T13:18:32-07:00
hpc: Carry method id mapping in TcGblEnv
- - - - -
87b43c0e by Florian Ragwitz at 2026-09-03T13:18:32-07:00
hpc: pass instance method mapping to addTicksToBinds and propagate ABEs
- - - - -
304ac851 by Florian Ragwitz at 2026-09-03T13:18:32-07:00
hpc: Do not create top-level boxes for generated instance methods
Users care about which of their written methods are or aren't covered, not
whether all of the inherited methods are covered as well. Those should be
covered where they are implemented.
This set of changes achieves the above by stopping to generate top-level boxes
which will often appear as uncovered with no clear indication as to why, and no
way to fix other than excercising code the user has not written.
- - - - -
4da0c157 by Florian Ragwitz at 2026-09-03T19:36:04-07:00
hpc: Allocate one top-level box for each class instance for coverage
- - - - -
ef171e23 by Florian Ragwitz at 2026-09-03T19:59:16-07:00
hpc: Tick top-level boxes for instances when any method is used at run-time
- - - - -
46aeba43 by Florian Ragwitz at 2026-09-03T20:05:20-07:00
hpc: Don't allocate boxes for methodless classes
With the plumbing we currently have, these could never be covered, which is not
helpful to hpc users. This could be improved upon further.
- - - - -
9 changed files:
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Monad.hs
- + testsuite/tests/hpc/instmeths/instmeths.hs
- + testsuite/tests/hpc/instmeths/instmeths.stdout
- + testsuite/tests/hpc/instmeths/test.T
Changes:
=====================================
compiler/GHC/HsToCore.hs
=====================================
@@ -147,6 +147,7 @@ deSugar hsc_env
tcg_tcs = tcs,
tcg_default_exports = defaults,
tcg_insts = insts,
+ tcg_inst_meths = inst_meths,
tcg_fam_insts = fam_insts,
tcg_complete_matches = complete_matches,
tcg_self_boot = self_boot
@@ -170,7 +171,8 @@ deSugar hsc_env
(hsc_logger hsc_env)
(initTicksConfig (hsc_dflags hsc_env))
mod mod_loc
- export_set (typeEnvTyCons type_env) binds
+ export_set (typeEnvTyCons type_env)
+ insts inst_meths binds
else return (binds, Nothing)
; let modBreaks
| Just (_, _, breakpointSpecs) <- m_tickInfo
=====================================
compiler/GHC/HsToCore/Ticks.hs
=====================================
@@ -24,6 +24,8 @@ import GHC.Unit
import GHC.Core.Type
import GHC.Core.TyCon
+import GHC.Core.InstEnv
+import GHC.Core.Class
import GHC.Data.Maybe
import GHC.Data.FastString
@@ -100,11 +102,13 @@ addTicksToBinds
-- isExportedId doesn't work yet (the desugarer
-- hasn't set it), so we have to work from this set.
-> [TyCon] -- ^ Type constructors in this module
+ -> [ClsInst]
+ -> IdEnv DFunId
-> LHsBinds GhcTc
-> IO (LHsBinds GhcTc, Maybe (FilePath, SizedSeq Tick, SizedSeq Tick))
addTicksToBinds logger cfg
- mod mod_loc exports tyCons binds
+ mod mod_loc exports tyCons insts inst_meths binds
| let passes = ticks_passes cfg
, not (null passes)
, Just orig_file <- ml_hs_file mod_loc = do
@@ -129,8 +133,13 @@ addTicksToBinds logger cfg
, this_mod = mod
, tickishType = tickish
, recSelBinds = emptyVarEnv
+ , instMeths = inst_meths
+ , instTicks = emptyVarEnv
}
- (binds',_,st') = unTM (addTickLHsBinds binds) env st
+ addTick = do
+ instTicks <- allocInstTicks insts
+ withEnv (\e -> e{ instTicks }) $ addTickLHsBinds binds
+ (binds',_,st') = unTM addTick env st
in (binds', st')
(binds1,st) = foldr tickPass (binds, initTTState) passes
@@ -231,7 +240,7 @@ addTickLHsBind :: LHsBind GhcTc -> TM (LHsBind GhcTc)
addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds
, abs_exports = abs_exports
}))) =
- withEnv (add_rec_sels . add_inlines . add_exports) $ do
+ withEnv (add_inst_meths . add_rec_sels . add_inlines . add_exports) $ do
binds' <- addTickLHsBinds binds
return $ L pos $ XHsBindsLR $ bind { abs_binds = binds' }
where
@@ -259,19 +268,26 @@ addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds
| ABE{ abe_poly, abe_mono } <- abs_exports
, RecSelId{} <- [idDetails abe_poly] ] }
+ add_inst_meths env =
+ env{ instMeths = instMeths env `extendVarEnvList`
+ [ (abe_mono, dfun)
+ | ABE{ abe_poly, abe_mono } <- abs_exports
+ , Just dfun <- [lookupVarEnv (instMeths env) abe_poly] ] }
+
addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches }))) = do
let name = getOccString id
decl_path <- getPathEntry
density <- getDensity
+ env <- getEnv
- inline_ids <- liftM inlines getEnv
-- See Note [inline sccs]
let inline = isInlinePragma (idInlinePragma id)
- || id `elemVarSet` inline_ids
+ || id `elemVarSet` inlines env
-- See Note [inline sccs]
- tickish <- tickishType `liftM` getEnv
- case tickish of { ProfNotes | inline -> return (L pos funBind); _ -> do
+ case tickishType env of { ProfNotes | inline -> return (L pos funBind); _ -> do
+
+ instTick <- instMethTick id
-- See Note [Record-selector ticks]
selTicks <- recSelTick id
@@ -294,8 +310,12 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches
toplev = null decl_path
exported = idName id `elemNameSet` exported_names
- tick <- if not blackListed &&
- shouldTickBind density toplev exported simple inline
+ let generatedInstMeth = id `elemVarEnv` instMeths env
+ && isGenerated (mg_origin (mg_ext matches))
+
+ tick <- if not generatedInstMeth
+ && not blackListed
+ && shouldTickBind density toplev exported simple inline
then
bindTick density name (locA pos) fvs
else
@@ -303,7 +323,8 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches
let mbCons = maybe Prelude.id (:)
return $ L pos $ funBind { fun_matches = mg
- , fun_ext = second (tick `mbCons`) (fun_ext funBind) }
+ , fun_ext = second ((instTick `mbCons`) . (tick `mbCons`))
+ (fun_ext funBind) }
} }
where
-- See Note [Record-selector ticks]
@@ -1098,6 +1119,8 @@ data TickTransEnv = TTE { fileName :: FastString
, this_mod :: Module
, tickishType :: TickishType
, recSelBinds :: IdEnv DVarSet
+ , instMeths :: IdEnv DFunId
+ , instTicks :: IdEnv CoreTickish
}
-- deriving Show
@@ -1238,6 +1261,21 @@ isBlackListed (RealSrcSpan pos _) = TM $ \ env st -> (Set.member pos (blackList
isBlackListed GeneratedSrcSpan{} = return False
isBlackListed UnhelpfulSpan{} = return False
+allocInstTicks :: [ClsInst] -> TM (IdEnv CoreTickish)
+allocInstTicks insts =
+ ifDensity TickForCoverage (mkVarEnv . catMaybes <$> mapM alloc insts) (pure emptyVarEnv)
+ where
+ alloc inst
+ | null (classMethods (is_cls inst)) = pure Nothing
+ | otherwise = do
+ let dfun = is_dfun inst
+ fmap (dfun,) <$> allocATickBox (TopLevelBox [getOccString dfun])
+ False True (getSrcSpan dfun) noFVs
+
+instMethTick :: Id -> TM (Maybe CoreTickish)
+instMethTick id = getEnv >>= \e ->
+ pure $ lookupVarEnv (instMeths e) id >>= lookupVarEnv (instTicks e)
+
-- the tick application inherits the source position of its
-- expression argument to support nested box allocations
allocTickBox :: BoxLabel -> Bool -> Bool -> SrcSpan -> TM (HsExpr GhcTc)
=====================================
compiler/GHC/Tc/Module.hs
=====================================
@@ -1770,7 +1770,7 @@ tcTopSrcDecls (HsGroup { hs_tyclds = tycl_decls,
-- Second pass over class and instance declarations,
-- now using the kind-checked decls
traceTc "Tc6" empty ;
- inst_binds <- tcInstDecls2 (tyClGroupTyClDecls tycl_decls) inst_infos ;
+ (inst_binds, inst_meths) <- tcInstDecls2 (tyClGroupTyClDecls tycl_decls) inst_infos ;
-- Foreign exports
traceTc "Tc7" empty ;
@@ -1802,8 +1802,9 @@ tcTopSrcDecls (HsGroup { hs_tyclds = tycl_decls,
, tcg_anns = tcg_anns tcg_env ++ annotations
, tcg_ann_env = extendAnnEnvList (tcg_ann_env tcg_env) annotations
, tcg_fords = tcg_fords tcg_env ++ foe_decls ++ fi_decls
- , tcg_dus = tcg_dus tcg_env `plusDU` usesOnly fo_fvs } } ;
+ , tcg_dus = tcg_dus tcg_env `plusDU` usesOnly fo_fvs
-- tcg_dus: see Note [Newtype constructor usage in foreign declarations]
+ , tcg_inst_meths = tcg_inst_meths tcg_env `plusVarEnv` inst_meths } } ;
-- See Note [Newtype constructor usage in foreign declarations]
addUsedGREs NoDeprecationWarnings (bagToList fo_gres) ;
=====================================
compiler/GHC/Tc/TyCl/Instance.hs
=====================================
@@ -1282,7 +1282,7 @@ takes a slightly different approach.
********************************************************************* -}
tcInstDecls2 :: [LTyClDecl GhcRn] -> [InstInfo GhcRn]
- -> TcM (LHsBinds GhcTc)
+ -> TcM (LHsBinds GhcTc, IdEnv DFunId)
-- (a) From each class declaration,
-- generate any default-method bindings
-- (b) From each instance decl
@@ -1299,11 +1299,11 @@ tcInstDecls2 tycl_decls inst_decls
-- Add the default method Ids (again)
-- (they were already added in GHC.Tc.TyCl.Utils.tcAddImplicits)
-- See Note [Default methods in the type environment]
- ; inst_binds_s <- tcExtendGlobalValEnv dm_ids $
- mapM tcInstDecl2 inst_decls
+ ; (inst_binds_s, inst_meths_s) <- unzip <$> (tcExtendGlobalValEnv dm_ids $
+ mapM tcInstDecl2 inst_decls)
-- Done
- ; return (dm_binds ++ concat inst_binds_s) }
+ ; return (dm_binds ++ concat inst_binds_s, plusVarEnvList inst_meths_s) }
{- Note [Default methods in the type environment]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1319,12 +1319,12 @@ So right here in tcInstDecls2 we must re-extend the type envt with
the default method Ids replete with their INLINE pragmas. Urk.
-}
-tcInstDecl2 :: InstInfo GhcRn -> TcM (LHsBinds GhcTc)
+tcInstDecl2 :: InstInfo GhcRn -> TcM (LHsBinds GhcTc, IdEnv DFunId)
-- Returns a binding for the dfun
tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
- = recoverM (return emptyLHsBinds) $
- setSrcSpan loc $
- addErrCtxt (instDeclCtxt2 dfun_ty) $
+ = recoverM (return (emptyLHsBinds, emptyVarEnv)) $
+ setSrcSpan loc $
+ addErrCtxt (instDeclCtxt2 dfun_ty) $
do { -- Instantiate the instance decl with skolem constants
(skol_info, inst_tyvars, dfun_theta, clas, inst_tys) <- tcSkolDFunType dfun_ty
; dfun_ev_vars <- newEvVars dfun_theta
@@ -1342,7 +1342,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
-- See Note [Typechecking plan for instance declarations]
; dfun_ev_binds_var <- newTcEvBinds
; let dfun_ev_binds = TcEvBinds dfun_ev_binds_var
- ; (tclvl, (sc_meth_ids, sc_meth_binds, sc_meth_implics))
+ ; (tclvl, (sc_meth_ids, sc_meth_binds, sc_meth_implics, meth_ids))
<- pushTcLevelM $
do { (sc_ids, sc_binds, sc_implics)
<- tcSuperClasses skol_info dfun_id clas inst_tyvars
@@ -1356,7 +1356,8 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
; return ( sc_ids ++ meth_ids
, sc_binds ++ meth_binds
- , sc_implics `unionBags` meth_implics ) }
+ , sc_implics `unionBags` meth_implics
+ , meth_ids ) }
; imp <- newImplication
; emitImplication $
@@ -1413,7 +1414,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
, abs_binds = [dict_bind]
, abs_sig = True }
- ; return (L loc' main_bind : sc_meth_binds)
+ ; return (L loc' main_bind : sc_meth_binds, mkVarEnv $ (,dfun_id) <$> meth_ids)
}
where
dfun_id = instanceDFunId ispec
=====================================
compiler/GHC/Tc/Types.hs
=====================================
@@ -157,6 +157,7 @@ import GHC.Types.Name.Env
import GHC.Types.Name.Set
import GHC.Types.Avail
import GHC.Types.Var
+import GHC.Types.Var.Env
import GHC.Types.TypeEnv
import GHC.Types.SourceFile
import GHC.Types.SrcLoc
@@ -528,6 +529,7 @@ data TcGblEnv
-- ^ Instance envt for all /home-package/ modules;
-- Includes the dfuns in tcg_insts
-- NB. BangPattern is to fix a leak, see #15111
+ tcg_inst_meths :: IdEnv DFunId,
tcg_fam_inst_env :: !FamInstEnv, -- ^ Ditto for family instances
-- NB. BangPattern is to fix a leak, see #15111
tcg_ann_env :: AnnEnv, -- ^ And for annotations
=====================================
compiler/GHC/Tc/Utils/Monad.hs
=====================================
@@ -409,6 +409,7 @@ initTcGblEnv hsc_env hsc_src keep_rn_syntax mod loc =
, tcg_knot_vars = hsc_type_env_vars hsc_env
, tcg_known_key_maps = known_key_maps_var
, tcg_inst_env = emptyInstEnv
+ , tcg_inst_meths = emptyVarEnv
, tcg_fam_inst_env = emptyFamInstEnv
, tcg_ann_env = emptyAnnEnv
, tcg_complete_match_env = []
=====================================
testsuite/tests/hpc/instmeths/instmeths.hs
=====================================
@@ -0,0 +1,47 @@
+import Data.Bifunctor
+import Data.List
+import Data.Maybe
+
+import Trace.Hpc.Mix
+import Trace.Hpc.Reflect
+import Trace.Hpc.Tix
+import Trace.Hpc.Util (HpcPos, fromHpcPos, readFileUtf8)
+
+data T = T
+
+class Foo a where
+ inheritedMethod :: a -> Int
+ inheritedMethod _ = 23
+
+ explicitMethod :: a -> Int
+
+instance Foo T where
+ explicitMethod _ = 42
+
+interesting :: (Int, MixEntry) -> Maybe (Int, HpcPos, [String])
+interesting (n, (pos, TopLevelBox path))
+ | any isInteresting path = Just (n, pos, path)
+ where
+ isInteresting name =
+ "inheritedMethod" `isInfixOf` name
+ || "explicitMethod" `isInfixOf` name
+interesting _ = Nothing
+
+sourceAt :: String -> HpcPos -> String
+sourceAt src pos
+ | l1 == l2 = take (c2 - c1 + 1) . drop (c1 - 1) $ ls !! (l1 - 1)
+ | otherwise = intercalate "\n" $ first : (middle ++ [last])
+ where
+ (l1, c1, l2, c2) = fromHpcPos pos
+ ls = lines src
+ first = drop (c1 - 1) $ ls !! (l1 - 1)
+ middle = take (l2 - l1 - 1) $ drop l1 ls
+ last = take c2 $ ls !! (l2 - 1)
+
+main :: IO ()
+main = do
+ Mix source _ _ _ mixEntries <- readMix [".hpc"] (Left "Main")
+ src <- readFileUtf8 source
+ let boxes = mapMaybe interesting $ zip [0 ..] mixEntries
+ Tix [TixModule "Main" _ _ counts] <- examineTix
+ mapM_ print [ (counts !! n, path, sourceAt src pos) | (n, pos, path) <- boxes ]
=====================================
testsuite/tests/hpc/instmeths/instmeths.stdout
=====================================
=====================================
testsuite/tests/hpc/instmeths/test.T
=====================================
@@ -0,0 +1,5 @@
+setTestOpts([omit_ghci, when(fast(), skip), js_skip])
+
+test('instmeths',
+ [ignore_extension],
+ compile_and_run, ['-fhpc'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/afe5fe8057f9a48af9adcceee7fb48…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/afe5fe8057f9a48af9adcceee7fb48…
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/az/exactprint-annotation-rationalisation] 11 commits: EPA: Located do statements
by Alan Zimmerman (@alanz) 04 Sep '26
by Alan Zimmerman (@alanz) 04 Sep '26
04 Sep '26
Alan Zimmerman pushed to branch wip/az/exactprint-annotation-rationalisation at Glasgow Haskell Compiler / GHC
Commits:
ddaa9dad by Alan Zimmerman at 2026-09-03T21:14:34+01:00
EPA: Located do statements
- - - - -
d1903a7d by Alan Zimmerman at 2026-09-03T22:19:43+01:00
EPA: Print RecStmt located
- - - - -
b2b6f17a by Alan Zimmerman at 2026-09-03T22:55:11+01:00
EPA: HsCmdDo Located
- - - - -
f48723a3 by Alan Zimmerman at 2026-09-03T22:59:45+01:00
Extend Test20297 for additional occurrences
- - - - -
7819a32e by Alan Zimmerman at 2026-09-03T22:59:45+01:00
Plan update DO NOT COMMIT
- - - - -
9571a5ba by Alan Zimmerman at 2026-09-03T22:59:45+01:00
EPA: First pass implementation of HsList, for ClassDecls
Just as a straight list replacement to start with, no payload.
This shows the scope and invasiveness of the initial change
- - - - -
e50c0be9 by Alan Zimmerman at 2026-09-03T22:59:45+01:00
EPA: HsList attempt WIP
- - - - -
20edaa07 by Alan Zimmerman at 2026-09-03T22:59:45+01:00
Enable ppr test for Haddock1. It currently fails
- - - - -
3e4fb6e4 by Alan Zimmerman at 2026-09-03T22:59:45+01:00
WIP on removing NoEpAnn. Likely abandon
- - - - -
346b41c1 by Alan Zimmerman at 2026-09-03T22:59:45+01:00
EPA: Add an overview doc for exact printing
- - - - -
86403107 by Simon Peyton Jones at 2026-09-03T22:59:45+01:00
Added an intro section
- - - - -
44 changed files:
- ANNLIST-LAYOUT-PLAN.md
- + ExactPrint.md
- LAYOUT-SCOPE-PLAN.md
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Main/Interactive.hs
- compiler/GHC/Hs.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/DocString.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Stats.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/ThToHs.hs
- compiler/Language/Haskell/Syntax.hs
- compiler/Language/Haskell/Syntax/Basic.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- ghc/GHCi/UI.hs
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/T20452.stderr
- testsuite/tests/printer/Makefile
- + testsuite/tests/printer/Test20297.expected.hs
- testsuite/tests/printer/Test20297.hs
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cb9f848c1bdea8ad4dc5daf6daa183…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cb9f848c1bdea8ad4dc5daf6daa183…
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/rafl/hpc-instances] 5 commits: hpc: Make instances available in TickTransEnv
by Florian Ragwitz (@rafl) 03 Sep '26
by Florian Ragwitz (@rafl) 03 Sep '26
03 Sep '26
Florian Ragwitz pushed to branch wip/rafl/hpc-instances at Glasgow Haskell Compiler / GHC
Commits:
ae204bf8 by Florian Ragwitz at 2026-09-03T12:11:24-07:00
hpc: Make instances available in TickTransEnv
- - - - -
844fcc29 by Florian Ragwitz at 2026-09-03T12:11:24-07:00
hpc: Capture which method Ids belong to which dictionary function Id
- - - - -
7ca944f1 by Florian Ragwitz at 2026-09-03T12:11:25-07:00
hpc: Carry method id mapping in TcGblEnv
- - - - -
54575c5a by Florian Ragwitz at 2026-09-03T12:11:25-07:00
hpc: pass instance method mapping to addTicksToBinds and propagate ABEs
- - - - -
afe5fe80 by Florian Ragwitz at 2026-09-03T12:11:25-07:00
hpc: Do not create top-level boxes for generated instance methods
Users care about which of their written methods are or aren't covered, not
whether all of the inherited methods are covered as well. Those should be
covered where they are implemented.
This set of changes achieves the above by stopping to generate top-level boxes
which will often appear as uncovered with no clear indication as to why, and no
way to fix other than excercising code the user has not written.
- - - - -
6 changed files:
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Monad.hs
Changes:
=====================================
compiler/GHC/HsToCore.hs
=====================================
@@ -147,6 +147,7 @@ deSugar hsc_env
tcg_tcs = tcs,
tcg_default_exports = defaults,
tcg_insts = insts,
+ tcg_inst_meths = inst_meths,
tcg_fam_insts = fam_insts,
tcg_complete_matches = complete_matches,
tcg_self_boot = self_boot
@@ -170,7 +171,7 @@ deSugar hsc_env
(hsc_logger hsc_env)
(initTicksConfig (hsc_dflags hsc_env))
mod mod_loc
- export_set (typeEnvTyCons type_env) binds
+ export_set (typeEnvTyCons type_env) inst_meths binds
else return (binds, Nothing)
; let modBreaks
| Just (_, _, breakpointSpecs) <- m_tickInfo
=====================================
compiler/GHC/HsToCore/Ticks.hs
=====================================
@@ -24,6 +24,7 @@ import GHC.Unit
import GHC.Core.Type
import GHC.Core.TyCon
+import GHC.Core.InstEnv
import GHC.Data.Maybe
import GHC.Data.FastString
@@ -100,11 +101,12 @@ addTicksToBinds
-- isExportedId doesn't work yet (the desugarer
-- hasn't set it), so we have to work from this set.
-> [TyCon] -- ^ Type constructors in this module
+ -> IdEnv DFunId
-> LHsBinds GhcTc
-> IO (LHsBinds GhcTc, Maybe (FilePath, SizedSeq Tick, SizedSeq Tick))
addTicksToBinds logger cfg
- mod mod_loc exports tyCons binds
+ mod mod_loc exports tyCons inst_meths binds
| let passes = ticks_passes cfg
, not (null passes)
, Just orig_file <- ml_hs_file mod_loc = do
@@ -129,6 +131,7 @@ addTicksToBinds logger cfg
, this_mod = mod
, tickishType = tickish
, recSelBinds = emptyVarEnv
+ , instMeths = inst_meths
}
(binds',_,st') = unTM (addTickLHsBinds binds) env st
in (binds', st')
@@ -231,7 +234,7 @@ addTickLHsBind :: LHsBind GhcTc -> TM (LHsBind GhcTc)
addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds
, abs_exports = abs_exports
}))) =
- withEnv (add_rec_sels . add_inlines . add_exports) $ do
+ withEnv (add_inst_meths . add_rec_sels . add_inlines . add_exports) $ do
binds' <- addTickLHsBinds binds
return $ L pos $ XHsBindsLR $ bind { abs_binds = binds' }
where
@@ -259,19 +262,24 @@ addTickLHsBind (L pos (XHsBindsLR bind@(AbsBinds { abs_binds = binds
| ABE{ abe_poly, abe_mono } <- abs_exports
, RecSelId{} <- [idDetails abe_poly] ] }
+ add_inst_meths env =
+ env{ instMeths = instMeths env `extendVarEnvList`
+ [ (abe_mono, dfun)
+ | ABE{ abe_poly, abe_mono } <- abs_exports
+ , Just dfun <- [lookupVarEnv (instMeths env) abe_poly] ] }
+
addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches }))) = do
let name = getOccString id
decl_path <- getPathEntry
density <- getDensity
+ env <- getEnv
- inline_ids <- liftM inlines getEnv
-- See Note [inline sccs]
let inline = isInlinePragma (idInlinePragma id)
- || id `elemVarSet` inline_ids
+ || id `elemVarSet` inlines env
-- See Note [inline sccs]
- tickish <- tickishType `liftM` getEnv
- case tickish of { ProfNotes | inline -> return (L pos funBind); _ -> do
+ case tickishType env of { ProfNotes | inline -> return (L pos funBind); _ -> do
-- See Note [Record-selector ticks]
selTicks <- recSelTick id
@@ -294,8 +302,12 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches
toplev = null decl_path
exported = idName id `elemNameSet` exported_names
- tick <- if not blackListed &&
- shouldTickBind density toplev exported simple inline
+ let generatedInstMeth = id `elemVarEnv` instMeths env
+ && isGenerated (mg_origin (mg_ext matches))
+
+ tick <- if not generatedInstMeth
+ && not blackListed
+ && shouldTickBind density toplev exported simple inline
then
bindTick density name (locA pos) fvs
else
@@ -1098,6 +1110,7 @@ data TickTransEnv = TTE { fileName :: FastString
, this_mod :: Module
, tickishType :: TickishType
, recSelBinds :: IdEnv DVarSet
+ , instMeths :: IdEnv DFunId
}
-- deriving Show
=====================================
compiler/GHC/Tc/Module.hs
=====================================
@@ -1770,7 +1770,7 @@ tcTopSrcDecls (HsGroup { hs_tyclds = tycl_decls,
-- Second pass over class and instance declarations,
-- now using the kind-checked decls
traceTc "Tc6" empty ;
- inst_binds <- tcInstDecls2 (tyClGroupTyClDecls tycl_decls) inst_infos ;
+ (inst_binds, inst_meths) <- tcInstDecls2 (tyClGroupTyClDecls tycl_decls) inst_infos ;
-- Foreign exports
traceTc "Tc7" empty ;
@@ -1802,8 +1802,9 @@ tcTopSrcDecls (HsGroup { hs_tyclds = tycl_decls,
, tcg_anns = tcg_anns tcg_env ++ annotations
, tcg_ann_env = extendAnnEnvList (tcg_ann_env tcg_env) annotations
, tcg_fords = tcg_fords tcg_env ++ foe_decls ++ fi_decls
- , tcg_dus = tcg_dus tcg_env `plusDU` usesOnly fo_fvs } } ;
+ , tcg_dus = tcg_dus tcg_env `plusDU` usesOnly fo_fvs
-- tcg_dus: see Note [Newtype constructor usage in foreign declarations]
+ , tcg_inst_meths = tcg_inst_meths tcg_env `plusVarEnv` inst_meths } } ;
-- See Note [Newtype constructor usage in foreign declarations]
addUsedGREs NoDeprecationWarnings (bagToList fo_gres) ;
=====================================
compiler/GHC/Tc/TyCl/Instance.hs
=====================================
@@ -1282,7 +1282,7 @@ takes a slightly different approach.
********************************************************************* -}
tcInstDecls2 :: [LTyClDecl GhcRn] -> [InstInfo GhcRn]
- -> TcM (LHsBinds GhcTc)
+ -> TcM (LHsBinds GhcTc, IdEnv DFunId)
-- (a) From each class declaration,
-- generate any default-method bindings
-- (b) From each instance decl
@@ -1299,11 +1299,11 @@ tcInstDecls2 tycl_decls inst_decls
-- Add the default method Ids (again)
-- (they were already added in GHC.Tc.TyCl.Utils.tcAddImplicits)
-- See Note [Default methods in the type environment]
- ; inst_binds_s <- tcExtendGlobalValEnv dm_ids $
- mapM tcInstDecl2 inst_decls
+ ; (inst_binds_s, inst_meths_s) <- unzip <$> (tcExtendGlobalValEnv dm_ids $
+ mapM tcInstDecl2 inst_decls)
-- Done
- ; return (dm_binds ++ concat inst_binds_s) }
+ ; return (dm_binds ++ concat inst_binds_s, plusVarEnvList inst_meths_s) }
{- Note [Default methods in the type environment]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1319,12 +1319,12 @@ So right here in tcInstDecls2 we must re-extend the type envt with
the default method Ids replete with their INLINE pragmas. Urk.
-}
-tcInstDecl2 :: InstInfo GhcRn -> TcM (LHsBinds GhcTc)
+tcInstDecl2 :: InstInfo GhcRn -> TcM (LHsBinds GhcTc, IdEnv DFunId)
-- Returns a binding for the dfun
tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
- = recoverM (return emptyLHsBinds) $
- setSrcSpan loc $
- addErrCtxt (instDeclCtxt2 dfun_ty) $
+ = recoverM (return (emptyLHsBinds, emptyVarEnv)) $
+ setSrcSpan loc $
+ addErrCtxt (instDeclCtxt2 dfun_ty) $
do { -- Instantiate the instance decl with skolem constants
(skol_info, inst_tyvars, dfun_theta, clas, inst_tys) <- tcSkolDFunType dfun_ty
; dfun_ev_vars <- newEvVars dfun_theta
@@ -1342,7 +1342,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
-- See Note [Typechecking plan for instance declarations]
; dfun_ev_binds_var <- newTcEvBinds
; let dfun_ev_binds = TcEvBinds dfun_ev_binds_var
- ; (tclvl, (sc_meth_ids, sc_meth_binds, sc_meth_implics))
+ ; (tclvl, (sc_meth_ids, sc_meth_binds, sc_meth_implics, meth_ids))
<- pushTcLevelM $
do { (sc_ids, sc_binds, sc_implics)
<- tcSuperClasses skol_info dfun_id clas inst_tyvars
@@ -1356,7 +1356,8 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
; return ( sc_ids ++ meth_ids
, sc_binds ++ meth_binds
- , sc_implics `unionBags` meth_implics ) }
+ , sc_implics `unionBags` meth_implics
+ , meth_ids ) }
; imp <- newImplication
; emitImplication $
@@ -1413,7 +1414,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = ibinds })
, abs_binds = [dict_bind]
, abs_sig = True }
- ; return (L loc' main_bind : sc_meth_binds)
+ ; return (L loc' main_bind : sc_meth_binds, mkVarEnv $ (,dfun_id) <$> meth_ids)
}
where
dfun_id = instanceDFunId ispec
=====================================
compiler/GHC/Tc/Types.hs
=====================================
@@ -157,6 +157,7 @@ import GHC.Types.Name.Env
import GHC.Types.Name.Set
import GHC.Types.Avail
import GHC.Types.Var
+import GHC.Types.Var.Env
import GHC.Types.TypeEnv
import GHC.Types.SourceFile
import GHC.Types.SrcLoc
@@ -528,6 +529,7 @@ data TcGblEnv
-- ^ Instance envt for all /home-package/ modules;
-- Includes the dfuns in tcg_insts
-- NB. BangPattern is to fix a leak, see #15111
+ tcg_inst_meths :: IdEnv DFunId,
tcg_fam_inst_env :: !FamInstEnv, -- ^ Ditto for family instances
-- NB. BangPattern is to fix a leak, see #15111
tcg_ann_env :: AnnEnv, -- ^ And for annotations
=====================================
compiler/GHC/Tc/Utils/Monad.hs
=====================================
@@ -409,6 +409,7 @@ initTcGblEnv hsc_env hsc_src keep_rn_syntax mod loc =
, tcg_knot_vars = hsc_type_env_vars hsc_env
, tcg_known_key_maps = known_key_maps_var
, tcg_inst_env = emptyInstEnv
+ , tcg_inst_meths = emptyVarEnv
, tcg_fam_inst_env = emptyFamInstEnv
, tcg_ann_env = emptyAnnEnv
, tcg_complete_match_env = []
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c5eaffb8b1932973d0d3f3809209c1…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c5eaffb8b1932973d0d3f3809209c1…
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
03 Sep '26
Florian Ragwitz pushed new branch wip/rafl/hpc-instances at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/rafl/hpc-instances
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/az/epa-tidy-locatedxxx-22] 3 commits: Add -Wimplicit-field-strictness (#16836)
by Alan Zimmerman (@alanz) 03 Sep '26
by Alan Zimmerman (@alanz) 03 Sep '26
03 Sep '26
Alan Zimmerman pushed to branch wip/az/epa-tidy-locatedxxx-22 at Glasgow Haskell Compiler / GHC
Commits:
9e7739ab by Simon Jakobi at 2026-09-03T13:45:43-04:00
Add -Wimplicit-field-strictness (#16836)
This opt-in warning fires when a data constructor field lacks an
explicit strictness annotation (`!` or `~`). It complements the
LazyFieldAnnotations extension (4762a8bf30f) from GHC proposal 752,
which makes `~` annotations available for this purpose.
Deciding which fields to report requires their levity, so the check
runs after typechecking. To keep the noise down, the diagnostic is
emitted once per data declaration, grouped by constructor.
Closes #16836.
Assisted-by: Claude Fable 5
- - - - -
6a44d591 by mangoiv at 2026-09-03T13:46:22-04:00
simplifier: remove a bogus `assert` in `rebuild_app'` in `GHC.CoreToStg.Prep.cpeApp`.
Prior to this commit
commit 08bc245be70d95801bc1138804ed1de9474fbdc0
Author: sheaf <sam.derbyshire(a)gmail.com>
Date: Sat Feb 28 16:30:43 2026 +0100
Clean up join points, casts & ticks
This commit shores up the logic dealing with casts and ticks occurring
in between a join point binding and a jump
any `PlaceRuntime` ticks we observed were profiling ticks, even though that
isn't necessary.
The more liberal rules in the above commit allow e.g. breakpoint ticks
(which are valid PlaceRuntime ticks) to legitimately appear in an argument
position.
Fixes #27556
- - - - -
d7fd9a06 by Alan Zimmerman at 2026-09-03T19:10:26+00: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.
- - - - -
29 changed files:
- + changelog.d/27556
- + changelog.d/implicit-field-strictness-warning
- changelog.d/lazy-field-annotations
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/Hs/Extension/Pass.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/Tickish.hs
- docs/users_guide/exts/strict.rst
- docs/users_guide/using-warnings.rst
- + testsuite/tests/simplCore/should_compile/T27556.hs
- + testsuite/tests/simplCore/should_compile/T27556.script
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/warnings/should_compile/T16836a.hs
- + testsuite/tests/warnings/should_compile/T16836a.stderr
- + testsuite/tests/warnings/should_compile/T16836b.hs
- + testsuite/tests/warnings/should_compile/T16836c.hs
- + testsuite/tests/warnings/should_compile/T16836c.stderr
- + testsuite/tests/warnings/should_compile/T16836d.hs
- + testsuite/tests/warnings/should_compile/T16836d.stderr
- testsuite/tests/warnings/should_compile/all.T
- utils/check-exact/ExactPrint.hs
Changes:
=====================================
changelog.d/27556
=====================================
@@ -0,0 +1,5 @@
+section: compiler
+synopsis: Remove a too strict assert in coreprep; fixes a bug where debug builds
+ of GHC would fail to compile correctly optimized programs.
+mrs: !16558
+issues: #27556
=====================================
changelog.d/implicit-field-strictness-warning
=====================================
@@ -0,0 +1,10 @@
+section: compiler
+synopsis: Add `-Wimplicit-field-strictness`
+issues: #16836
+mrs: !16555
+
+description: {
+ The new opt-in warning :ghc-flag:`-Wimplicit-field-strictness` reports
+ data constructor fields that lack an explicit strictness annotation
+ (``!`` or ``~``).
+}
=====================================
changelog.d/lazy-field-annotations
=====================================
@@ -11,4 +11,7 @@ description: {
continues to control the default strictness of unannotated fields.
See `GHC Proposal #752 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0752-l…>`_.
+
+ Also note the new opt-in :ghc-flag:`-Wimplicit-field-strictness` warning, which
+ reports fields lacking an explicit annotation.
}
=====================================
compiler/GHC/CoreToStg/Prep.hs
=====================================
@@ -1260,10 +1260,9 @@ cpeApp top_env expr
-- See Note [Ticks and mandatory eta expansion]
AITick tickish
- | tickishPlace tickish == PlaceRuntime
+ | PlaceRuntime <- tickishPlace tickish
, req_depth > 0
- -> assert (isProfTick tickish) $
- rebuild_app' env as fun' floats ss (tickish:rt_ticks) req_depth
+ -> rebuild_app' env as fun' floats ss (tickish:rt_ticks) req_depth
| otherwise
-- See [Floating Ticks in CorePrep]
-> rebuild_app' env as fun' (snocFloat floats (FloatTick tickish)) ss rt_ticks req_depth
=====================================
compiler/GHC/Driver/Flags.hs
=====================================
@@ -1142,6 +1142,7 @@ data WarningFlag =
| Opt_WarnUnrecognisedModifiers -- ^ @since 10.0
| Opt_WarnSemaphoreOpenFailure -- Since 10.0.1
| Opt_WarnDefaultedCallStack -- ^ @since 10.2
+ | Opt_WarnImplicitFieldStrictness -- ^ @since 10.2
deriving (Eq, Ord, Show, Enum, Bounded)
-- | Return the names of a WarningFlag
@@ -1251,6 +1252,7 @@ warnFlagNames wflag = case wflag of
Opt_WarnTypeEqualityRequiresOperators -> "type-equality-requires-operators" :| []
Opt_WarnMissingRoleAnnotations -> "missing-role-annotations" :| []
Opt_WarnImplicitRhsQuantification -> "implicit-rhs-quantification" :| []
+ Opt_WarnImplicitFieldStrictness -> "implicit-field-strictness" :| []
Opt_WarnIncompleteExportWarnings -> "incomplete-export-warnings" :| []
Opt_WarnIncompleteRecordSelectors -> "incomplete-record-selectors" :| []
Opt_WarnBadlyLevelledTypes -> "badly-levelled-types" :| []
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -2449,6 +2449,7 @@ wWarningFlagsDeps = [minBound..maxBound] >>= \x -> case x of
Opt_WarnUnrecognisedModifiers -> warnSpec x
Opt_WarnSemaphoreOpenFailure -> warnSpec x
Opt_WarnDefaultedCallStack -> warnSpec x
+ Opt_WarnImplicitFieldStrictness -> warnSpec x
warningGroupsDeps :: [(Deprecation, FlagSpec WarningGroup)]
warningGroupsDeps = map mk warningGroups
=====================================
compiler/GHC/Hs/Doc.hs
=====================================
@@ -58,6 +58,7 @@ import Language.Haskell.Syntax.Doc
import Language.Haskell.Syntax.Extension
import Language.Haskell.Syntax.Module.Name
+-- Exact print annotations ignore LHsDoc, so bare SrcSpan is fine
type instance Anno (WithHsDocIdentifiers (HsDocString (GhcPass pass)) (GhcPass pass)) = SrcSpan
deriving instance (Data pass, Data (LIdP pass), Data a) => Data (WithHsDocIdentifiers a pass)
=====================================
compiler/GHC/Hs/Extension/Pass.hs
=====================================
@@ -46,6 +46,7 @@ type instance XRec (GhcPass p) a = XRecGhc a
-- but pass-independent, source location
type XRecGhc a = GenLocated (Anno a) a
+-- Exact print annotations ignore LHsDoc, so bare SrcSpan is fine
type instance Anno (HsDocString (GhcPass _)) = SrcSpan
type instance Anno HsDocStringChunk = SrcSpan
=====================================
compiler/GHC/Tc/Errors/Ppr.hs
=====================================
@@ -1384,6 +1384,21 @@ instance Diagnostic TcRnMessage where
hang (text "Missing role annotation" <> colon)
2 (text "type role" <+> ppr name <+> hsep (map ppr roles))
+ TcRnImplicitFieldStrictness _lazy_anns cons -> mkSimpleDecorated $
+ hang (text "These constructor fields lack an explicit strictness annotation" <> colon)
+ 2 (vcat (map ppr_con (NE.toList cons)))
+ where
+ ppr_con (con, fields) =
+ bullet <+> text "In" <+> quotes (ppr con) <> colon <+> ppr_fields (NE.toList fields)
+ ppr_fields fields
+ | let names = [n | ImplicitStrictnessRecField n <- fields]
+ , not (null names)
+ = text "field" <> plural names <+> quotedListWithAnd (map ppr names)
+ | otherwise
+ = let poss = [i | ImplicitStrictnessPosField i <- fields]
+ in text "field" <> plural poss
+ <+> unquotedListWith (text "and") (map int poss)
+
TcRnIllformedTypePattern p
-> mkSimpleDecorated $
hang (text "Ill-formed type pattern:") 2 (ppr p)
@@ -2693,6 +2708,8 @@ instance Diagnostic TcRnMessage where
-> ErrorWithoutFlag
TcRnMissingRoleAnnotation{}
-> WarningWithFlag Opt_WarnMissingRoleAnnotations
+ TcRnImplicitFieldStrictness{}
+ -> WarningWithFlag Opt_WarnImplicitFieldStrictness
TcRnIllegalInvisTyVarBndr{}
-> ErrorWithoutFlag
TcRnIllegalWildcardTyVarBndr{}
@@ -3428,6 +3445,12 @@ instance Diagnostic TcRnMessage where
-> noHints
TcRnMissingRoleAnnotation{}
-> noHints
+ TcRnImplicitFieldStrictness lazy_anns _
+ -> SuggestExplicitFieldStrictness
+ : [ useExtensionInOrderTo
+ (text "to allow" <+> quotes (char '~') <+> text "annotations")
+ LangExt.LazyFieldAnnotations
+ | not lazy_anns ]
TcRnIllegalInvisTyVarBndr{}
-> [suggestExtension LangExt.TypeAbstractions]
TcRnIllegalWildcardTyVarBndr{}
=====================================
compiler/GHC/Tc/Errors/Types.hs
=====================================
@@ -123,6 +123,7 @@ module GHC.Tc.Errors.Types (
, TypeSyntax(..)
, typeSyntaxExtension
, SuggestLinear(..)
+ , ImplicitStrictnessField(..)
-- * Errors for hs-boot and signature files
, BadBootDecls(..)
@@ -4235,6 +4236,23 @@ data TcRnMessage where
-}
TcRnMissingRoleAnnotation :: Name -> [Role] -> TcRnMessage
+
+ {-| TcRnImplicitFieldStrictness is a warning that occurs when a data
+ constructor field lacks an explicit strictness annotation (@!@ or @~@)
+
+ Controlled by flags:
+ - Wimplicit-field-strictness
+
+ Test cases:
+ T16836a, T16836b, T16836c, T16836d
+
+ -}
+ TcRnImplicitFieldStrictness
+ :: Bool -- ^ whether @LazyFieldAnnotations@ is enabled
+ -> NonEmpty (Name, NonEmpty ImplicitStrictnessField)
+ -- ^ per data constructor, the fields lacking annotations
+ -> TcRnMessage
+
{-| TcRnPatersonCondFailure is an error that occurs when an instance
declaration fails to conform to the Paterson conditions. Which particular condition
fails depends on the constructor of PatersonCondFailure
@@ -6399,6 +6417,14 @@ data PatSynInvalidRhsReason
| PatSynUnboundVar !Name
deriving (Generic)
+-- | A constructor field lacking an explicit strictness annotation, as
+-- reported by 'TcRnImplicitFieldStrictness'.
+data ImplicitStrictnessField
+ -- | A record field
+ = ImplicitStrictnessRecField FieldLabelString
+ -- | A positional argument (1-based index)
+ | ImplicitStrictnessPosField Int
+
data BadFieldAnnotationReason where
{-| A lazy data type field annotation (~) was used without enabling the
extension LazyFieldAnnotations.
=====================================
compiler/GHC/Tc/TyCl.hs
=====================================
@@ -5022,6 +5022,16 @@ checkValidTyCon tc
; mapM_ (checkValidDataCon dflags ex_ok tc) data_cons
; mapM_ (checkPartialRecordField data_cons) (tyConFieldLabels tc)
+ ; warn_implicit_strictness <- woptM Opt_WarnImplicitFieldStrictness
+ ; when (warn_implicit_strictness
+ && not (isNewTyCon tc)
+ && not (isTypeDataTyCon tc)) $
+ whenIsJust (NE.nonEmpty (mapMaybe conImplicitStrictnessFields data_cons)) $
+ \offenders ->
+ do { lazy_anns <- xoptM LangExt.LazyFieldAnnotations
+ ; addDiagnosticTc $
+ TcRnImplicitFieldStrictness lazy_anns offenders }
+
-- Check that fields with the same name share a type
; mapM_ check_fields groups }}
where
@@ -5072,6 +5082,29 @@ checkValidTyCon tc
res2 = dataConOrigResTy con2
fty2 = dataConFieldType con2 lbl
+-- | For a given data constructor, collect the fields to report for
+-- @-Wimplicit-field-strictness@.
+--
+-- Only fields whose type is known to be lifted are collected: unlifted
+-- fields are unconditionally strict, and annotating one with @!@ or
+-- @~@ would trigger @-Wredundant-strictness-flags@.
+conImplicitStrictnessFields :: DataCon -> Maybe (Name, NonEmpty ImplicitStrictnessField)
+conImplicitStrictnessFields con
+ | Just ne_fields <- NE.nonEmpty fields
+ = Just (dataConName con, ne_fields)
+ | otherwise
+ = Nothing
+ where
+ fld_refs = case dataConFieldLabels con of
+ [] -> map ImplicitStrictnessPosField [1..]
+ lbls -> map (ImplicitStrictnessRecField . flLabel) lbls
+ fields = [ ref
+ | (ref, arg_ty, HsSrcBang _ _ NoSrcStrict)
+ <- zip3 fld_refs
+ (map scaledThing (dataConOrigArgTys con))
+ (dataConSrcBangs con)
+ , typeLevity_maybe arg_ty == Just Lifted ]
+
checkPartialRecordField :: [DataCon] -> FieldLabel -> TcM ()
-- Checks the partial record field selector, and warns.
-- See Note [Checking partial record field]
=====================================
compiler/GHC/Types/Error/Codes.hs
=====================================
@@ -542,6 +542,7 @@ type family GhcDiagnosticCode c = n | n -> c where
GhcDiagnosticCode "TcRnNegativeNumTypeLiteral" = 93632
GhcDiagnosticCode "TcRnUnusedQuantifiedTypeVar" = 54180
GhcDiagnosticCode "TcRnMissingRoleAnnotation" = 65490
+ GhcDiagnosticCode "TcRnImplicitFieldStrictness" = 47032
GhcDiagnosticCode "TcRnUntickedPromotedThing" = 49957
GhcDiagnosticCode "TcRnIllegalBuiltinSyntax" = 39716
=====================================
compiler/GHC/Types/Hint.hs
=====================================
@@ -343,6 +343,14 @@ data GhcHint
-}
| SuggestAddStandaloneKindSignature Name
+ {-| Suggests to annotate each constructor field with explicit strictness
+ (@!@ or @~@).
+
+ Triggered by: 'GHC.Tc.Errors.Types.TcRnImplicitFieldStrictness'
+ Test case(s): warnings/should_compile/T16836a
+ -}
+ | SuggestExplicitFieldStrictness
+
{-| Suggests the user to fill in the wildcard constraint to
disambiguate which constraint that is.
=====================================
compiler/GHC/Types/Hint/Ppr.hs
=====================================
@@ -185,6 +185,9 @@ instance Outputable GhcHint where
-> text "Use a standalone deriving declaration instead"
SuggestAddStandaloneKindSignature name
-> text "Add a standalone kind signature for" <+> quotes (ppr name)
+ SuggestExplicitFieldStrictness
+ -> text "Annotate each field with" <+> quotes (char '!')
+ <+> text "(strict) or" <+> quotes (char '~') <+> text "(lazy)"
SuggestFillInWildcardConstraint
-> text "Fill in the wildcard constraint yourself"
SuggestAppropriateTHTick ns
=====================================
compiler/GHC/Types/Tickish.hs
=====================================
@@ -13,7 +13,6 @@ module GHC.Types.Tickish (
mkNoCount,
mkNoScope,
tickishIsCode,
- isProfTick,
TickishPlacement(..),
tickishPlace,
tickishContains,
@@ -545,10 +544,6 @@ tickishIsCode ProfNote{} = True
tickishIsCode Breakpoint{} = True
tickishIsCode HpcTick{} = True
-isProfTick :: GenTickish pass -> Bool
-isProfTick ProfNote{} = True
-isProfTick _ = False
-
-- | Governs the kind of expression that the tick gets placed on when
-- annotating for example using @mkTick@. If we find that we want to
-- put a tickish on an expression ruled out here, we try to float it
=====================================
docs/users_guide/exts/strict.rst
=====================================
@@ -194,6 +194,9 @@ The ``~`` annotation must be written in prefix form::
See `GHC Proposal #229 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0229-w…>`__
for the precise rules.
+See also :ghc-flag:`-Wimplicit-field-strictness`, which warns about
+fields lacking an explicit annotation.
+
.. _strict-data:
Strict-by-default data types
=====================================
docs/users_guide/using-warnings.rst
=====================================
@@ -2505,6 +2505,21 @@ of ``-W(no-)*``.
In other words the type-class role cannot be accidentally left
representational or phantom, which could affected the code correctness.
+.. ghc-flag:: -Wimplicit-field-strictness
+ :shortdesc: warn when constructor fields lack explicit strictness annotations
+ :type: dynamic
+ :reverse: -Wno-implicit-field-strictness
+ :category:
+
+ :since: 10.2.1
+ :default: off
+
+ .. index::
+ single: strictness annotations, missing
+
+ This warning reports data constructor fields that lack an explicit
+ strictness annotation (``!`` or ``~``).
+
.. ghc-flag:: -Wimplicit-rhs-quantification
:shortdesc: warn when type variables on the RHS of a type synonym are implicitly quantified
:type: dynamic
=====================================
testsuite/tests/simplCore/should_compile/T27556.hs
=====================================
@@ -0,0 +1,4 @@
+import Control.Exception
+
+main = mask $ \restore -> restore (pure ())
+
=====================================
testsuite/tests/simplCore/should_compile/T27556.script
=====================================
@@ -0,0 +1 @@
+:l T27556
=====================================
testsuite/tests/simplCore/should_compile/all.T
=====================================
@@ -611,3 +611,4 @@ test('T27296', [], makefile_test, ['T27296'])
test('T27296b', [], makefile_test, ['T27296b'])
test('T27589', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques'])
test('T27590', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques'])
+test('T27556', [only_ways('ghci'), extra_hc_opts('-O -fno-unoptimized-core-for-interpreter')], ghci_script, ['T27556.script'])
=====================================
testsuite/tests/warnings/should_compile/T16836a.hs
=====================================
@@ -0,0 +1,37 @@
+{-# OPTIONS_GHC -Wimplicit-field-strictness #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+module T16836a where
+
+-- plain multi-constructor data
+-- warns for both constructors
+data T a = MkT a Bool
+ | MkT2 !Int a
+
+-- record with a shared field group
+-- warns for x, y and z; not for b
+data R = MkR { x, y :: Int, z :: Char, b :: !Bool }
+
+-- infix constructor
+-- warns for the first argument
+data I = Int :+: !Bool
+
+-- GADT syntax
+-- warns for the first argument
+data G a where
+ MkG :: Int -> !Bool -> G a
+
+-- GADT record syntax
+-- warns for gx
+data GR a where
+ MkGR :: { gx :: Int, gy :: !Bool } -> GR a
+
+-- data family instance
+-- warns
+data family F a
+data instance F Int = MkF Char
+
+-- fully annotated
+-- doesn't warn
+data S = MkS !Int !Bool
=====================================
testsuite/tests/warnings/should_compile/T16836a.stderr
=====================================
@@ -0,0 +1,55 @@
+T16836a.hs:9:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘MkT’: fields 1 and 2
+ • In ‘MkT2’: field 2
+ • In the data type declaration for ‘T’
+ Suggested fixes:
+ • Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+ • Use the ‘LazyFieldAnnotations’ extension (implied by ‘StrictData’)
+ to allow ‘~’ annotations
+
+T16836a.hs:14:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘MkR’: fields ‘x’, ‘y’ and ‘z’
+ • In the data type declaration for ‘R’
+ Suggested fixes:
+ • Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+ • Use the ‘LazyFieldAnnotations’ extension (implied by ‘StrictData’)
+ to allow ‘~’ annotations
+
+T16836a.hs:18:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘:+:’: field 1
+ • In the data type declaration for ‘I’
+ Suggested fixes:
+ • Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+ • Use the ‘LazyFieldAnnotations’ extension (implied by ‘StrictData’)
+ to allow ‘~’ annotations
+
+T16836a.hs:22:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘MkG’: field 1
+ • In the data type declaration for ‘G’
+ Suggested fixes:
+ • Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+ • Use the ‘LazyFieldAnnotations’ extension (implied by ‘StrictData’)
+ to allow ‘~’ annotations
+
+T16836a.hs:27:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘MkGR’: field ‘gx’
+ • In the data type declaration for ‘GR’
+ Suggested fixes:
+ • Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+ • Use the ‘LazyFieldAnnotations’ extension (implied by ‘StrictData’)
+ to allow ‘~’ annotations
+
+T16836a.hs:33:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘MkF’: field 1
+ • In the data family instance declaration for ‘F’
+ Suggested fixes:
+ • Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+ • Use the ‘LazyFieldAnnotations’ extension (implied by ‘StrictData’)
+ to allow ‘~’ annotations
+
=====================================
testsuite/tests/warnings/should_compile/T16836b.hs
=====================================
@@ -0,0 +1,25 @@
+{-# OPTIONS_GHC -Wimplicit-field-strictness #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeData #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE LazyFieldAnnotations #-}
+module T16836b where
+
+-- fully annotated declarations don't warn
+data T a = MkT ~a !Bool
+data R = MkR { x, y :: !Int, z :: ~Char }
+data G a where
+ MkG :: !Int -> ~Bool -> G a
+data family F a
+data instance F Int = MkF !Char
+
+-- newtypes can't have annotations; exempt
+newtype N = MkN Int
+
+-- 'type data' can't have annotations; exempt
+type data TD = MkTD Bool
+
+-- no fields, nothing to annotate
+data E
+data Nullary = A | B
=====================================
testsuite/tests/warnings/should_compile/T16836c.hs
=====================================
@@ -0,0 +1,6 @@
+{-# OPTIONS_GHC -Wimplicit-field-strictness #-}
+{-# LANGUAGE StrictData #-}
+module T16836c where
+
+-- unannotated fields warn under StrictData too
+data T a = MkT a !Bool ~Char
=====================================
testsuite/tests/warnings/should_compile/T16836c.stderr
=====================================
@@ -0,0 +1,6 @@
+T16836c.hs:6:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘MkT’: field 1
+ • In the data type declaration for ‘T’
+ Suggested fix: Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+
=====================================
testsuite/tests/warnings/should_compile/T16836d.hs
=====================================
@@ -0,0 +1,20 @@
+{-# OPTIONS_GHC -Wimplicit-field-strictness #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnliftedDatatypes #-}
+module T16836d where
+
+import GHC.Exts
+
+-- unlifted fields can't be usefully annotated; exempt
+data P = MkP Int# (# Int, Int #)
+
+type UD :: UnliftedType
+data UD = MkUD
+
+-- a field of an unlifted data type is exempt too
+data Q = MkQ UD
+
+-- mixed constructor
+-- warns only for the lifted field 2
+data M = MkM Int# Int
=====================================
testsuite/tests/warnings/should_compile/T16836d.stderr
=====================================
@@ -0,0 +1,9 @@
+T16836d.hs:20:1: warning: [GHC-47032] [-Wimplicit-field-strictness]
+ • These constructor fields lack an explicit strictness annotation:
+ • In ‘MkM’: field 2
+ • In the data type declaration for ‘M’
+ Suggested fixes:
+ • Annotate each field with ‘!’ (strict) or ‘~’ (lazy)
+ • Use the ‘LazyFieldAnnotations’ extension (implied by ‘StrictData’)
+ to allow ‘~’ annotations
+
=====================================
testsuite/tests/warnings/should_compile/all.T
=====================================
@@ -91,3 +91,7 @@ test('T25901_imp_unused_3', [extra_files(['T25901_helper_3.hs'])], multimod_comp
test('T25901_imp_unused_4', normal, compile, ['-Wunused-imports'])
test('T25901_imp_dodgy_1', [extra_files(['T25901_helper_1.hs'])], multimod_compile, ['T25901_imp_dodgy_1', '-v0 -Wdodgy-imports'])
test('T25901_imp_dodgy_2', [extra_files(['T25901_helper_2.hs'])], multimod_compile, ['T25901_imp_dodgy_2', '-v0 -Wdodgy-imports'])
+test('T16836a', normal, compile, [''])
+test('T16836b', normal, compile, [''])
+test('T16836c', normal, compile, [''])
+test('T16836d', normal, compile, [''])
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -3397,13 +3397,13 @@ instance ExactPrint (HsCmd GhcPs) where
e' <- markAnnotated e
return (HsCmdLet (tkLet', tkIn') binds' e')
- exact (HsCmdDo (an0,loc) (L l es)) = do
+ exact (HsCmdDo (an0,loc) es) = do
debugM $ "HsCmdDo"
loc' <- printStringAtAA loc "do"
(an1,es') <- markAnnList' an0 $ do
- ee <- mapM markAnnotated es
+ ee <- markAnnotated es
return ee
- return (HsCmdDo (an1,loc') (L l es'))
+ return (HsCmdDo (an1,loc') es')
-- ---------------------------------------------------------------------
@@ -4462,10 +4462,10 @@ instance ExactPrint [LocatedA (StmtLR GhcPs GhcPs (LocatedA (HsCmd GhcPs)))] whe
Just (initStmts, ls@(L _ (LastStmt _ _body _ _))) -> do
debugM $ "LocatedL [ExprLStmt: snocView"
ls' <- markAnnotated ls
- initStmts' <- markAnnotated initStmts
+ initStmts' <- mapM markAnnotated initStmts
return (initStmts' ++ [ls'])
_ -> do
- stmts' <- markAnnotated stmts
+ stmts' <- mapM markAnnotated stmts
return stmts'
instance ExactPrint [Located HsDocStringChunk] where
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6af3089f1929befb0b98143b10ad44…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6af3089f1929befb0b98143b10ad44…
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] 4 commits: Add -Wimplicit-field-strictness (#16836)
by Marge Bot (@marge-bot) 03 Sep '26
by Marge Bot (@marge-bot) 03 Sep '26
03 Sep '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
9e7739ab by Simon Jakobi at 2026-09-03T13:45:43-04:00
Add -Wimplicit-field-strictness (#16836)
This opt-in warning fires when a data constructor field lacks an
explicit strictness annotation (`!` or `~`). It complements the
LazyFieldAnnotations extension (4762a8bf30f) from GHC proposal 752,
which makes `~` annotations available for this purpose.
Deciding which fields to report requires their levity, so the check
runs after typechecking. To keep the noise down, the diagnostic is
emitted once per data declaration, grouped by constructor.
Closes #16836.
Assisted-by: Claude Fable 5
- - - - -
6a44d591 by mangoiv at 2026-09-03T13:46:22-04:00
simplifier: remove a bogus `assert` in `rebuild_app'` in `GHC.CoreToStg.Prep.cpeApp`.
Prior to this commit
commit 08bc245be70d95801bc1138804ed1de9474fbdc0
Author: sheaf <sam.derbyshire(a)gmail.com>
Date: Sat Feb 28 16:30:43 2026 +0100
Clean up join points, casts & ticks
This commit shores up the logic dealing with casts and ticks occurring
in between a join point binding and a jump
any `PlaceRuntime` ticks we observed were profiling ticks, even though that
isn't necessary.
The more liberal rules in the above commit allow e.g. breakpoint ticks
(which are valid PlaceRuntime ticks) to legitimately appear in an argument
position.
Fixes #27556
- - - - -
e3134725 by Andrei Borzenkov at 2026-09-03T14:17:55-04:00
Parentheses in prefix GADT constructors (#27423)
Updated `splitLHsGadtTy` to allow looking
through the parentheses for inner binders. General example
of a code pattern that's allowed now:
data S a where
MkS :: (forall a. S a)
That should work now with any combination of nested
foralls and parentheses.
We don't perform parenthesis unwrapping for record
GADT constructors in accordance with GHC Proposal #402.
To this end `con_inner_bndrs` no longer stores plain forall
telescopes: `[HsForAllTelescope pass]` is replaced with
`[LHsGadtTelescope pass]`, a new `HsArg`-style type whose
`HsGadtForAll` holds an inner telescope and whose `HsGadtPar`
holds a pair of parentheses. The parentheses carry no meaning
for renaming or type checking; the only reason to record them
is exact-printing.
Updated `pprConDecl` to improve the `parse == parse . ppr . parse`
property of GADT pretty-printing.
The pretty printer can now output code that's similar to this:
data T a where
MkT1 :: (forall a. T a)
MkT2 :: forall . forall a. T a
These are special cases of inner forall binders
for prefix GADT constructors, when we have either
implicit or zero explicit outer binders.
- - - - -
4da8f180 by Evgeny Malyshev at 2026-09-03T14:18:03-04:00
HsPat: Add spacing to unary tuple patterns
Use hsep when printing unary boxed TuplePat applications so that the
MkSolo constructor is separated from its argument. The old hcat rendered
wildcard and parenthesized arguments as MkSolo_ and MkSolo().
Add T27034 to exercise the HsPat splice-dump path with wildcard and
variable arguments, and update existing affected golden output.
Fixes #27034
Assisted-By: OpenAI Codex
- - - - -
61 changed files:
- + changelog.d/27556
- + changelog.d/allow-gadt-prefix-con-parens
- + changelog.d/implicit-field-strictness-warning
- changelog.d/lazy-field-annotations
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/Tickish.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Type.hs
- docs/users_guide/exts/gadt_syntax.rst
- docs/users_guide/exts/strict.rst
- docs/users_guide/using-warnings.rst
- − testsuite/tests/gadt/T14320.stderr
- testsuite/tests/gadt/T18191.hs
- testsuite/tests/gadt/T18191.stderr
- + testsuite/tests/gadt/T27423a.hs
- + testsuite/tests/gadt/T27423b.hs
- + testsuite/tests/gadt/T27423b.stderr
- testsuite/tests/gadt/all.T
- testsuite/tests/printer/Makefile
- + testsuite/tests/printer/T27423c.hs
- testsuite/tests/printer/all.T
- + testsuite/tests/simplCore/should_compile/T27556.hs
- + testsuite/tests/simplCore/should_compile/T27556.script
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/th/T17380.stderr
- testsuite/tests/th/T18612.stderr
- + testsuite/tests/th/T27034.hs
- + testsuite/tests/th/T27034.stderr
- testsuite/tests/th/T8761.stderr
- testsuite/tests/th/all.T
- + testsuite/tests/warnings/should_compile/T16836a.hs
- + testsuite/tests/warnings/should_compile/T16836a.stderr
- + testsuite/tests/warnings/should_compile/T16836b.hs
- + testsuite/tests/warnings/should_compile/T16836c.hs
- + testsuite/tests/warnings/should_compile/T16836c.stderr
- + testsuite/tests/warnings/should_compile/T16836d.hs
- + testsuite/tests/warnings/should_compile/T16836d.stderr
- testsuite/tests/warnings/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ef675ca483910d8360f51c2dbed2d4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ef675ca483910d8360f51c2dbed2d4…
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/9.14.2-rc2] 9 commits: Introduce UnitIndex for global external unit caching
by Zubin (@wz1000) 03 Sep '26
by Zubin (@wz1000) 03 Sep '26
03 Sep '26
Zubin pushed to branch wip/9.14.2-rc2 at Glasgow Haskell Compiler / GHC
Commits:
494d5744 by fendor at 2026-09-03T23:24:45+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)
- - - - -
81ff8fcf by fendor at 2026-09-03T23:24:45+05:30
Reuse the UnitIndexCache after initialising multiple home units
(cherry picked from commit 024c4d04a98f7e27b3dcb93f9b038f9b6b5a1ad9)
- - - - -
36a525b2 by Andreas Klebinger at 2026-09-03T23:24:45+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)
- - - - -
10c01bb7 by Zubin Duggal at 2026-09-03T23:24:45+05:30
hadrian: constrain splitmix to keep building on Debian 9
- - - - -
2c0d4914 by Zubin Duggal at 2026-09-03T23:24:45+05:30
Bump file-io submodule to 0.1.6
- - - - -
8f2e7775 by Zubin Duggal at 2026-09-03T23:24:45+05:30
Bump haskeline submodule to 0.8.5.0
- - - - -
4c7174d7 by Zubin Duggal at 2026-09-03T23:24:45+05:30
Bump os-string submodule to 2.0.10
- - - - -
319278b9 by Zubin Duggal at 2026-09-03T23:24:45+05:30
Bump directory submodule to 1.3.11.0
- - - - -
65e02ee2 by Zubin Duggal at 2026-09-03T23:24:45+05:30
Prepare 9.14.2-rc2
- - - - -
62 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/T27440
- − changelog.d/T27455
- − changelog.d/T27583
- − changelog.d/T27586
- − changelog.d/T27639
- − changelog.d/T27657
- − changelog.d/arm_ncg_fixes_T27430
- − changelog.d/llvm-23
- compiler/GHC.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/Types/Unique.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/Info.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- compiler/ghc.cabal.in
- docs/users_guide/9.14.2-notes.rst
- ghc/GHCi/UI.hs
- hadrian/cabal.project
- hadrian/src/Rules/Generate.hs
- libraries/base/changelog.md
- libraries/directory
- libraries/file-io
- libraries/haskeline
- libraries/os-string
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- + 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/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
- 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/08f58e965838674e2a8260145b50e1…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/08f58e965838674e2a8260145b50e1…
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