[Git][ghc/ghc][wip/dcoutts/io-manager-tidy] 11 commits: Split posix/MIO.c out of posix/Signals.c
by Duncan Coutts (@dcoutts) 08 Jul '26
by Duncan Coutts (@dcoutts) 08 Jul '26
08 Jul '26
Duncan Coutts pushed to branch wip/dcoutts/io-manager-tidy at Glasgow Haskell Compiler / GHC
Commits:
d37b0453 by Duncan Coutts at 2026-07-08T12:20:28+01:00
Split posix/MIO.c out of posix/Signals.c
The MIO I/O manager was secretly living inside the Signals file.
Now it gets its own file, like any other self-respecting I/O manager.
- - - - -
e15e8577 by Duncan Coutts at 2026-07-08T12:20:28+01:00
Rationalise some scheduler run queue utilities
Move them all to the same place in the file.
Make some static that were used only internally.
Also remove a redundant assignment after calling truncateRunQueue that
is already done within truncateRunQueue.
- - - - -
fbaa3157 by Duncan Coutts at 2026-07-08T12:20:28+01:00
Rename initIOManager{AfterFork} to {re}startIOManager
These are more accurate names, since these actions happen after
initialisation and are really about starting (or restarting) background
threads.
- - - - -
6c27b769 by Duncan Coutts at 2026-07-08T12:20:28+01:00
Free per-cap I/O managers during shutdown and forkProcess
Historically this was not strictly necessary. The select and win32
legacy I/O managers did not maintain any dynamically allocated
resources. The new poll one does (an auxillary table), and so this
should be freed.
After forkProcess, all threads get deleted. This includes threads
waiting on I/O or timers. So as of this patch, resetting the I/O
manager is just about tidying things up. For example, for the poll
I/O manager this will reset the size of the AIOP table (which
otherwise grows but never shrinks).
In future however the re-initialising will become neeecessary for
functionality, since some I/O managers will need to re-initialise
wakeup fds that are set CLOEXEC.
- - - - -
2daa8f5e by Duncan Coutts at 2026-07-08T12:26:04+01:00
Add a TODO to the MIO I/O manager
The direction of travel is to make I/O managers per-capability and have
all their state live in the struct CapIOManager. The MIO I/O manager
however still has a number of global variables.
It's not obvious how handle these globals however.
- - - - -
79d1cf40 by Duncan Coutts at 2026-07-08T12:26:04+01:00
Add a FIXME note in the Poll I/O manager
- - - - -
fd1eca2a by Duncan Coutts at 2026-07-08T12:26:04+01:00
Add missing updateRemembSetPushClosure in poll I/O manager
For the non-moving GC.
- - - - -
4ecf19cf by Duncan Coutts at 2026-07-08T12:26:04+01:00
Minor doc improvement to struct StgAsyncIOOp member outcome
Mention the enumeration names, as well as their numeric values. The rest
of the code uses the enum names.
- - - - -
7b59929c by Duncan Coutts at 2026-07-08T12:26:05+01:00
Minor doc improvements for StgTSOBlockInfo
Clarify that certain union members are used only by certain legacy
I/O managers. Hopefully we will be able to remove these at some point.
- - - - -
03cd3ca9 by Duncan Coutts at 2026-07-08T12:26:05+01:00
Avoid exporting various win32-specific rts symbols
The BeginPrivate.h / EndPrivate.h scheme works perfectly well on
Windows, but all of the rts/win32/*.h files were not using it.
- - - - -
d9414b2c by Duncan Coutts at 2026-07-08T12:26:05+01:00
Remove wakeupIOManager, ioManagerWakeup and setIOManagerWakeupFd
We no longer need wakeupIOManager for the threaded RTS case, so we can
remove it and the bits only needed to support it. This includes the
pipe/eventfd fd shared between the RTS and the in-library I/O manager
used for waking up the I/O manager thread. The pipe/eventfd still
exists, but it no longer has to be communicated to the RTS, since the
RTS no longer needs to use it.
So we remove the RTS API export setIOManagerWakeupFd, and remove uses of
it within the I/O managers in ghc-internal.
- - - - -
28 changed files:
- libraries/ghc-internal/src/GHC/Internal/Event/Control.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Manager.hs
- libraries/ghc-internal/src/GHC/Internal/Event/TimerManager.hs
- rts/Capability.c
- rts/IOManager.c
- rts/IOManager.h
- rts/RtsStartup.c
- rts/RtsSymbols.c
- rts/Schedule.c
- rts/Schedule.h
- rts/include/rts/IOInterface.h
- rts/include/rts/storage/Closures.h
- rts/include/rts/storage/TSO.h
- + rts/posix/MIO.c
- + rts/posix/MIO.h
- rts/posix/Poll.c
- rts/posix/Poll.h
- rts/posix/Signals.c
- rts/posix/Signals.h
- rts/rts.cabal
- rts/win32/AsyncMIO.h
- rts/win32/AsyncWinIO.h
- rts/win32/AwaitEvent.h
- rts/win32/ConsoleHandler.h
- rts/win32/MIOManager.h
- rts/win32/ThrIOManager.h
- rts/win32/WorkQueue.h
- rts/win32/veh_excn.h
Changes:
=====================================
libraries/ghc-internal/src/GHC/Internal/Event/Control.hs
=====================================
@@ -39,7 +39,7 @@ import GHC.Internal.Show (Show)
import GHC.Internal.Types (Bool(..), Int, IO)
import GHC.Internal.Word (Word8)
import GHC.Internal.Foreign.C.Error (throwErrnoIfMinus1_, throwErrno, getErrno)
-import GHC.Internal.Foreign.C.Types (CInt(..), CSize(..))
+import GHC.Internal.Foreign.C.Types (CSize(..))
import GHC.Internal.Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrBytes, withForeignPtr)
import GHC.Internal.Foreign.Marshal.Alloc (alloca, allocaBytes)
import GHC.Internal.Foreign.Marshal.Array (allocaArray)
@@ -51,7 +51,7 @@ import GHC.Internal.System.Posix.Types (Fd)
#if defined(HAVE_EVENTFD)
import GHC.Internal.Foreign.C.Error (throwErrnoIfMinus1, eBADF)
-import GHC.Internal.Foreign.C.Types (CULLong(..))
+import GHC.Internal.Foreign.C.Types (CInt(..), CULLong(..))
#else
import GHC.Internal.Foreign.C.Error (eAGAIN, eWOULDBLOCK, eBADF)
#endif
@@ -78,7 +78,10 @@ data Control = W {
, wakeupReadFd :: {-# UNPACK #-} !Fd
, wakeupWriteFd :: {-# UNPACK #-} !Fd
#endif
- , didRegisterWakeupFd :: !Bool
+ , didRegisterWakeupFd :: !Bool -- ^ Now redundant. Always False.
+ --TODO: remove ^^ this redundant field.
+ -- Technically, removing this is an API change to base. Sigh.
+
-- | Have this Control's fds been cleaned up?
, controlIsDead :: !(IORef Bool)
}
@@ -91,8 +94,8 @@ wakeupReadFd = controlEventFd
-- | Create the structure (usually a pipe) used for waking up the IO
-- manager thread from another thread.
-newControl :: Bool -> IO Control
-newControl shouldRegister = allocaArray 2 $ \fds -> do
+newControl :: IO Control
+newControl = allocaArray 2 $ \fds -> do
let createPipe = do
throwErrnoIfMinus1_ "pipe" $ c_pipe fds
rd <- peekElemOff fds 0
@@ -108,10 +111,8 @@ newControl shouldRegister = allocaArray 2 $ \fds -> do
ev <- throwErrnoIfMinus1 "eventfd" $ c_eventfd 0 0
setNonBlockingFD ev True
setCloseOnExec ev
- when shouldRegister $ c_setIOManagerWakeupFd ev
#else
(wake_rd, wake_wr) <- createPipe
- when shouldRegister $ c_setIOManagerWakeupFd wake_wr
#endif
isDead <- newIORef False
return W { controlReadFd = fromIntegral ctrl_rd
@@ -122,25 +123,16 @@ newControl shouldRegister = allocaArray 2 $ \fds -> do
, wakeupReadFd = fromIntegral wake_rd
, wakeupWriteFd = fromIntegral wake_wr
#endif
- , didRegisterWakeupFd = shouldRegister
+ , didRegisterWakeupFd = False
, controlIsDead = isDead
}
-- | Close the control structure used by the IO manager thread.
--- N.B. If this Control is the Control whose wakeup file was registered with
--- the RTS, then *BEFORE* the wakeup file is closed, we must call
--- c_setIOManagerWakeupFd (-1), so that the RTS does not try to use the wakeup
--- file after it has been closed.
---
--- Note, however, that even if we do the above, this function is still racy
--- since we do not synchronize between here and ioManagerWakeup.
--- ioManagerWakeup ignores failures that arise from this case.
closeControl :: Control -> IO ()
closeControl w = do
_ <- atomicSwapIORef (controlIsDead w) True
_ <- c_close . fromIntegral . controlReadFd $ w
_ <- c_close . fromIntegral . controlWriteFd $ w
- when (didRegisterWakeupFd w) $ c_setIOManagerWakeupFd (-1)
#if defined(HAVE_EVENTFD)
_ <- c_close . fromIntegral . controlEventFd $ w
#else
@@ -248,11 +240,3 @@ foreign import ccall unsafe "sys/eventfd.h eventfd"
foreign import ccall unsafe "sys/eventfd.h eventfd_write"
c_eventfd_write :: CInt -> CULLong -> IO CInt
#endif
-
-#if defined(wasm32_HOST_ARCH)
-c_setIOManagerWakeupFd :: CInt -> IO ()
-c_setIOManagerWakeupFd _ = return ()
-#else
-foreign import ccall unsafe "setIOManagerWakeupFd"
- c_setIOManagerWakeupFd :: CInt -> IO ()
-#endif
=====================================
libraries/ghc-internal/src/GHC/Internal/Event/Manager.hs
=====================================
@@ -194,7 +194,7 @@ newWith :: Backend -> IO EventManager
newWith be = do
iofds <- fmap (listArray (0, callbackArraySize-1)) $
replicateM callbackArraySize (newMVar =<< IT.new 8)
- ctrl <- newControl False
+ ctrl <- newControl
state <- newIORef Created
us <- newSource
_ <- mkWeakIORef state $ do
=====================================
libraries/ghc-internal/src/GHC/Internal/Event/TimerManager.hs
=====================================
@@ -126,7 +126,7 @@ new = newWith =<< newDefaultBackend
newWith :: Backend -> IO TimerManager
newWith be = do
timeouts <- newIORef Q.empty
- ctrl <- newControl True
+ ctrl <- newControl
state <- newIORef Created
us <- newSource
_ <- mkWeakIORef state $ do
=====================================
rts/Capability.c
=====================================
@@ -1293,6 +1293,8 @@ shutdownCapabilities(Task *task, bool safe)
static void
freeCapability (Capability *cap)
{
+ freeCapabilityIOManager(cap->iomgr);
+ stgFree(cap->iomgr);
stgFree(cap->mut_lists);
stgFree(cap->saved_mut_lists);
if (cap->current_segments) {
=====================================
rts/IOManager.c
=====================================
@@ -39,7 +39,7 @@
#endif
#if defined(IOMGR_ENABLED_MIO_POSIX)
-#include "posix/Signals.h"
+#include "posix/MIO.h"
#include "Prelude.h"
#endif
@@ -373,11 +373,25 @@ void initCapabilityIOManager(CapIOManager *iomgr)
}
+void freeCapabilityIOManager(CapIOManager *iomgr)
+{
+ switch (iomgr_type) {
+#if defined(IOMGR_ENABLED_POLL)
+ case IO_MANAGER_POLL:
+ freeCapabilityIOManagerPoll(iomgr);
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+
/* Called late in the RTS initialisation
*/
-void initIOManager(void)
+void startIOManager(void)
{
- debugTrace(DEBUG_iomanager, "initialising %s I/O manager", showIOManager());
+ debugTrace(DEBUG_iomanager, "starting %s I/O manager", showIOManager());
switch (iomgr_type) {
@@ -441,7 +455,7 @@ void initIOManager(void)
/* Called from forkProcess in the child process on the surviving capability.
*/
void
-initIOManagerAfterFork(CapIOManager *iomgr, Capability **pcap)
+restartIOManager(CapIOManager *iomgr, Capability **pcap)
{
switch (iomgr_type) {
@@ -541,42 +555,6 @@ exitIOManager(bool wait_threads)
}
}
-/* Wakeup hook: called from the scheduler's wakeUpRts (currently only in
- * threaded mode).
- */
-void wakeupIOManager(void)
-{
- switch (iomgr_type) {
-
-#if defined(IOMGR_ENABLED_MIO_POSIX)
- case IO_MANAGER_MIO_POSIX:
- /* MIO Posix implementation in posix/Signals.c */
- ioManagerWakeup();
- break;
-#endif
-#if defined(IOMGR_ENABLED_MIO_WIN32)
- case IO_MANAGER_MIO_WIN32:
- /* MIO Windows implementation in win32/ThrIOManager.c
- * Yes, this is shared with the WinIO (threaded) impl.
- */
- ioManagerWakeup();
- break;
-#endif
-#if defined(IOMGR_ENABLED_WINIO)
- case IO_MANAGER_WINIO:
-#if defined(THREADED_RTS)
- /* WinIO threaded implementation in win32/ThrIOManager.c
- * Yes, this is shared with the MIO win32 impl.
- */
- ioManagerWakeup();
-#endif
- break;
-#endif
- default:
- break;
- }
-}
-
void markCapabilityIOManager(evac_fn evac, void *user, CapIOManager *iomgr)
{
switch (iomgr_type) {
=====================================
rts/IOManager.h
=====================================
@@ -243,11 +243,33 @@ CapIOManager *allocCapabilityIOManager(Capability *cap);
*/
void initCapabilityIOManager(CapIOManager *iomgr);
+/* When shutting down a capability, or after forkProcess, free the resources
+ * held by a CapIOManager to put it back into a state in which either it can be
+ * re-initialised using initCapabilityIOManager, or the whole structure freed.
+ *
+ * Note that this does not free the CapIOManager structure itself, just the
+ * contents.
+ *
+ * This is used during capability shutdown, during RTS shutdown. It is not used
+ * when reducing the number of capabilities. Capabilities are disabled rather
+ * than freed entirely: the I/O manager keeps running but threads that become
+ * runnable are migrated away.
+ *
+ * It is also used after forkProcess.
+ */
+void freeCapabilityIOManager(CapIOManager *iomgr);
+
+/* CapIOManager life cycle:
+ *
+ * alloc -> init -> free -> free struct
+ * ^ |
+ * +--------+
+ */
/* Init hook: called from hs_init_ghc, very late in the startup after almost
* everything else is done.
*/
-void initIOManager(void);
+void startIOManager(void);
/* Init hook: called from forkProcess in the child process on the surviving
@@ -256,8 +278,8 @@ void initIOManager(void);
* This is synchronous and can run Haskell code, so can change the given cap.
* TODO: it would make for a cleaner API here if this were made asynchronous.
*/
-void initIOManagerAfterFork(CapIOManager *iomgr,
- /* inout */ Capability **pcap);
+void restartIOManager(CapIOManager *iomgr,
+ /* inout */ Capability **pcap);
/* TODO: rationalise initIOManager and initIOManagerAfterFork into a single
per-capability init function.
@@ -284,23 +306,6 @@ void stopIOManager(void);
void exitIOManager(bool wait_threads);
-/* Wakeup hook: called from the scheduler's wakeUpRts (currently only in
- * threaded mode).
- *
- * The I/O manager can be blocked waiting on I/O or timers. Sometimes there are
- * other external events where we need to wake up the I/O manager and return
- * to the schedulr.
- *
- * At the moment, all the non-threaded I/O managers will do this automagically
- * since a signal will interrupt any waiting system calls, so at the moment
- * the implementation for the non-threaded I/O managers does nothing.
- *
- * For the I/O managers in threaded mode, this arranges to unblock the I/O
- * manager if it waa blocked waiting.
- */
-void wakeupIOManager(void);
-
-
/* GC hook: mark any per-capability GC roots the I/O manager uses.
*/
void markCapabilityIOManager(evac_fn evac, void *user, CapIOManager *iomgr);
=====================================
rts/RtsStartup.c
=====================================
@@ -427,7 +427,7 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config)
}
#endif
- initIOManager();
+ startIOManager();
x86_init_fpu();
=====================================
rts/RtsSymbols.c
=====================================
@@ -265,7 +265,6 @@ extern char **environ;
#define RTS_USER_SIGNALS_SYMBOLS \
SymI_HasProto(setIOManagerControlFd) \
SymI_HasProto(setTimerManagerControlFd) \
- SymI_HasProto(setIOManagerWakeupFd) \
SymI_HasProto(blockUserSignals) \
SymI_HasProto(unblockUserSignals)
#else
=====================================
rts/Schedule.c
=====================================
@@ -175,6 +175,11 @@ static void deleteAllThreads (void);
static void deleteThread_(StgTSO *tso);
#endif
+#if defined(FORKPROCESS_PRIMOP_SUPPORTED)
+static void truncateRunQueue(Capability *cap);
+#endif
+static StgTSO *popRunQueue (Capability *cap);
+
/* ---------------------------------------------------------------------------
Main scheduling loop.
@@ -592,38 +597,6 @@ run_thread:
} /* end of while() */
}
-/* -----------------------------------------------------------------------------
- * Run queue operations
- * -------------------------------------------------------------------------- */
-
-static void
-removeFromRunQueue (Capability *cap, StgTSO *tso)
-{
- if (tso->block_info.prev == END_TSO_QUEUE) {
- ASSERT(cap->run_queue_hd == tso);
- cap->run_queue_hd = tso->_link;
- } else {
- setTSOLink(cap, tso->block_info.prev, tso->_link);
- }
- if (tso->_link == END_TSO_QUEUE) {
- ASSERT(cap->run_queue_tl == tso);
- cap->run_queue_tl = tso->block_info.prev;
- } else {
- setTSOPrev(cap, tso->_link, tso->block_info.prev);
- }
- tso->_link = tso->block_info.prev = END_TSO_QUEUE;
- cap->n_run_queue--;
-
- IF_DEBUG(sanity, checkRunQueue(cap));
-}
-
-void
-promoteInRunQueue (Capability *cap, StgTSO *tso)
-{
- removeFromRunQueue(cap, tso);
- pushOnRunQueue(cap, tso);
-}
-
/* -----------------------------------------------------------------------------
* scheduleFindWork()
*
@@ -2199,7 +2172,15 @@ forkProcess(HsStablePtr *entry
// bound threads for which the corresponding Task does not
// exist.
truncateRunQueue(cap);
- cap->n_run_queue = 0;
+
+ // Reset and re-initialise the capability's I/O manager,
+ // to get the I/O manager ready again.
+ //
+ // Any threads waiting on I/O or timers should have been
+ // removed from I/O manager queues by deleteThread_ above.
+ // TODO: but we could assert that here.
+ freeCapabilityIOManager(cap->iomgr);
+ initCapabilityIOManager(cap->iomgr);
// Any suspended C-calling Tasks are no more, their OS threads
// don't exist now:
@@ -2216,7 +2197,7 @@ forkProcess(HsStablePtr *entry
cap->n_returning_tasks = 0;
#endif
- // Release all caps except 0, we'll use that for starting
+ // Release all caps except 0, we'll use that for restarting
// the IO manager and running the client action below.
if (cap->no != 0) {
task->cap = cap;
@@ -2240,7 +2221,7 @@ forkProcess(HsStablePtr *entry
// like startup event, capabilities, process info etc
traceTaskCreate(task, cap);
- initIOManagerAfterFork(cap->iomgr, &cap);
+ restartIOManager(cap->iomgr, &cap);
// start timer after the IOManager is initialized
// (the idle GC may wake up the IOManager)
@@ -2339,6 +2320,10 @@ setNumCapabilities (uint32_t new_n_capabilities USED_IF_THREADS)
// the capability; we don't have to worry about GC data
// structures, the nursery, etc.
//
+ // This approach also handles threads blocked on I/O. Such threads
+ // remain blocked, and when I/O completes and threads become runnable
+ // then they are migrated away.
+ //
for (n = new_n_capabilities; n < enabled_capabilities; n++) {
getCapability(n)->disabled = true;
traceCapDisable(getCapability(n));
@@ -3016,7 +3001,7 @@ pushOnRunQueue (Capability *cap, StgTSO *tso)
cap->n_run_queue++;
}
-StgTSO *popRunQueue (Capability *cap)
+static StgTSO *popRunQueue (Capability *cap)
{
ASSERT(cap->n_run_queue > 0);
StgTSO *t = cap->run_queue_hd;
@@ -3036,6 +3021,45 @@ StgTSO *popRunQueue (Capability *cap)
return t;
}
+#if defined(FORKPROCESS_PRIMOP_SUPPORTED)
+static void truncateRunQueue(Capability *cap)
+{
+ // Can only be called by the task owning the capability.
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_hd, "truncateRunQueue");
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_tl, "truncateRunQueue");
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->n_run_queue, "truncateRunQueue");
+ cap->run_queue_hd = END_TSO_QUEUE;
+ cap->run_queue_tl = END_TSO_QUEUE;
+ cap->n_run_queue = 0;
+}
+#endif
+
+static void removeFromRunQueue (Capability *cap, StgTSO *tso)
+{
+ if (tso->block_info.prev == END_TSO_QUEUE) {
+ ASSERT(cap->run_queue_hd == tso);
+ cap->run_queue_hd = tso->_link;
+ } else {
+ setTSOLink(cap, tso->block_info.prev, tso->_link);
+ }
+ if (tso->_link == END_TSO_QUEUE) {
+ ASSERT(cap->run_queue_tl == tso);
+ cap->run_queue_tl = tso->block_info.prev;
+ } else {
+ setTSOPrev(cap, tso->_link, tso->block_info.prev);
+ }
+ tso->_link = tso->block_info.prev = END_TSO_QUEUE;
+ cap->n_run_queue--;
+
+ IF_DEBUG(sanity, checkRunQueue(cap));
+}
+
+void promoteInRunQueue (Capability *cap, StgTSO *tso)
+{
+ removeFromRunQueue(cap, tso);
+ pushOnRunQueue(cap, tso);
+}
+
/* -----------------------------------------------------------------------------
raiseExceptionHelper
=====================================
rts/Schedule.h
=====================================
@@ -164,10 +164,6 @@ void appendToRunQueue (Capability *cap, StgTSO *tso);
*/
void pushOnRunQueue (Capability *cap, StgTSO *tso);
-/* Pop the first thread off the runnable queue.
- */
-StgTSO *popRunQueue (Capability *cap);
-
INLINE_HEADER StgTSO *
peekRunQueue (Capability *cap)
{
@@ -184,18 +180,6 @@ emptyRunQueue(Capability *cap)
return cap->n_run_queue == 0;
}
-INLINE_HEADER void
-truncateRunQueue(Capability *cap)
-{
- // Can only be called by the task owning the capability.
- TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_hd, "truncateRunQueue");
- TSAN_ANNOTATE_BENIGN_RACE(&cap->run_queue_tl, "truncateRunQueue");
- TSAN_ANNOTATE_BENIGN_RACE(&cap->n_run_queue, "truncateRunQueue");
- cap->run_queue_hd = END_TSO_QUEUE;
- cap->run_queue_tl = END_TSO_QUEUE;
- cap->n_run_queue = 0;
-}
-
#endif /* !IN_STG_CODE */
#include "EndPrivate.h"
=====================================
rts/include/rts/IOInterface.h
=====================================
@@ -33,7 +33,6 @@ void ioManagerFinished (void);
void setIOManagerControlFd (uint32_t cap_no, int fd);
void setTimerManagerControlFd(int fd);
-void setIOManagerWakeupFd (int fd);
#endif
=====================================
rts/include/rts/storage/Closures.h
=====================================
@@ -829,11 +829,11 @@ typedef struct {
// here due to portability concerns for this C bitfield.
uint16_t notify_type: 2;
- // The outcome:
- // 0: still in-progress, no detail
- // 1: success, result field contains the result code
- // 2: failed, error field contains the error code
- // 3: cancelled, no detail
+ // The outcome (see enum IOOpOutcome):
+ // 0: IOOpOutcomeInFlight: still in-progress, no further detail.
+ // 1: IOOpOutcomeSuccess: result field contains the result code.
+ // 2: IOOpOutcomeFailed: error field contains the error code.
+ // 3: IOOpOutcomeCancelled: cancelled, no further detail.
uint16_t outcome: 2;
// 12 bits going spare!
=====================================
rts/include/rts/storage/TSO.h
=====================================
@@ -48,14 +48,16 @@ typedef union {
StgAsyncIOOp *aiop;
StgTimeoutQueue *timeout;
#if defined(mingw32_HOST_OS)
+ // Only used by the Legacy Win32 I/O manager: the async request id for the
+ // operation.
StgWord async_reqID;
#endif
#if !defined(THREADED_RTS)
StgWord target;
- // Only for the non-threaded RTS: the target time for a thread
- // blocked in threadDelay, in units of 1ms. This is a
- // compromise: we don't want to take up much space in the TSO. If
- // you want better resolution for threadDelay, use -threaded.
+ // Only for the legacy select I/O manager: the target time for a thread
+ // blocked in threadDelay, in units of 1ms. This is a compromise: we don't
+ // want to take up much space in the TSO. If you want better resolution
+ // for threadDelay, use *literally any* other I/O manager.
#endif
} StgTSOBlockInfo;
=====================================
rts/posix/MIO.c
=====================================
@@ -0,0 +1,122 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 1998-2005
+ *
+ * The MIO I/O manager RTS stub.
+ *
+ * This I/O manager lives primarily in Haskell in the ghc-internal package.
+ * This file implementes the required subset of the RTS's internal I/O manager
+ * API.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#include "rts/PosixSource.h"
+#include "Rts.h"
+
+#include "Schedule.h"
+#include "RtsUtils.h"
+#include "Prelude.h"
+#include "ThreadLabels.h"
+
+#include "MIO.h"
+#include "IOManager.h"
+#include "IOManagerInternals.h"
+
+#if defined(HAVE_ERRNO_H)
+# include <errno.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+
+// Here's the pipe into which we will send our signals
+static int timer_manager_control_wr_fd = -1;
+// TODO: Eliminate these globals. Put then into the CapIOManager, but the
+// problem is these are shared across all caps, not per cap.
+
+#define IO_MANAGER_DIE 0xfe
+
+void setTimerManagerControlFd(int fd) {
+ RELAXED_STORE(&timer_manager_control_wr_fd, fd);
+}
+
+#if defined(THREADED_RTS)
+void timerManagerNotifySignal(int sig, siginfo_t *info)
+{
+ StgWord8 buf[sizeof(siginfo_t) + 1];
+ int r;
+
+ buf[0] = sig;
+ if (info == NULL) {
+ // info may be NULL on Solaris (see #3790)
+ memset(buf+1, 0, sizeof(siginfo_t));
+ } else {
+ memcpy(buf+1, info, sizeof(siginfo_t));
+ }
+
+ int timer_control_fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
+ if (0 <= timer_control_fd)
+ {
+ r = write(timer_control_fd, buf, sizeof(siginfo_t)+1);
+ if (r == -1 && errno == EAGAIN) {
+ errorBelch("lost signal due to full pipe: %d\n", sig);
+ }
+ }
+
+ // If the IO manager hasn't told us what the FD of the write end
+ // of its pipe is, there's not much we can do here, so just ignore
+ // the signal..
+}
+#endif
+
+
+#if defined(THREADED_RTS)
+void
+ioManagerDie (void)
+{
+ StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
+ uint32_t i;
+ int r;
+
+ {
+ // Shut down timer manager
+ const int fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
+ if (0 <= fd) {
+ r = write(fd, &byte, 1);
+ if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
+ RELAXED_STORE(&timer_manager_control_wr_fd, -1);
+ }
+ }
+
+ {
+ // Shut down IO managers
+ for (i=0; i < getNumCapabilities(); i++) {
+ const int fd = RELAXED_LOAD(&getCapability(i)->iomgr->control_fd);
+ if (0 <= fd) {
+ r = write(fd, &byte, 1);
+ if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
+ RELAXED_STORE(&getCapability(i)->iomgr->control_fd, -1);
+ }
+ }
+ }
+}
+
+void
+ioManagerStartCap (Capability **cap)
+{
+ rts_evalIO(cap,ensureIOManagerIsRunning_closure,NULL);
+}
+
+void
+ioManagerStart (void)
+{
+ // Make sure the IO manager thread is running
+ Capability *cap;
+ if (SEQ_CST_LOAD(&timer_manager_control_wr_fd) < 0) {
+ cap = rts_lock();
+ ioManagerStartCap(&cap);
+ rts_unlock(cap);
+ }
+}
+#endif
+
=====================================
rts/posix/MIO.h
=====================================
@@ -0,0 +1,29 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 1998-2005
+ *
+ * Signal processing / handling.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "IOManager.h"
+
+#if defined(HAVE_SIGNAL_H)
+# include <signal.h>
+#endif
+
+#include "BeginPrivate.h"
+
+/* Communicating with the IO manager thread (see GHC.Conc).
+ */
+#if defined(THREADED_RTS)
+void ioManagerDie (void);
+void ioManagerStart (void);
+void ioManagerStartCap (/* inout */ Capability **cap);
+
+void timerManagerNotifySignal(int sig, siginfo_t *info);
+#endif
+
+#include "EndPrivate.h"
=====================================
rts/posix/Poll.c
=====================================
@@ -134,6 +134,14 @@ void initCapabilityIOManagerPoll(CapIOManager *iomgr)
}
+void freeCapabilityIOManagerPoll(CapIOManager *iomgr)
+{
+ if (iomgr->aiop_poll_table) {
+ stgFree(iomgr->aiop_poll_table);
+ }
+}
+
+
/* Used to implement syncIOWaitReady.
* Result is true on success, or false on allocation failure. */
bool syncIOWaitReadyPoll(CapIOManager *iomgr, StgTSO *tso,
@@ -194,6 +202,13 @@ void syncIOCancelPoll(CapIOManager *iomgr, StgTSO *tso)
* status, as that is done by removeFromQueues (in the throwTo* functions).
*/
tso->block_info.closure = (StgClosure *)END_TSO_QUEUE;
+
+ /* We are in the TSO case, where the aiop was only reachable from the TSO
+ * itself, and thus it is now no longer be reachable at all.
+ */
+ IF_NONMOVING_WRITE_BARRIER_ENABLED {
+ updateRemembSetPushClosure(iomgr->cap, (StgClosure *)aiop);
+ }
}
@@ -251,7 +266,6 @@ static void notifyIOCompletion(CapIOManager *iomgr, StgAsyncIOOp *aiop)
raiseAsync(iomgr->cap, tso,
(StgClosure *)blockedOnBadFD_closure,
false, NULL);
- break;
} else {
/* We should be guaranteed that the tso is still on the same
* cap because the tso was not on the run queue of any cap and
@@ -262,6 +276,12 @@ static void notifyIOCompletion(CapIOManager *iomgr, StgAsyncIOOp *aiop)
tso->_link = END_TSO_QUEUE;
pushOnRunQueue(iomgr->cap, tso);
}
+ /* For the TSO case, the aiop was only reachable from the TSO
+ * itself, and thus it is now no longer be reachable at all.
+ */
+ IF_NONMOVING_WRITE_BARRIER_ENABLED {
+ updateRemembSetPushClosure(iomgr->cap, (StgClosure *)aiop);
+ }
break;
}
case NotifyMVar:
@@ -455,6 +475,9 @@ void awaitCompletedTimeoutsOrIOPoll(CapIOManager *iomgr)
int ncompletions = res;
ASSERT(ncompletions <= (int)nfds);
processIOCompletions(iomgr, ncompletions);
+ // FIXME: do we also need to check for timeout completions now?
+ // we have a non-empty queue, but if !wait then we have also moved
+ // on and so we sould check for timeouts.
} else if (errno == EINTR) {
/* We got interrupted by a signal. In the non-threaded RTS, if the
=====================================
rts/posix/Poll.h
=====================================
@@ -17,6 +17,7 @@
#if defined(IOMGR_ENABLED_POLL)
void initCapabilityIOManagerPoll(CapIOManager *iomgr);
+void freeCapabilityIOManagerPoll(CapIOManager *iomgr);
/* Synchronous I/O and timer operations */
bool syncIOWaitReadyPoll(CapIOManager *iomgr, StgTSO *tso,
=====================================
rts/posix/Signals.c
=====================================
@@ -9,21 +9,13 @@
#include "rts/PosixSource.h"
#include "Rts.h"
-#include "Schedule.h"
#include "RtsSignals.h"
-#include "Signals.h"
-#include "IOManager.h"
#include "RtsUtils.h"
+#include "Schedule.h"
#include "Prelude.h"
-#include "Ticker.h"
#include "ThreadLabels.h"
#include "Libdw.h"
-
-/* TODO: eliminate this include. This file should be about signals, not be
- * part of an I/O manager implementation. The code here that are really part
- * of an I/O manager should be moved into an appropriate I/O manager impl.
- */
-#include "IOManagerInternals.h"
+#include "MIO.h"
#if defined(alpha_HOST_ARCH)
# if defined(linux_HOST_OS)
@@ -41,19 +33,10 @@
# include <signal.h>
#endif
-#if defined(HAVE_ERRNO_H)
-# include <errno.h>
-#endif
-
-#if defined(HAVE_EVENTFD_H)
-# include <sys/eventfd.h>
-#endif
-
#if defined(HAVE_TERMIOS_H)
#include <termios.h>
#endif
-#include <stdlib.h>
#include <string.h>
/* This curious flag is provided for the benefit of the Haskell binding
@@ -134,110 +117,6 @@ more_handlers(int sig)
nHandlers = sig + 1;
}
-// Here's the pipe into which we will send our signals
-static int io_manager_wakeup_fd = -1;
-static int timer_manager_control_wr_fd = -1;
-
-#define IO_MANAGER_WAKEUP 0xff
-#define IO_MANAGER_DIE 0xfe
-#define IO_MANAGER_SYNC 0xfd
-
-void setTimerManagerControlFd(int fd) {
- RELAXED_STORE(&timer_manager_control_wr_fd, fd);
-}
-
-void
-setIOManagerWakeupFd (int fd)
-{
- // only called when THREADED_RTS, but unconditionally
- // compiled here because GHC.Event.Control depends on it.
- SEQ_CST_STORE(&io_manager_wakeup_fd, fd);
-}
-
-/* -----------------------------------------------------------------------------
- * Wake up at least one IO or timer manager HS thread.
- * -------------------------------------------------------------------------- */
-void
-ioManagerWakeup (void)
-{
- int r;
- const int wakeup_fd = SEQ_CST_LOAD(&io_manager_wakeup_fd);
- // Wake up the IO Manager thread by sending a byte down its pipe
- if (wakeup_fd >= 0) {
-#if defined(HAVE_EVENTFD)
- StgWord64 n = (StgWord64)IO_MANAGER_WAKEUP;
- r = write(wakeup_fd, (char *) &n, 8);
-#else
- StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
- r = write(wakeup_fd, &byte, 1);
-#endif
- /* N.B. If the TimerManager is shutting down as we run this
- * then there is a possibility that our first read of
- * io_manager_wakeup_fd is non-negative, but before we get to the
- * write the file is closed. If this occurs, io_manager_wakeup_fd
- * will be written into with -1 (GHC.Event.Control does this prior
- * to closing), so checking this allows us to distinguish this case.
- * To ensure we observe the correct ordering, we declare the
- * io_manager_wakeup_fd as volatile.
- * Since this is not an error condition, we do not print the error
- * message in this case.
- */
- if (r == -1 && SEQ_CST_LOAD(&io_manager_wakeup_fd) >= 0) {
- sysErrorBelch("ioManagerWakeup: write");
- }
- }
-}
-
-#if defined(THREADED_RTS)
-void
-ioManagerDie (void)
-{
- StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
- uint32_t i;
- int r;
-
- {
- // Shut down timer manager
- const int fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
- if (0 <= fd) {
- r = write(fd, &byte, 1);
- if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
- RELAXED_STORE(&timer_manager_control_wr_fd, -1);
- }
- }
-
- {
- // Shut down IO managers
- for (i=0; i < getNumCapabilities(); i++) {
- const int fd = RELAXED_LOAD(&getCapability(i)->iomgr->control_fd);
- if (0 <= fd) {
- r = write(fd, &byte, 1);
- if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
- RELAXED_STORE(&getCapability(i)->iomgr->control_fd, -1);
- }
- }
- }
-}
-
-void
-ioManagerStartCap (Capability **cap)
-{
- rts_evalIO(cap,ensureIOManagerIsRunning_closure,NULL);
-}
-
-void
-ioManagerStart (void)
-{
- // Make sure the IO manager thread is running
- Capability *cap;
- if (SEQ_CST_LOAD(&timer_manager_control_wr_fd) < 0 || SEQ_CST_LOAD(&io_manager_wakeup_fd) < 0) {
- cap = rts_lock();
- ioManagerStartCap(&cap);
- rts_unlock(cap);
- }
-}
-#endif
-
#if !defined(THREADED_RTS)
#define N_PENDING_HANDLERS 16
@@ -260,31 +139,9 @@ generic_handler(int sig USED_IF_THREADS,
void *p STG_UNUSED)
{
#if defined(THREADED_RTS)
-
- StgWord8 buf[sizeof(siginfo_t) + 1];
- int r;
-
- buf[0] = sig;
- if (info == NULL) {
- // info may be NULL on Solaris (see #3790)
- memset(buf+1, 0, sizeof(siginfo_t));
- } else {
- memcpy(buf+1, info, sizeof(siginfo_t));
- }
-
- int timer_control_fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
- if (0 <= timer_control_fd)
- {
- r = write(timer_control_fd, buf, sizeof(siginfo_t)+1);
- if (r == -1 && errno == EAGAIN) {
- errorBelch("lost signal due to full pipe: %d\n", sig);
- }
- }
-
- // If the IO manager hasn't told us what the FD of the write end
- // of its pipe is, there's not much we can do here, so just ignore
- // the signal..
-
+ //TODO: This calls MIO directly. We should go via IOManager API.
+ // The IOManager API should be extended to cover signals.
+ timerManagerNotifySignal(sig, info);
#else /* not THREADED_RTS */
/* Can't call allocate from here. Probably can't call malloc
=====================================
rts/posix/Signals.h
=====================================
@@ -25,18 +25,6 @@ extern siginfo_t *next_pending_handler;
void startSignalHandlers(Capability *cap);
#endif
-/* Communicating with the IO manager thread (see GHC.Conc).
- *
- * TODO: these I/O manager things are not related to signals and ought to live
- * elsewhere, e.g. in a module specifically for the I/O manager.
- */
-void ioManagerWakeup (void);
-#if defined(THREADED_RTS)
-void ioManagerDie (void);
-void ioManagerStart (void);
-void ioManagerStartCap (/* inout */ Capability **cap);
-#endif
-
extern StgInt *signal_handlers;
#include "EndPrivate.h"
=====================================
rts/rts.cabal
=====================================
@@ -583,6 +583,7 @@ library
posix/OSMem.c
posix/OSThreads.c
posix/FdWakeup.c
+ posix/MIO.c
posix/Poll.c
posix/Select.c
posix/Signals.c
=====================================
rts/win32/AsyncMIO.h
=====================================
@@ -12,6 +12,8 @@
#include "Rts.h"
+#include "BeginPrivate.h"
+
extern unsigned int
addIORequest(int fd,
bool forWriting,
@@ -28,3 +30,5 @@ extern int awaitRequests(bool wait);
extern void abandonRequestWait(void);
extern void resetAbandonRequestWait(void);
extern HsInt rts_EINTR(void);
+
+#include "EndPrivate.h"
=====================================
rts/win32/AsyncWinIO.h
=====================================
@@ -14,12 +14,16 @@
#include <stdbool.h>
#include <windows.h>
-extern bool startupAsyncWinIO(void);
-extern void shutdownAsyncWinIO(bool wait_threads);
-extern void awaitAsyncRequests(bool wait);
extern void registerIOCPHandle (HANDLE port);
extern void registerAlertableWait (bool has_timeout, DWORD mssec);
-
extern OVERLAPPED_ENTRY* getOverlappedEntries (uint32_t *num);
extern void completeSynchronousRequest (void);
+
+#include "BeginPrivate.h"
+
+extern bool startupAsyncWinIO(void);
+extern void shutdownAsyncWinIO(bool wait_threads);
+extern void awaitAsyncRequests(bool wait);
extern bool queueIOThread(void);
+
+#include "EndPrivate.h"
=====================================
rts/win32/AwaitEvent.h
=====================================
@@ -1,4 +1,7 @@
#pragma once
+#include "BeginPrivate.h"
+
void awaitCompletedTimeoutsOrIOWin32(Capability *cap, bool wait);
+#include "EndPrivate.h"
=====================================
rts/win32/ConsoleHandler.h
=====================================
@@ -7,6 +7,8 @@
#pragma once
+#include "BeginPrivate.h"
+
/*
* Console control handlers lets an application handle Ctrl+C, Ctrl+Break etc.
* in Haskell under Win32. Akin to the Unix signal SIGINT.
@@ -69,3 +71,5 @@ extern int rts_waitConsoleHandlerCompletion(void);
* Tear down and shut down user signal processing.
*/
extern void finiUserSignals(void);
+
+#include "EndPrivate.h"
=====================================
rts/win32/MIOManager.h
=====================================
@@ -12,6 +12,8 @@
#include <windows.h>
+#include "BeginPrivate.h"
+
/*
The IOManager subsystem provides a non-blocking view
of I/O operations. It lets one (or more) OS thread(s)
@@ -107,3 +109,5 @@ extern int AddProcRequest ( void* proc,
extern void abandonWorkRequest ( int reqID );
extern void interruptIOManagerEvent ( void );
+
+#include "EndPrivate.h"
=====================================
rts/win32/ThrIOManager.h
=====================================
@@ -12,7 +12,12 @@
/* Communicating with the IO manager thread (see GHC.Conc).
*/
+void ioManagerFinished (void);
+
+#include "BeginPrivate.h"
+
void ioManagerWakeup (void);
void ioManagerDie (void);
void ioManagerStart (void);
-void ioManagerFinished (void);
+
+#include "EndPrivate.h"
=====================================
rts/win32/WorkQueue.h
=====================================
@@ -10,6 +10,8 @@
#include <windows.h>
+#include "BeginPrivate.h"
+
/* This is a fixed-size queue. */
#define WORKQUEUE_SIZE 16
@@ -34,3 +36,5 @@ extern HANDLE GetWorkQueueHandle ( WorkQueue* pq );
extern BOOL GetWork ( WorkQueue* pq, void** ppw );
extern BOOL FetchWork ( WorkQueue* pq, void** ppw );
extern int SubmitWork ( WorkQueue* pq, void* pw );
+
+#include "EndPrivate.h"
=====================================
rts/win32/veh_excn.h
=====================================
@@ -59,6 +59,8 @@
// simplified quite a bit.
// Using VEH also means we don't have to worry about the dynamic code generated by GHCi.
+#include "BeginPrivate.h"
+
// Prototype of the VEH callback function.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms681419(v=vs.85).…
//
@@ -72,3 +74,5 @@ void __unregister_hs_exception_handler( void );
// prototypes for dump methods.
void generateDump(EXCEPTION_POINTERS* pExceptionPointers);
void generateStack (EXCEPTION_POINTERS* pExceptionPointers);
+
+#include "EndPrivate.h"
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/268152b0a44214325ee6b243d302d6…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/268152b0a44214325ee6b243d302d6…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T27448] 74 commits: perf: Share Module in Iface Symbol Table
by Simon Jakobi (@sjakobi2) 08 Jul '26
by Simon Jakobi (@sjakobi2) 08 Jul '26
08 Jul '26
Simon Jakobi pushed to branch wip/sjakobi/T27448 at Glasgow Haskell Compiler / GHC
Commits:
27463426 by Rodrigo Mesquita at 2026-06-26T20:54:58-04:00
perf: Share Module in Iface Symbol Table
This commit modifies the structure of the serialized `SymbolTable Name`
to then re-use and share the `Module` (both on disk and in memory) across
all `Name`s from the same module.
The new structure looks like:
<total name count>
$modules.size
for (mod, names) in $modules:
$mod
$names.size
for table_ix, occ in $names
$table_ix
$occ
i.e. we put the module just once, followed by all names in that module.
When deserializing, we deserialize the module just once, and all the
following `Name`s are constructed with a pointer to that same decoded
`Module`.
In `hoogle-test`, we must use `DNameEnv` rather than `Map Name`,
otherwise the output fixities order was susceptible to changes in the
uniques assigned to each Names, which is not stable.
Fixes #27401
-------------------------
Metric Decrease:
InstanceMatching
LinkableUsage01
LinkableUsage02
hard_hole_fits
-------------------------
- - - - -
412f1675 by Simon Hengel at 2026-06-26T20:55:41-04:00
Rename `MCDiagnostic` to `InternalMCDiagnostic`
`MCDiagnostic` is meant to be used for compiler diagnostics.
Any code that creates `MCDiagnostic` directly, without going through
`GHC.Driver.Errors.printMessage`, sidesteps `-fdiagnostics-as-json` (see
e.g. !14616, !14475, !14492 !14548).
To avoid this in the future, this change more narrowly controls who
creates `MCDiagnostic` (see #24113).
- - - - -
6f212121 by Facundo Domínguez at 2026-06-26T20:56:27-04:00
Encapsulate options of occurAnalysePgm in a record
- - - - -
adfbb179 by Facundo Domínguez at 2026-06-26T20:56:27-04:00
Allow to configure the occurrence analyser to retain some dead bindings
This is needed by plugins that are the only consumers of a binding which
is otherwise unused in the program.
See Note [Controlling elimination of dead bindings in occurrence analysis]
added in this commit, or
https://gitlab.haskell.org/ghc/ghc/-/issues/27240 for more discussion.
- - - - -
c745b11f by Copilot at 2026-06-26T20:56:27-04:00
Address documentation feedback
- - - - -
2c2a4a2a by Copilot at 2026-06-26T20:56:27-04:00
Keep the imp_rules parameter of occurPgmAnalysePgm and add occ_opts to OccEnv
- - - - -
e2262b0e by Copilot at 2026-06-26T20:56:27-04:00
Strengthen T27240.hs with a binding that should be removed
- - - - -
5f9d9268 by Copilot at 2026-06-26T20:56:27-04:00
Move the reference #27240 to a related paragraph
- - - - -
d86d2644 by Simon Hengel at 2026-06-26T20:57:10-04:00
Remove deprecated flag `-ddump-json` (see #24113)
This was first deprecated in 9.10.1.
- - - - -
3b15ff03 by Simon Jakobi at 2026-06-27T18:48:34+02:00
Tweak mk_mod_usage_info
* Use O(log n) `elemModuleEnv` instead of O(n) `elem` to filter the
direct imports.
* Use `nonDetModuleEnvKeys` to avoid sorting the ent_map keys twice.
* Prepend the presumably shorter list when creating all_mods with
`(++)`. Actually this eliminates the `(++)` entirely, as it seems to
fuse with the `filter` expression.
As a result there is a tiny speed-up when generating the .hi-files for
modules with many imports.
None of the changes affect compilation determinism as the module list
is explicitly sorted to ensure a canonical order.
- - - - -
2d0fd154 by Alan Zimmerman at 2026-06-29T11:44:00-04:00
EPA: Remove LocatedC / SrcSpanAnnC
This is part of a cleanup of the zoo of
SrcSpanAnnXXX types for exact print annotations.
This one removes SrcSpanAnnC used for storing exact print annotations
for contexts. It replaces it with an explicit `HsContext` data type
that carries the annotations and the context.
So, replace
type HsContext pass = [LHsType pass]
with
type HsContext pass = HsContextDetails pass (LHsType pass)
data HsContextDetails pass arg
= HsContext
{ hsc_ext :: !(XHsContext pass)
, hsc_ctxt :: [arg]
}
| XHsContextDetails !(XXHsContextDetails pass)
We need the parameterised HsContextDetails because it is used both for
HsQual carrying 'LHsExpr p' and "normal" contexts carrying 'LHsType p'.
- - - - -
cca0d589 by Luite Stegeman at 2026-06-30T13:33:40-04:00
rts: handle large AP closures in compacting GC
The function update_fwd_large in the compacting GC could run into
an unexpected object with the following error:
internal error: update_fwd_large: unknown/strange object 24
Closure type 24 is the AP closure, which was not handled in
upd_fwd_large. This patch adds handling them.
fixes #27434
- - - - -
42935858 by Luite Stegeman at 2026-06-30T13:33:40-04:00
testsuite: use compacting_gc way instead of hardcoding +RTS -c
- - - - -
bf7b5ce6 by Alan Zimmerman at 2026-06-30T13:34:23-04:00
EPA: Remove LocatedLW from LStmtLR
HsDo already had its XDo extension point for an
AnnList, which also appeared in LocatedLW.
So we remove the redundant one and use the one inside HsDo
as originally intended.
Also delete LocatedLC/LocatedLS as they were unused
- - - - -
d7cfea49 by Recursion Ninja at 2026-06-30T21:37:12-04:00
Decoupling 'L.H.S' from 'GHC.Types.SourceText'
* Migrated 'IntegralLit' to 'L.H.S.Lit'.
* Migrated 'FractionalLit' to 'L.H.S.Lit'.
* Migrated 'StringLiteral' to 'L.H.S.Lit'.
* Added TTG extension points to the types above.
* Added nice export list to 'GHC.Hs.Lit'.
* Added 'rnOverLitVal' and 'tcOverLitVal' functions to 'GHC.Hs.Lit'.
* Added instance 'Anno (StringLiteral (GhcPass p)) = SrcSpanAnnN'
* Moved [Notes] about 'SourceText' from 'L.H.S.*' to 'GHC.*'.
* Removed all references to 'SourceText' from 'L.H.S'.
* Removed the trailing comma record field from 'StringLiteral'
* Renamed exported functions for nomenclature consistency.
* Deprecated the renamed functions
Fixes #26953
- - - - -
a1f2558b by Recursion Ninja at 2026-06-30T21:37:12-04:00
Monomorphising GHC pass parameters where appropriate
- - - - -
7bf9e3c5 by Teo Camarasu at 2026-06-30T21:38:03-04:00
Make Q abstract
This patch aims to clearly demarcate the internal and external interfaces
of Q.
In the past the `Quasi` typeclass was both part of the external,
public-facing interface, and was used to give the implementation of `Q`.
Now we separate out these two distinct roles. `Quasi` continues to exist
in the public interface, but we introduce a new `MetaHandlers` type,
which is equivalent to `Dict Quasi`.
`Q a` is now defined to be `MetaHandlers -> IO a`, and, crucially,
the constructor and the new `MetaHandlers` type are not exposed from the
public interface.
This gives us the ability to vary the interface on the GHC side without
forcing a breaking change on the `template-haskell` side.
Similarly `template-haskell` has more freedom to change the `Quasi`
typeclass without needing any changes in `lib:ghc`.
Implements https://github.com/ghc-proposals/ghc-proposals/pull/700
Resolves #27341
- - - - -
4262af36 by L0neGamer at 2026-06-30T21:38:56-04:00
generically defines mconcat in terms of internal type's Semigroup instance
add changelog entry
use simpler definition for mconcat
`nonEmpty` isn't available yet; inline branches in case
add test case
fixup generically defines mconcat in terms of internal type's Semigroup instance
add comment on Generically and deriving mishaps
swap mconcat to foldr version
add some strictness testing for mconcat
add to `base` changelog entry
- - - - -
e22ad997 by Cheng Shao at 2026-06-30T21:39:43-04:00
hadrian/rts: fix unregisterised build for gcc 15+
This patch fixes unregisterised build for gcc 15+:
- Pass -optc-Wno-error in hadrian when +werror enables -optc-Werror,
see added comment for details.
- For RTS functions that the codegen would emit calls, ensure their
real prototype is hidden when the header is included in .hc fies
(IN_STG_CODE), and the dummy prototype is provided to match the EFF_
convention.
In the future we should get rid of EFF_ (#14647) and remove these
hacks, but for now this patch makes unregisterised work again on newer
toolchains. Fixes #27404.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
3f00f234 by Cheng Shao at 2026-06-30T21:40:32-04:00
compiler: fix missing handling of CmmUnsafeForeignCall node in LayoutStack
This patch fixes missing handling of `CmmUnsafeForeignCall` middle
node in the `LayoutStack` pass.
Before proc-points splitting, this pass computes liveliness of local
registers, and spills those alive across a Cmm native call onto the
stack. It need to traverse all middle nodes in each block and check
whether a local register is an assignee, if so then the previous
mapping in `sm_regs` is invalidated and needs to be dropped. However,
it didn't handle `CmmUnsafeForeignCall` node which may also assign to
a local register. When proc-points splitting is enabled, this can
produce an invalid basic block that doesn't properly backup the
updated local register to the stack before doing a Cmm call, resulting
in completely invalid runtime behavior.
The patch also adds a `T27447` regression test. With no-TNTC or with
LLVM backend, without the fix the test case would output a stale
0x1111111111111111 value, instead of the expected 0x2222222222222222
output.
Fixes #27447.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
701088db by Ben Gamari at 2026-07-01T10:34:03-04:00
gitlab-ci: Drop vestigial references to make build system
- - - - -
62d54a53 by Ben Gamari at 2026-07-01T10:34:03-04:00
gitlab-ci: Add support for running specifying a job's testsuite ways
- - - - -
7f97ac2c by Ben Gamari at 2026-07-01T10:34:03-04:00
gitlab-ci: Run llvm testsuite ways in llvm jobs
Addresses #25762.
- - - - -
7ea75116 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Add normalise_ddump_deriv setup function
Some tests check the result of -ddump-deriv, which may contain INLINE pragmas depending on optimization flags.
With normalise_ddump_deriv setup function, INLINE pragmas are stripped off.
- - - - -
c7a8199f by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Use -dsuppress-idinfo to make tests more robust
Previously, T18052a and T21755 were failing on 'optasm' and 'optllvm' ways because of visibility of unfoldings.
- - - - -
a12122e5 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Use a trick to keep large objects alive
Previously, T17574 and T19381 were failing on 'optasm' and 'optllvm' ways because of compiler optimizations.
Change them to use NOINLINE to prevent unwanted optimizations.
- - - - -
1a95b327 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Only run T24224 in 'normal' way
This test is a frontend-only one and breaks if optimizations are enabled.
- - - - -
8abea737 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Ignore T18118's stderr
When optimizations are enabled, the compiler emits a warning (You cannot SPECIALISE ...).
The message is not important, so ignore it.
- - - - -
9453a722 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Mark T816 and tc216 broken with optimizations
These tests are about type checking, so we should not care too much if they are broken with optimizations.
See #26952
- - - - -
0aef9ec0 by Ben Gamari at 2026-07-01T10:34:03-04:00
testsuite: ds014 is not longer broken
It now appears to pass in the ways it was marked as broken in.
Closes #14901.
- - - - -
4692d1e4 by Ben Gamari at 2026-07-01T10:34:03-04:00
testsuite: Only run stack cloning tests in the normal way
These are too dependent upon code generation specifics to pass in most
other ways.
- - - - -
c154df26 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Update options_ghc_fbyte-code
The `-fbyte-code` option used to be overriden by `-fllvm` but it is no longer true since !14872 was merged.
I updated the test to accept the new behavior.
Closes #27049
- - - - -
5d8bb7b5 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Only run T22744 in 'normal' way
This test takes a long time on optimized ways.
- - - - -
d1e74c8e by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Disable tests that use -finfo-table-map on llvm ways
Currently, -finfo-table-map does not work with -fllvm. See #26435
- - - - -
3bf38c84 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Don't run T24726 on optimized ways
If optimizations are enabled, the rewrite rule just fires and -drule-check will report nothing.
- - - - -
e4eef116 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Use -fno-unoptimized-core-for-interpreter when running LinkableUsage01/02
Optimizations for the bytecode interpreter are considered experimental, and need a flag to be enabled.
- - - - -
234a9872 by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Suppress unwanted optimizations on T25284
- - - - -
99a2af2f by ARATA Mizuki at 2026-07-01T10:34:03-04:00
testsuite: Don't run stack_big_ret with optimizations
Stack layout may change with optimizations enabled.
- - - - -
04c836df by ARATA Mizuki at 2026-07-01T10:34:04-04:00
testsuite: Mark memo001 broken on optimized ways
See #27396
- - - - -
1a8a24f4 by ARATA Mizuki at 2026-07-01T10:34:04-04:00
testsuite: Mark syn-perf broken on optimized ways
See #27398
- - - - -
40412093 by Duncan Coutts at 2026-07-01T10:34:50-04:00
Add a test for thread scheduler fairness
It also tests that the interval timer and context switching works.
We also test that fairness is lost when the context switching interval
is too coarse for the duration of the test.
We add this test before doing surgery on the interval timer, so we have
decent coverage.
- - - - -
3f34d557 by Duncan Coutts at 2026-07-01T10:34:50-04:00
Make exported stop/startTimer no-ops, and rename internal functions
Specifically, internally rename:
stop/startTimer to pause/unpauseTimer
stop/startTicker to pause/unpauseTicker
and keep stop/startTimer as exported functions, but now as no-ops.
In the past the stop/startTicker actions were used incorrectly as if
they were synchronous, which they are not. See issue #27105. We now
document pause/unpackTicker as being async and not to be used for the
purpose of concurrency safety.
The existing stop/startTimer (note Timer not Ticker, the Timer calls the
Ticker!) are also exported from the RTS as a public API. This was
historically because the ticker used signals and it was important to
suspend the timer signel over a process fork. So these functions were
exported to be used by the process and unix libraries.
We cannot just remove the RTS exports, but we now make them no-ops, and
they can be removed from the process and unix library later. This
was already documented in a changelog.d entry no-more-timer-signal but
due to changes during the MR process the change to make stop/startTicker
into no-ops didn't make it into the earlier MR.
- - - - -
02e84e5f by Duncan Coutts at 2026-07-01T10:34:51-04:00
Make exitTicker/exitTimer unconditionally synchronous
We never use them asynchronously, and we should never need to do so.
And update some related comments.
- - - - -
13db6a72 by Duncan Coutts at 2026-07-01T10:34:51-04:00
posix ticker: update and improve comments on (un)pause and exit
Clarify what is async vs sync.
- - - - -
43d9a07d by Duncan Coutts at 2026-07-01T10:34:51-04:00
posix ticker: split out ppoll/select helper functions
Move the #ifdefs out of the main code body by introducing local helper
functions and types, which themselves have two implementations (with a
common API) based on ppoll or select.
This helps improve clarity/readability.
- - - - -
a5491baa by Duncan Coutts at 2026-07-01T10:34:51-04:00
posix ticker: improve the implementation
The existing implementation supported pausing and exiting, with the
implementation of pausing reling on a mutex and condition variable.
It needed to check the pause and stop shared variables on every
iteration. It relies on ppoll or select, to wait on the timeout and also
wait on an interrupt fd. The interrupt fd was only used for prompt
exit/shutdown, and not for pausing or other notification. The pause only
needed a lock and a memory operation, but the pause was not prompt. The
resume used a lock, and signaling a cond var.
The new implementation uses a somewhat more regular design: every
notification is done by setting a shared variable and
interrupting/notifying the ticker via the fd. The ticker thread does not
need to check any shared variables on normal timer expiry, only when it
recevies notification. This may be a micro-optimisation, but the tick
occurs 100 times a second by default so any improvements in the hot path
are amplified. When the ticker thread does receive notification it can
check the various shared variables and update its local state. The
blocking relies on using ppoll/select but without a timeout. This avoids
the condition var and also allows further notifications when paused
(also used for unpausing).
This design can be extended with further notification types if needed by
using and checking further shared vars (or making existing shared vars
an enum or counter). This may be used in future for additional
notifications to the ticker thread. This will likely be used to proxy
wakeUpRts from a single handler context for example. And this approach,
avoiding mutexes, is compatible with use from signal handlers.
So overall, it's:
* slightly simpler / more regular;
* easier to extend with additional notifications;
* probably slightly more efficient (but a micro-optimisation);
* and supports calling notification from signal handlers
- - - - -
5b20821e by Duncan Coutts at 2026-07-01T10:34:51-04:00
posix ticker: further minor local renaming for code clarity
Improve the clarity with better choice of names for several local vars
and function.
- - - - -
1f3ec5e0 by Duncan Coutts at 2026-07-01T10:34:51-04:00
win32 ticker: split out local helper functions
- - - - -
596e7307 by Duncan Coutts at 2026-07-01T10:34:51-04:00
win32 ticker: provide guarantee about concurrency and idempotency
Use a lock to ensure pause/unpause can be used concurrently. Use a
paused variable, protected by the lock, to ensure that pause and unpause
are both idempotent. This is what the portable API expects.
- - - - -
1870edd7 by Duncan Coutts at 2026-07-01T10:34:51-04:00
win32 ticker: make the initial tick be after one wait interval
There is no need to tick immediately. This is consistent with the
posix implementation.
- - - - -
7c15ab5b by Duncan Coutts at 2026-07-01T10:34:51-04:00
ticker: remove now-unnecessary layer of enable/disable
There was an atomic variable used to block *part* of the actions of the
tick handler. This still did not make stopTimer synchronous, even for
the part of the the handle_tick actions it covered. It also added a more
expensive (sequentuially consistent) atomic operation in the hot path
for the handle_tick action, whereas our new design requires no atomic
ops at all.
Now that we have eliminate the need for synchronous stop/startTicker,
we don't need this not-quite-working-anyway atomic protocol. The new
pause/unpauseTicker is explicitly asynchronous and idempotent.
- - - - -
8585f8cb by Duncan Coutts at 2026-07-01T10:34:51-04:00
ticker: add TODOs about issue #27250: too much being done from handle_tick
The handle_tick should not perform I/O, block, perform long-running
operations or call arbitrary user code. Unfortunately, everything to
do with the eventlog (at the moment) falls into all those categories.
- - - - -
6e381626 by Duncan Coutts at 2026-07-01T22:29:55+01:00
Adjust releaseCapability_ precondition to allow cap->running_task == NULL
There are two use cases for releaseCapability_:
1. The current Task (cap->running_task) releases the Capability.
The Capability is marked free, and if there is any work to do,
an appropriate Task is woken up.
2. There is no current task (cap->task == NULL), and thus the
Capability is idle, and we want to wake up an idle Task to animate
the Capability. This case uses always_wakeup.
Currently, the precondition for releaseCapability_ is
cap->running_task != NULL
and so the 2nd use cases have to set cap->running_task (which is then
immediately overwritten) just to satisfy the precondition. See the
use cases in sendMessage and prodCapability.
So we can relax the precondition to be:
cap->running_task != NULL || always_wakeup
so that in the always_wakeup case, we say it is ok for the
cap->running_task to be NULL.
This lets us simplify sendMessage and prodCapability. In particular it
will allow prodCapability to not need a Task parameter.
The ulterior motive for all this is that I want to be able to call
prodCapability from an OS thread that is not itself a Task, in persuit
of issue #27086: disentangle I/O managers from wakeUpRts. The most
straightforward way to wake the RTS is using prodCapability, but the
context in which we will need to do that are threads that are not Tasks.
- - - - -
89404ebc by Duncan Coutts at 2026-07-01T22:29:55+01:00
prodCapability no longer needs to take a Task param
Now that releaseCapability_ can accept cap->running_task == NULL then it
is no longer necessary for prodCapability to require a Task.
- - - - -
4e60c5f6 by Duncan Coutts at 2026-07-01T22:29:56+01:00
Define prodOneCapability
There was an existing declaration for this in the header file, but no
definition.
Similarly, there is a declaration for prodAllCapabilities but no
definition, and we don't need it, so remove the declaration.
- - - - -
2527026f by Duncan Coutts at 2026-07-01T22:29:56+01:00
Add a wakeUpRtsViaTicker feature to the posix ticker
It proxies a call to wakeUpRts, but crucially, this can be called from
a signal handler context. It will be used for ctl-c handling.
- - - - -
aa5a03a5 by Duncan Coutts at 2026-07-01T22:29:56+01:00
Change how wakeUpRts works
Previously it would call wakeupIOManager to get a capability to wake up
and run. This works but it entangles the I/O managers with unrelated
features: ctl-c handling and idle gc (the two features that use wakeUpRts).
The reason it used wakeupIOManager is that this action is safe to use
from a posix signal handler, since it just posts bytes to a pipe.
Otherwise the more direct approach (used e.g. by sendMessage when the
target capability is idle) is to use releaseCapability. But that uses
condition variables and mutexes, which are not safe to use from within a
signal handler.
So instead of entangling the (multiple) I/O managers with this, we make
wakeUpRts use the direct approach (using prodOneCapability). On win32
the ctl-c console handler can call wakeUpRts directly, since it is
called in a proper thread. On posix, to deal with the signal handler
problem, we make the signal handler ask the ticker thread to proxy the
call to wakeUpRts, since the ticker thread is also a proper thread.
This will allow the I/O managers to no longer be concerned with this.
This is good because there are many I/O managers (and they're
complicated), but there is (on posix) only one ticker implementation. So
this is an overall reduction in coupling and complexity.
Fixes issue #27086
- - - - -
c6d53c16 by sheaf at 2026-07-02T21:35:44-04:00
Test driver: normalise line numbers into libraries
When comparing the stdout of tests that print out callstacks, we can't
rely on the stability of exact line:column spans pointing into libraries
(e.g. ghc-internal), as any change (such as adding a comment) can change
them.
This commit addresses this by normalising away line:column in callstacks,
but only when those point into internal libraries. We don't do this in
general, as the exact span might be important to the test (e.g. for a
span within the test module itself).
Fixes #27387
- - - - -
81ee62e0 by Alan Zimmerman at 2026-07-02T21:36:33-04:00
EPA: Remove LocatedLW from MatchGroup
This is the last usage of LocatedLW / SrcSpanAnnLW
- - - - -
925959db by Recursion Ninja at 2026-07-04T04:14:12-04:00
Decoupling 'L.H.S' from 'GHC.Hs.Doc'
* Migrated 'GHC.Hs.Doc' and 'GHC.Hs.DocString' AST defintions from 'GHC.*' namespace,
to new 'Language.Haskell.Syntax.Doc' module in the 'L.H.S' "namespace."
* Updated 'HsDocString to be TTG-parameterised as 'HsDocString pass'.
* Added 'GHC.Hs.Extension.Pass': splits 'GhcPass'/'Pass' and all 'HsDocString'
TTG instances out of 'GHC.Hs.Extension', which re-exports it unchanged
(this is backwards compatible and prevents the introduction of a boot file).
* Deleted 'GHC.Hs.Doc.hs-boot'; removed all 'L.H.S.*' imports of 'GHC.Hs.Doc'.
* Updated 'GHC.Hs.DocString' to be TTG pass-parameterised throughout; moved
'mkHsDocStringChunk'/'unpackHDSC' here (require 'GHC.Utils.Encoding').
* Split 'GHC.Rename.Doc.rnHsDoc' from 'rnHsDocIdentifiersOnly'.
* Updated parser, renamer, typechecker, HIE, and exact-print for new types.
* Added 'HsDocString' TTG instances for 'DocNameI' to 'Haddock.Types'.
* Killed the last module loop between GHC.* and LHS.*.
- Only edges from LHS.* to GHC.Data.FastString now!
Resolves #26971
- - - - -
b7e24044 by mangoiv at 2026-07-04T04:14:56-04:00
ci: retry fetching test metrics
Retry fetching test metrics to make the CI not fail if the services is
temporarily unavailable
- - - - -
4180af3f by Zubin Duggal at 2026-07-04T04:15:38-04:00
Bump semaphore-compat submodule to 2.0.1
This versions includes some cruicial fixes for darwin
- - - - -
242d4317 by sheaf at 2026-07-04T04:16:19-04:00
Remove outdated comment in GHC.Data.ShortText
There was a long comment in GHC.Data.ShortText about a workaround that
was necessary when bootstrapping with GHC 9.2 and below. The actual
logic has since been dropped, but the comment remained. This commit
removes the vestigial comment.
- - - - -
9b714c4c by Zubin Duggal at 2026-07-05T09:40:36+05:30
CorePrep: Don't speculatively evaluate bindings that we have already discovered to be absent
In #25924, we segfault because speculation forces a projection out of a RUBBISH dictionary
(which we generated because it absent).
Solution: Don't speculate on bindings we already know are absent.
Fixes 25924
- - - - -
4a59b3ee by Zubin Duggal at 2026-07-05T09:40:36+05:30
Don't make absent fillers for terminating types
In #25924 we discovered that we could speculatively evaluate an absent filler
for a dictionary, and project a field (a superclass selector) out of it,
resulting in segfaults.
Solution: Never make an absent filler or rubbish literal for a terminating type
like a dictionary. mkAbsentFiller returns Nothing for isTerminatingType, so
worker/wrapper and the specialiser keep the real argument instead.
Some small metric decreases because we do a little less work in the
simplifier now.
Metric Decrease:
T9872a
T9872b
T9872c
TcPlugin_RewritePerf
- - - - -
383ddcd4 by Alan Zimmerman at 2026-07-06T07:08:16-04:00
EPA: Move the 'where' annotation for PatSynBind
This allows us to move it out of the MatchGroup exact print annotation
too
- - - - -
66d1a5d5 by fendor at 2026-07-07T16:57:56-04:00
Add 'backendInfoTableMapValidity' backend predicate
Check whether the backend supports the `-finfo-table-map` flag and
ignore it otherwise.
Improve by-design documentation of `backendCodeOutput`.
`Backend` is **abstract by design**. Make this clearer in
`backendCodeOutput` which is incorrectly being used as a proxy for
`Backend`.
Instead, define the desired property predicates in GHC.Driver.Backend
In the process, make `backendCodeOutput` total.
- - - - -
74f1071d by fendor at 2026-07-07T16:57:56-04:00
Add failing test for `-finfo-table-map` and bytecode backend
If you compile a module using the bytecode backend, with
-finfo-table-map, then the info table map doesn't get populated for the
module.
This is because the -finfo-table-map code path is implemented mostly in
the StgToCmm phase which isn't run when creating bytecode.
Ticket #27039
- - - - -
28d63bca by mangoiv at 2026-07-07T16:59:16-04:00
ci: don't fail nightly if there have been no changes that night
Fixes #27127
- - - - -
4ebfc478 by Rodrigo Mesquita at 2026-07-08T04:47:53-04:00
ttg: Using ShortText over FastString in the AST
To make the AST independent of GHC, this commit replaces usages of
`FastString` with `HText` in the AST, killing the last edge from
Language.Haskell.* to GHC.* modules.
Even though we /do/ want to use FastStrings in general -- critically in
Names or Ids -- there is no particular reason for the FastStrings that
occur in the AST proper to be FastStrings. Strings in the AST are
typically unique and don't benefit particularly from being interned
FastStrings with Uniques for fast comparison.
`HText` is a type synonym for `ShortText` which uses GHC's Modified
UTF-8 encoding exclusively.
Modified UTF-8 must be used to represent the Haskell AST because the
Haskell Report allows surrogate code points. `Data.Text.Text` functions
use Standard UTF-8 which replace surrogates with a placeholder value,
thus `Data.Text.Text` is unsuitable for AST strings. See the
`Language.Haskell.Syntax.Text` module header for more details.
Final progress towards #21592
Closes #21628
- - - - -
d910b353 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00
Update equality-type documenation in GHC.Builtin.Types.Prim
Fix #27466
- - - - -
b2530542 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00
Honour -dsuppress-coercions in GHC.Core.TyCo.pprCo
Fixes #27467
- - - - -
9a73179a by Facundo Domínguez at 2026-07-08T04:49:26-04:00
Add item to MR checklist asking to squash fixup commits after approval
The checklist has an item that reads
All commits are either individually buildable or squashed.
This item could be checked immediately after sending the merge request
though. If reviewers ask for amends later on, and the author amends
the merge request, there was no item that would remind the contributors
to squash the fixup commits before landing.
This commit adds a new item
After all approvals and before landing: all fixup commits are squashed with their originating commits.
which should be harder to mark as done before approvals have been given.
- - - - -
1e8d118c by Simon Jakobi at 2026-07-08T13:01:38+02:00
NCG: optimize loopInfo.mkDomMap
Previously, mkDomMap built an intermediate association list with (++)
and a recursive concatMap before handing it to mapFromList. The
concatMap re-copied each node's list once per ancestor, so the work was
O(n^2) in the depth of the dominator tree.
The new code builds the LabelMap directly, with one mapInsert per
dominator-tree node, so each node is handled once.
This reduces allocation when compiling the new ManyBasicBlocks test by
~27% at -O1 and -O2. (At -O0, static control-flow prediction is
disabled.)
This also fixes a small inconsistency: previously a leaf of the
dominator tree included itself in its dominator set, while interior
nodes did not. The map is consumed only by isBackEdge, so the only
observable effect was that a self-loop edge was treated as a back edge
iff its block was a dominator-tree leaf. domMap now holds each block's
strict dominators, excluding the entry.
Closes #27448
Assisted-by: Claude Opus 4.8
- - - - -
325 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- .gitlab/merge_request_templates/Default.md
- .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
- .gitlab/test-metrics.sh
- + changelog.d/AbstractQ
- + changelog.d/T21628
- + changelog.d/add_can_drop_to_occurence_analyser
- + changelog.d/fix-absent-dict-projection
- + changelog.d/fix-compacting-gc-ap-27434
- + changelog.d/fix-layout-stack-fcall
- + changelog.d/fix-unreg
- + changelog.d/generically-mconcat
- + changelog.d/remove-ddump-json-flag
- changelog.d/semaphore-v2
- compiler/GHC/Builtin/Types/Prim.hs
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Cmm/CLabel.hs
- compiler/GHC/Cmm/LayoutStack.hs
- compiler/GHC/CmmToAsm/CFG.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Data/IOEnv.hs
- compiler/GHC/Data/StringBuffer.hs
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/CodeOutput.hs
- compiler/GHC/Driver/Config.hs
- compiler/GHC/Driver/Errors.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main/Compile.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Doc.hs
- − compiler/GHC/Hs/Doc.hs-boot
- compiler/GHC/Hs/DocString.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Extension.hs
- + compiler/GHC/Hs/Extension/Pass.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/HsToCore/Foreign/JavaScript.hs
- compiler/GHC/HsToCore/Foreign/Wasm.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Warnings.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Parser/Types.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Doc.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Lit.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Foreign.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToJS/FFI.hs
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Errors/Hole/FitTypes.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Arrow.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Do.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Gen/Splice.hs-boot
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Error.hs
- − compiler/GHC/Types/Error.hs-boot
- compiler/GHC/Types/FieldLabel.hs
- compiler/GHC/Types/ForeignCall.hs
- compiler/GHC/Types/Literal.hs
- compiler/GHC/Types/PkgQual.hs
- compiler/GHC/Types/SourceError.hs
- compiler/GHC/Types/SourceText.hs
- compiler/GHC/Unit/Module/Env.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Error.hs
- compiler/GHC/Utils/Logger.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/Language/Haskell/Syntax.hs
- compiler/Language/Haskell/Syntax/Basic.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Binds/InlinePragma.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- + compiler/Language/Haskell/Syntax/Doc.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Expr.hs-boot
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/ImpExp.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- + compiler/Language/Haskell/Syntax/Text.hs
- compiler/Language/Haskell/Syntax/Type.hs
- − compiler/Language/Haskell/Syntax/Type.hs-boot
- compiler/ghc.cabal.in
- docs/users_guide/debugging.rst
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Exception.hs
- hadrian/src/Flavour.hs
- hadrian/src/Settings/Warnings.hs
- libraries/base/changelog.md
- libraries/base/tests/all.T
- libraries/ghc-boot/GHC/Data/ShortText.hs
- libraries/ghc-heap/tests/all.T
- libraries/ghc-internal/src/GHC/Internal/Generics.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
- libraries/ghci/GHCi/TH.hs
- libraries/semaphore-compat
- libraries/template-haskell/Language/Haskell/TH/Syntax.hs
- rts/Capability.c
- rts/Capability.h
- rts/Messages.c
- rts/RtsStartup.c
- rts/Schedule.c
- rts/Ticker.h
- rts/Timer.c
- rts/Timer.h
- rts/include/rts/NonMoving.h
- rts/include/rts/Timer.h
- rts/include/stg/MiscClosures.h
- rts/posix/Ticker.c
- rts/sm/Compact.c
- rts/sm/GC.c
- rts/win32/Ticker.c
- testsuite/driver/testlib.py
- testsuite/tests/arityanal/should_compile/T21755.stderr
- testsuite/tests/arityanal/should_compile/all.T
- testsuite/tests/bytecode/TLinkable/all.T
- testsuite/tests/cmm/should_compile/all.T
- + testsuite/tests/cmm/should_run/T27447.hs
- + testsuite/tests/cmm/should_run/T27447.stdout
- + testsuite/tests/cmm/should_run/T27447_cmm.cmm
- testsuite/tests/cmm/should_run/all.T
- testsuite/tests/codeGen/should_compile/T25177.stderr
- + testsuite/tests/concurrent/should_run/T27105.hs
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/core-to-stg/T25284/Cls.hs
- + testsuite/tests/core-to-stg/T25924/B.hs
- + testsuite/tests/core-to-stg/T25924/Main.hs
- + testsuite/tests/core-to-stg/T25924/all.T
- + testsuite/tests/core-to-stg/T25924a.hs
- + testsuite/tests/core-to-stg/T25924a.stdout
- testsuite/tests/core-to-stg/all.T
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/deSugar/should_fail/all.T
- testsuite/tests/deSugar/should_run/all.T
- testsuite/tests/deriving/should_compile/all.T
- testsuite/tests/dmdanal/should_compile/T18982.stderr
- testsuite/tests/driver/T16167.stderr
- − testsuite/tests/driver/T16167.stdout
- testsuite/tests/driver/all.T
- testsuite/tests/driver/json2.stderr
- − testsuite/tests/driver/json_dump.hs
- − testsuite/tests/driver/json_dump.stderr
- testsuite/tests/driver/options_ghc/Mod_fbyte_code.hs
- testsuite/tests/driver/options_ghc/all.T
- testsuite/tests/driver/options_ghc/options_ghc_fbyte-code.stderr
- testsuite/tests/generics/GenDerivOutput.hs
- testsuite/tests/generics/GenDerivOutput1_0.hs
- testsuite/tests/generics/GenDerivOutput1_1.hs
- testsuite/tests/generics/T10604/T10604_deriving.hs
- testsuite/tests/generics/T10604/all.T
- + testsuite/tests/generics/T27245.hs
- + testsuite/tests/generics/T27245.stdout
- testsuite/tests/generics/all.T
- testsuite/tests/ghc-api/T25121_status.stdout
- + testsuite/tests/ghc-api/T27240.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-api/annotations-literals/literals.stdout
- testsuite/tests/ghc-api/annotations-literals/parsed.hs
- testsuite/tests/ghc-api/exactprint/T22919.stderr
- testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr
- testsuite/tests/ghci/scripts/all.T
- + testsuite/tests/ghci/scripts/bytecodeIPE.hs
- + testsuite/tests/ghci/scripts/bytecodeIPE.script
- + testsuite/tests/ghci/scripts/bytecodeIPE.stdout
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T24221.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- testsuite/tests/module/mod185.stderr
- testsuite/tests/numeric/should_compile/T15547.stderr
- testsuite/tests/overloadedrecflds/should_compile/DRFPatSynExport.stdout
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T15279.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/parser/should_compile/T20718.stderr
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/parser/should_compile/T23315/T23315.stderr
- testsuite/tests/parser/should_compile/all.T
- + testsuite/tests/parser/should_run/StringStartsWithNull.hs
- + testsuite/tests/parser/should_run/StringStartsWithNull.stdout
- testsuite/tests/parser/should_run/all.T
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/perf/compiler/genManyBasicBlocks
- testsuite/tests/perf/compiler/hard_hole_fits.stderr
- testsuite/tests/printer/T18052a.stderr
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- testsuite/tests/printer/all.T
- testsuite/tests/profiling/perf/T23103/all.T
- testsuite/tests/profiling/should_run/all.T
- testsuite/tests/rename/should_compile/T1792_imports.stdout
- testsuite/tests/rename/should_compile/T18264.stdout
- testsuite/tests/rename/should_compile/T4239.stdout
- testsuite/tests/rts/T17574.hs
- testsuite/tests/rts/T19381.hs
- + testsuite/tests/rts/T27434.hs
- + testsuite/tests/rts/T27434.stdout
- testsuite/tests/rts/all.T
- testsuite/tests/rts/ipe/T24005/all.T
- testsuite/tests/showIface/DocsInHiFile1.stdout
- testsuite/tests/showIface/DocsInHiFileTH.stdout
- testsuite/tests/showIface/HaddockSpanIssueT24378.stdout
- testsuite/tests/showIface/MagicHashInHaddocks.stdout
- testsuite/tests/showIface/NoExportList.stdout
- testsuite/tests/simplCore/should_compile/DataToTagFamilyScrut.stderr
- testsuite/tests/simplCore/should_compile/T14978.stdout
- testsuite/tests/simplCore/should_compile/T18013.stderr
- testsuite/tests/simplCore/should_compile/T24229a.stderr
- testsuite/tests/simplCore/should_compile/T24229b.stderr
- testsuite/tests/simplCore/should_compile/T26615.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Preprocess.hs
- utils/check-exact/Utils.hs
- utils/check-exact/check-exact.cabal
- utils/haddock/haddock-api/haddock-api.cabal
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
- utils/haddock/haddock-api/src/Haddock/Interface/LexParseRn.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
- utils/haddock/haddock-api/src/Haddock/InterfaceFile.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/29ba0c3b0cf354c1b08feadf40992b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/29ba0c3b0cf354c1b08feadf40992b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
08 Jul '26
Cheng Shao pushed to branch wip/fix-hadrian-hls at Glasgow Haskell Compiler / GHC
Commits:
d645779f by Cheng Shao at 2026-07-08T09:48:49+00:00
hadrian: fix HLS support
This patch fixes hadrian's HLS support so one can rely on HLS when
working on the hadrian codebase. Fixes #27480.
Not building/linking shared libraries for hadrian is a severely
premature optimization; this top-level setting in `cabal.project` only
affects home packages while the dependencies in the cabal store are
built with vanilla/dynamic anyway, and even adding dynamic builds to
home packages would not be costly due to cabal's usage of
`-dynamic-too`.
- - - - -
1 changed file:
- hadrian/cabal.project
Changes:
=====================================
hadrian/cabal.project
=====================================
@@ -12,7 +12,3 @@ index-state: 2026-03-10T17:36:36Z
-- and the Cabal takes nearly twice as long to build with -O1. See #16817.
package Cabal
optimization: False
-
--- Build static linked, vanilla libraries to reduce build time.
-shared: False
-executable-dynamic: False
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d645779f9c3c02a6feb34d0a7a6b083…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d645779f9c3c02a6feb34d0a7a6b083…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
08 Jul '26
Cheng Shao pushed new branch wip/fix-hadrian-hls at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/fix-hadrian-hls
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc] Pushed new branch wip/dcoutts/capability-yield
by Duncan Coutts (@dcoutts) 08 Jul '26
by Duncan Coutts (@dcoutts) 08 Jul '26
08 Jul '26
Duncan Coutts pushed new branch wip/dcoutts/capability-yield at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/dcoutts/capability-yield
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 6 commits: ttg: Using ShortText over FastString in the AST
by Marge Bot (@marge-bot) 08 Jul '26
by Marge Bot (@marge-bot) 08 Jul '26
08 Jul '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
4ebfc478 by Rodrigo Mesquita at 2026-07-08T04:47:53-04:00
ttg: Using ShortText over FastString in the AST
To make the AST independent of GHC, this commit replaces usages of
`FastString` with `HText` in the AST, killing the last edge from
Language.Haskell.* to GHC.* modules.
Even though we /do/ want to use FastStrings in general -- critically in
Names or Ids -- there is no particular reason for the FastStrings that
occur in the AST proper to be FastStrings. Strings in the AST are
typically unique and don't benefit particularly from being interned
FastStrings with Uniques for fast comparison.
`HText` is a type synonym for `ShortText` which uses GHC's Modified
UTF-8 encoding exclusively.
Modified UTF-8 must be used to represent the Haskell AST because the
Haskell Report allows surrogate code points. `Data.Text.Text` functions
use Standard UTF-8 which replace surrogates with a placeholder value,
thus `Data.Text.Text` is unsuitable for AST strings. See the
`Language.Haskell.Syntax.Text` module header for more details.
Final progress towards #21592
Closes #21628
- - - - -
d910b353 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00
Update equality-type documenation in GHC.Builtin.Types.Prim
Fix #27466
- - - - -
b2530542 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00
Honour -dsuppress-coercions in GHC.Core.TyCo.pprCo
Fixes #27467
- - - - -
9a73179a by Facundo Domínguez at 2026-07-08T04:49:26-04:00
Add item to MR checklist asking to squash fixup commits after approval
The checklist has an item that reads
All commits are either individually buildable or squashed.
This item could be checked immediately after sending the merge request
though. If reviewers ask for amends later on, and the author amends
the merge request, there was no item that would remind the contributors
to squash the fixup commits before landing.
This commit adds a new item
After all approvals and before landing: all fixup commits are squashed with their originating commits.
which should be harder to mark as done before approvals have been given.
- - - - -
ae9c944a by Andreas Klebinger at 2026-07-08T05:22:46-04:00
Fix a profiling race condition resulting in segfaults.
StgToCmm: Don't assume tagged FUN closures in closureCodeBody.
When entering a closure the self/node pointer might not be tagged in
some situations when a thunk is evaluated by multiple threads.
So we most AND away the tag bits rather than subtracting an expected tag.
Apply.cmm: Fix a race condition occuring when a thunk is mutated during GC.
In stg_ap_0_fast when might need to run GC before entering a thunk. If this happens
another thread or the GC itself might mutate the closure making entering it no longer
valid. We now check for this.
Add test and changelog for #27123 fixes.
- - - - -
59b6942d by Cheng Shao at 2026-07-08T05:22:47-04:00
ghc-heap: fix invalid srtlen returned by peekItbl when no-TNTC
This patch fixes the no-TNTC code path of `peekItbl` so that it looks
at the right memory address when reading the `srt` field from the
`StgInfoTable_` struct. Also adds a `T27465` regression test that
reproduces the bug on no-TNTC builds before the fix. Fixes #27465.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
118 changed files:
- .gitlab/merge_request_templates/Default.md
- + changelog.d/T21628
- + changelog.d/T27123.md
- + changelog.d/fix-peekitbl-no-tntc
- compiler/GHC/Builtin/Types/Prim.hs
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Cmm/CLabel.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Data/StringBuffer.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/HsToCore/Foreign/JavaScript.hs
- compiler/GHC/HsToCore/Foreign/Wasm.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Bind.hs
- compiler/GHC/StgToCmm/Foreign.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToJS/FFI.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Error.hs
- compiler/GHC/Types/FieldLabel.hs
- compiler/GHC/Types/ForeignCall.hs
- compiler/GHC/Types/Literal.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/Language/Haskell/Syntax/Basic.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- + compiler/Language/Haskell/Syntax/Text.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/ghc.cabal.in
- libraries/ghc-boot/GHC/Data/ShortText.hs
- + libraries/ghc-heap/tests/T27465.hs
- + libraries/ghc-heap/tests/T27465.stdout
- libraries/ghc-heap/tests/all.T
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTableProf.hsc
- rts/Apply.cmm
- testsuite/tests/codeGen/should_compile/T25177.stderr
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/ghc-api/annotations-literals/parsed.hs
- testsuite/tests/numeric/should_compile/T15547.stderr
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- + testsuite/tests/parser/should_run/StringStartsWithNull.hs
- + testsuite/tests/parser/should_run/StringStartsWithNull.stdout
- testsuite/tests/parser/should_run/all.T
- testsuite/tests/perf/compiler/hard_hole_fits.stderr
- + testsuite/tests/rts/T27123.hs
- testsuite/tests/rts/all.T
- testsuite/tests/simplCore/should_compile/DataToTagFamilyScrut.stderr
- testsuite/tests/simplCore/should_compile/T14978.stdout
- testsuite/tests/simplCore/should_compile/T18013.stderr
- testsuite/tests/simplCore/should_compile/T24229a.stderr
- testsuite/tests/simplCore/should_compile/T24229b.stderr
- utils/check-exact/ExactPrint.hs
- utils/check-exact/check-exact.cabal
- utils/haddock/haddock-api/haddock-api.cabal
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d990626ecd9d9c064519fed1fc94d2…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d990626ecd9d9c064519fed1fc94d2…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] Add item to MR checklist asking to squash fixup commits after approval
by Marge Bot (@marge-bot) 08 Jul '26
by Marge Bot (@marge-bot) 08 Jul '26
08 Jul '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
9a73179a by Facundo Domínguez at 2026-07-08T04:49:26-04:00
Add item to MR checklist asking to squash fixup commits after approval
The checklist has an item that reads
All commits are either individually buildable or squashed.
This item could be checked immediately after sending the merge request
though. If reviewers ask for amends later on, and the author amends
the merge request, there was no item that would remind the contributors
to squash the fixup commits before landing.
This commit adds a new item
After all approvals and before landing: all fixup commits are squashed with their originating commits.
which should be harder to mark as done before approvals have been given.
- - - - -
1 changed file:
- .gitlab/merge_request_templates/Default.md
Changes:
=====================================
.gitlab/merge_request_templates/Default.md
=====================================
@@ -27,6 +27,7 @@ https://gitlab.haskell.org/ghc/ghc/-/wikis/Contributing-a-Patch
- [ ] If this MR has the potential to break user programs, the ~"user-facing" label was applied to
test against head.hackage.
- [ ] All commits are either individually buildable or squashed.
+- [ ] After all approvals and before landing: all fixup commits are squashed with their originating commits.
- [ ] Commit messages describe *what they do*, referring to tickets using `#NNNNN` syntax.
- [ ] Source comments describing the change were added. For larger changes [notes][notes] and
cross-references from the relevant places were added (as applicable).
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9a73179ad3244d0bc00f84c61cda90e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9a73179ad3244d0bc00f84c61cda90e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] 2 commits: Update equality-type documenation in GHC.Builtin.Types.Prim
by Marge Bot (@marge-bot) 08 Jul '26
by Marge Bot (@marge-bot) 08 Jul '26
08 Jul '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
d910b353 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00
Update equality-type documenation in GHC.Builtin.Types.Prim
Fix #27466
- - - - -
b2530542 by Simon Peyton Jones at 2026-07-08T04:48:36-04:00
Honour -dsuppress-coercions in GHC.Core.TyCo.pprCo
Fixes #27467
- - - - -
11 changed files:
- compiler/GHC/Builtin/Types/Prim.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- testsuite/tests/codeGen/should_compile/T25177.stderr
- testsuite/tests/numeric/should_compile/T15547.stderr
- testsuite/tests/simplCore/should_compile/DataToTagFamilyScrut.stderr
- testsuite/tests/simplCore/should_compile/T14978.stdout
- testsuite/tests/simplCore/should_compile/T18013.stderr
- testsuite/tests/simplCore/should_compile/T24229a.stderr
- testsuite/tests/simplCore/should_compile/T24229b.stderr
Changes:
=====================================
compiler/GHC/Builtin/Types/Prim.hs
=====================================
@@ -1002,26 +1002,29 @@ doublePrimTyCon = pcPrimTyCon0 doublePrimTyConName doubleRepDataConTy
Note [The equality types story]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-GHC sports a veritable menagerie of equality types:
-
- Type or Lifted? Hetero? Role Built in Defining module
- class? L/U TyCon
------------------------------------------------------------------------------------------
-~# T U hetero nominal eqPrimTyCon GHC.Prim
-~~ C L hetero nominal heqTyCon GHC.Types
-~ C L homo nominal eqTyCon GHC.Types
-:~: T L homo nominal (not built-in) Data.Type.Equality
-:~~: T L hetero nominal (not built-in) Data.Type.Equality
-
-~R# T U hetero repr eqReprPrimTy GHC.Prim
-Coercible C L homo repr coercibleTyCon GHC.Types
-Coercion T L homo repr (not built-in) Data.Type.Coercion
-~P# T U hetero phantom eqPhantPrimTyCon GHC.Prim
+GHC sports a veritable menagerie of equality types.
+
+ Result kind Hetero? Role Built in Defining module
+---------------------------------------------------------------------------------
+~# Constraint# hetero nominal eqPrimTyCon GHC.Prim
+~~ Constraint hetero nominal heqTyCon GHC.Types
+~ Constraint homo nominal eqTyCon GHC.Types
+:~: Type homo nominal (not built-in) Data.Type.Equality
+:~~: Type hetero nominal (not built-in) Data.Type.Equality
+
+~R# Constraint# hetero repr eqReprPrimTy GHC.Prim
+Coercible Constraint homo repr coercibleTyCon GHC.Types
+Coercion Type homo repr (not built-in) Data.Type.Coercion
+~P# Constraint# hetero phantom eqPhantPrimTyCon GHC.Prim
+
+Here `Constraint#` means `CONSTRAINT (TupleRep [])`, a constraint kind that is
+represented by a zero-width tuple.
Recall that "hetero" means the equality can related types of different
kinds. Knowing that (t1 ~# t2) or (t1 ~R# t2) or even that (t1 ~P# t2)
also means that (k1 ~# k2), where (t1 :: k1) and (t2 :: k2).
+
To produce less confusion for end users, when not dumping and without
-fprint-equality-relations, each of these groups is printed as the bottommost
listed equality. That is, (~#) and (~~) are both rendered as (~) in
@@ -1030,7 +1033,7 @@ error messages, and (~R#) is rendered as Coercible.
Let's take these one at a time:
--------------------------
- (~#) :: forall k1 k2. k1 -> k2 -> TYPE (TupleRep '[])
+ (~#) :: forall k1 k2. k1 -> k2 -> CONSTRAINT (TupleRep '[])
--------------------------
This is The Type Of Equality in GHC. It classifies nominal coercions.
This type is used in the solver for recording equality constraints.
@@ -1054,8 +1057,6 @@ This is (almost) an ordinary class, defined as if by
Here's what's unusual about it:
* We can't actually declare it that way because we don't have syntax for ~#.
- And ~# isn't a constraint, so even if we could write it, it wouldn't kind
- check.
* Users cannot write instances of it.
@@ -1112,7 +1113,7 @@ They are not defined within GHC at all.
--------------------------
- (~R#) :: forall k1 k2. k1 -> k2 -> TYPE (TupleRep '[])
+ (~R#) :: forall k1 k2. k1 -> k2 -> CONSTRAINT (TupleRep '[])
--------------------------
The is the representational analogue of ~#. This is the type of representational
equalities that the solver works on. All wanted constraints of this type are
@@ -1147,7 +1148,7 @@ within GHC at all.
--------------------------
- (~P#) :: forall k1 k2. k1 -> k2 -> TYPE (TupleRep '[])
+ (~P#) :: forall k1 k2. k1 -> k2 -> CONSTRAINT (TupleRep '[])
--------------------------
This is the phantom analogue of ~# and it is barely used at all.
(The solver has no idea about this one.) Here is the motivation:
=====================================
compiler/GHC/Core/Ppr.hs
=====================================
@@ -292,14 +292,14 @@ noParens :: SDoc -> SDoc
noParens pp = pp
pprOptCo :: Coercion -> SDoc
--- Print a coercion optionally; i.e. honouring -dsuppress-coercions
-pprOptCo co = sdocOption sdocSuppressCoercions $ \case
- True -> angleBrackets (text "Co:" <> int (coercionSize co)) <+> dcolon <+> co_type
- False -> parens $ sep [ppr co, dcolon <+> co_type]
- where
- co_type = sdocOption sdocSuppressCoercionTypes $ \case
- True -> ellipsis
- False -> ppr (coercionType co)
+-- Print a coercion with its type (unless suppressed by -dsuppress-coercion-types)
+-- Honour -dsuppress-coercions
+-- Placed here because it needs GHC.Core.Coercion.coercionType
+pprOptCo co = sdocOption sdocSuppressCoercionTypes $ \case
+ True -> pprParendCo co
+ False -> parens (sep [pprCo co, dcolon <+> pp_co_type])
+ where
+ pp_co_type = ppr (coercionType co)
ppr_id_occ :: (SDoc -> SDoc) -> Id -> SDoc
ppr_id_occ add_par id
=====================================
compiler/GHC/Core/TyCo/Ppr.hs
=====================================
@@ -132,8 +132,14 @@ tidyToIfaceTypeX env ty = toIfaceTypeX (mkVarSet free_tcvs) (tidyType env' ty)
------------
pprCo, pprParendCo :: Coercion -> SDoc
-pprCo co = getPprStyle $ \ sty -> pprIfaceCoercion (tidyToIfaceCoSty co sty)
-pprParendCo co = getPprStyle $ \ sty -> pprParendIfaceCoercion (tidyToIfaceCoSty co sty)
+-- Print a coercion without its type
+-- Honour -dsuppress-coercions
+pprCo co = sdocOption sdocSuppressCoercions $ \case
+ True -> angleBrackets (text "Co:" <> int (coercionSize co))
+ False -> getPprStyle $ \ sty -> pprIfaceCoercion (tidyToIfaceCoSty co sty)
+pprParendCo co = sdocOption sdocSuppressCoercions $ \case
+ True -> angleBrackets (text "Co:" <> int (coercionSize co))
+ False -> getPprStyle $ \ sty -> pprParendIfaceCoercion (tidyToIfaceCoSty co sty)
tidyToIfaceCoSty :: Coercion -> PprStyle -> IfaceCoercion
tidyToIfaceCoSty co sty
=====================================
compiler/GHC/Core/TyCo/Rep.hs
=====================================
@@ -1640,7 +1640,7 @@ Here,
co3 = UnivCo ProofIrrelProv Nominal (CoercionTy co1) (CoercionTy co2) [co5]
where
co5 :: (a1 ~# Bool) ~# (a2 ~# Bool)
- co5 = TyConAppCo Nominal (~#) [<Consraint#>, <Constraint#>, co4, <Bool>]
+ co5 = TyConAppCo Nominal (~#) [<Constraint#>, <Constraint#>, co4, <Bool>]
Note [The importance of tracking UnivCo dependencies]
=====================================
testsuite/tests/codeGen/should_compile/T25177.stderr
=====================================
@@ -11,7 +11,7 @@ lvl = foo d
bar1 = \ x eta -> case lvl of { W# ipv -> (# eta, () #) }
-bar = bar1 `cast` <Co:6> :: ...
+bar = bar1 `cast` <Co:6>
=====================================
testsuite/tests/numeric/should_compile/T15547.stderr
=====================================
@@ -5,25 +5,25 @@ Result size of Tidy Core
nat2Word#
= \ @n $dKnownNat p1 ->
- naturalToWord# ((natSing $dKnownNat) `cast` <Co:2> :: ...)
+ naturalToWord# ((natSing $dKnownNat) `cast` <Co:2>)
foo = \ ds -> 18##
fd
= \ @n $dKnownNat ds ->
- naturalToWord# ((natSing $dKnownNat) `cast` <Co:6> :: ...)
+ naturalToWord# ((natSing $dKnownNat) `cast` <Co:6>)
d = \ ds -> 3##
fm
= \ @n $dKnownNat ds ->
- naturalToWord# ((natSing $dKnownNat) `cast` <Co:8> :: ...)
+ naturalToWord# ((natSing $dKnownNat) `cast` <Co:8>)
m = \ ds -> 9##
fp
= \ @n $dKnownNat ds ->
- naturalToWord# ((natSing $dKnownNat) `cast` <Co:10> :: ...)
+ naturalToWord# ((natSing $dKnownNat) `cast` <Co:10>)
p = \ ds -> 512##
=====================================
testsuite/tests/simplCore/should_compile/DataToTagFamilyScrut.stderr
=====================================
@@ -5,7 +5,7 @@ Result size of Tidy Core
testFun
= \ @x v ->
- case v `cast` <Co:2> :: ... of {
+ case v `cast` <Co:2> of {
__DEFAULT -> 47#;
C0 ipv -> -3#;
C2 -> 13#;
=====================================
testsuite/tests/simplCore/should_compile/T14978.stdout
=====================================
@@ -1,2 +1,2 @@
foo :: Goof Int
-foo = T14978.Goof @Int @~<Co:1> :: Int GHC.Internal.Prim.~# Int
+foo = T14978.Goof @Int @~(<Co:1> :: Int GHC.Internal.Prim.~# Int)
=====================================
testsuite/tests/simplCore/should_compile/T18013.stderr
=====================================
@@ -161,11 +161,11 @@ T18013.$wmapMaybeRule
@s @(Maybe b) ww2 (GHC.Internal.Maybe.Nothing @b) #);
Just x ->
case ((wild s2 x)
- `cast` <Co:4> :: IO (Result s b)
- ~R# (GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
- -> (# GHC.Internal.Prim.State#
- GHC.Internal.Prim.RealWorld,
- Result s b #)))
+ `cast` (<Co:4>
+ :: IO (Result s b)
+ ~R# (GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
+ -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
+ Result s b #))))
s1
of
{ (# ipv, ipv1 #) ->
@@ -175,12 +175,13 @@ T18013.$wmapMaybeRule
}
}
})
- `cast` <Co:13> :: (s
- -> Maybe a
- -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
- -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
- Result s (Maybe b) #))
- ~R# (s -> Maybe a -> IO (Result s (Maybe b))))
+ `cast` (<Co:13>
+ :: (s
+ -> Maybe a
+ -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
+ -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
+ Result s (Maybe b) #))
+ ~R# (s -> Maybe a -> IO (Result s (Maybe b)))))
}
}
=====================================
testsuite/tests/simplCore/should_compile/T24229a.stderr
=====================================
@@ -15,8 +15,8 @@ foo
= \ @a ds ds1 ->
case ds of { I# ww ->
case ww of ds2 {
- __DEFAULT -> case ds1 `cast` <Co:4> :: ... of { (x, y) -> case foo_$s$wfoo (-# ds2 1#) y x of { (# ww1 #) -> Just ww1 } };
- 0# -> Just (ds1 `cast` <Co:4> :: ...)
+ __DEFAULT -> case ds1 `cast` <Co:4> of { (x, y) -> case foo_$s$wfoo (-# ds2 1#) y x of { (# ww1 #) -> Just ww1 } };
+ 0# -> Just (ds1 `cast` <Co:4>)
}
}
=====================================
testsuite/tests/simplCore/should_compile/T24229b.stderr
=====================================
@@ -15,8 +15,8 @@ foo
= \ @a ds ds1 ->
case ds of { I# ww ->
case ww of ds2 {
- __DEFAULT -> case ds1 `cast` <Co:4> :: ... of { (x, y) -> case foo_$s$wfoo (-# ds2 1#) y x of { (# ww1 #) -> Just ww1 } };
- 0# -> Just (ds1 `cast` <Co:4> :: ...)
+ __DEFAULT -> case ds1 `cast` <Co:4> of { (x, y) -> case foo_$s$wfoo (-# ds2 1#) y x of { (# ww1 #) -> Just ww1 } };
+ 0# -> Just (ds1 `cast` <Co:4>)
}
}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/4ebfc47842229a94a28c459806d9d8…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/4ebfc47842229a94a28c459806d9d8…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] ttg: Using ShortText over FastString in the AST
by Marge Bot (@marge-bot) 08 Jul '26
by Marge Bot (@marge-bot) 08 Jul '26
08 Jul '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
4ebfc478 by Rodrigo Mesquita at 2026-07-08T04:47:53-04:00
ttg: Using ShortText over FastString in the AST
To make the AST independent of GHC, this commit replaces usages of
`FastString` with `HText` in the AST, killing the last edge from
Language.Haskell.* to GHC.* modules.
Even though we /do/ want to use FastStrings in general -- critically in
Names or Ids -- there is no particular reason for the FastStrings that
occur in the AST proper to be FastStrings. Strings in the AST are
typically unique and don't benefit particularly from being interned
FastStrings with Uniques for fast comparison.
`HText` is a type synonym for `ShortText` which uses GHC's Modified
UTF-8 encoding exclusively.
Modified UTF-8 must be used to represent the Haskell AST because the
Haskell Report allows surrogate code points. `Data.Text.Text` functions
use Standard UTF-8 which replace surrogates with a placeholder value,
thus `Data.Text.Text` is unsuitable for AST strings. See the
`Language.Haskell.Syntax.Text` module header for more details.
Final progress towards #21592
Closes #21628
- - - - -
96 changed files:
- + changelog.d/T21628
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Cmm/CLabel.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Data/StringBuffer.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/HsToCore/Foreign/JavaScript.hs
- compiler/GHC/HsToCore/Foreign/Wasm.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Foreign.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToJS/FFI.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Error.hs
- compiler/GHC/Types/FieldLabel.hs
- compiler/GHC/Types/ForeignCall.hs
- compiler/GHC/Types/Literal.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/Language/Haskell/Syntax/Basic.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- + compiler/Language/Haskell/Syntax/Text.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/ghc.cabal.in
- libraries/ghc-boot/GHC/Data/ShortText.hs
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/ghc-api/annotations-literals/parsed.hs
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- + testsuite/tests/parser/should_run/StringStartsWithNull.hs
- + testsuite/tests/parser/should_run/StringStartsWithNull.stdout
- testsuite/tests/parser/should_run/all.T
- testsuite/tests/perf/compiler/hard_hole_fits.stderr
- utils/check-exact/ExactPrint.hs
- utils/check-exact/check-exact.cabal
- utils/haddock/haddock-api/haddock-api.cabal
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4ebfc47842229a94a28c459806d9d8b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4ebfc47842229a94a28c459806d9d8b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/junit-diffs] perf notes: include stat deviation and acceptance window in notes so they show up in gitlab
by Zubin (@wz1000) 08 Jul '26
by Zubin (@wz1000) 08 Jul '26
08 Jul '26
Zubin pushed to branch wip/junit-diffs at Glasgow Haskell Compiler / GHC
Commits:
b555b20b by Zubin Duggal at 2026-07-08T12:09:23+05:30
perf notes: include stat deviation and acceptance window in notes so they show up in gitlab
- - - - -
1 changed file:
- testsuite/driver/perf_notes.py
Changes:
=====================================
testsuite/driver/perf_notes.py
=====================================
@@ -653,7 +653,11 @@ def check_stats_change(actual: PerfStat,
error = str(change) + ' from ' + baseline.perfStat.test_env + \
' baseline @ %s' % baseline.commit
print(actual.metric, error + ':')
- result = failBecause('stat ' + error, tag='stat')
+ dev = 100.0 if expected_val == 0 else round(((float(actual.value) * 100) / int(expected_val)) - 100, 1)
+ change_line = (f'{actual.metric} {change.value} from {baseline.perfStat.test_env} '
+ f'baseline @ {baseline.commit[:7]}: {expected_val} -> {actual.value} '
+ f'({dev:+g}%, allowed {acceptance_window.describe()})')
+ result = failBecause('stat ' + change_line, tag='stat')
if not change_allowed or force_print:
length = max(len(str(x)) for x in [expected_val, lowerBound, upperBound, actual.value])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b555b20bb89ad38e8831810896bd3f7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b555b20bb89ad38e8831810896bd3f7…
You're receiving this email because of your account on gitlab.haskell.org.
1
0