[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 8 commits: testsuite: fix flaky foundation Divisible / mulIntMayOflo# tests (#27222)
by Marge Bot (@marge-bot) 05 May '26
by Marge Bot (@marge-bot) 05 May '26
05 May '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
5c4c3bf4 by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: fix flaky foundation Divisible / mulIntMayOflo# tests (#27222)
Since the LCG was widened to 64 bits and the seed randomised per CI run
(commit 2d30f7d3400 "Vendor mini-QuickCheck for testsuite"), two latent
bugs in the foundation test surface stochastically:
* The Divisible property `(x `div` y) * y + (x `mod` y) == x` raises
ArithException(Overflow) when (a, b) = (minBound, -1) for fixed-width
signed Integral types. Split testNumber/testDivisible into Bounded and
unbounded variants and skip just that one pair, gated by
`(minBound :: a) < 0` so unsigned types lose no coverage.
* The `mulIntMayOflo#` test compared raw Int# bit-for-bit, but the primop
is only specified to return 0/non-zero -- the exact non-zero indicator
legitimately differs between backends and inlining choices. Add a
dedicated `testPrimopMayOflo` helper that only compares zero / non-zero.
Also fix the long-standing typo "Dividible" -> "Divisible" in identifiers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
e242ce4f by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: catch and display exceptions in MiniQuickCheck
Exceptions raised while evaluating a property are now caught and reported
as a normal failure (with arguments and seed), instead of aborting the
test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
3b75cccd by fendor at 2026-05-02T03:40:14-04:00
Fix name of Note [Structure of dep_boot_mods]
- - - - -
a179e30b by Duncan Coutts at 2026-05-05T09:34:15-04:00
Use __attribute__((dllimport)) for external RTS symbol declarations
This is needed to be hygenic about DLL symbol imports and exports.
The attribute is ignored on platforms other than Windows.
Use of the attribute however means that external data symbols do not
have a compile-time constant address (they are loaded using an
indirection). This means we have to adjust the rtsSyms initial linker
table so that it is a local constant in a function, rather than a global
constant. We now define it within a function that pre-populates the
symbol table with the RTS symbols.
- - - - -
fdd26b00 by Duncan Coutts at 2026-05-05T09:34:15-04:00
Fix the rts linker declarations for a few data symbols
and ensure that the (windows only) rts_IOManagerIsWin32Native data
symbol is marked as externally visible.
- - - - -
1036f2ac by David Eichmann at 2026-05-05T09:34:15-04:00
Hadrian: Disable runtime pseudo relocations for RTS on windows hosts
- - - - -
6414bc49 by Teo Camarasu at 2026-05-05T09:34:16-04:00
ghci/TH: refactor to use IORef QState
This is a pure refactor and shouldn't modify semantics at all
- - - - -
bce22879 by Teo Camarasu at 2026-05-05T09:34:16-04:00
iserv: recover/getQ/putQ should behave same as internal interpreter
The internal and external interpreter should behave the same when
handling `recover`, the exeception recovery method of Q.
In practice, they diverge. In case of failure, the internal interpreter
only restores error message state to before the computation, wheras the
external interperter restores error message state *and* the state of putQ/getQ.
As far as I can tell this is a simple mistake in the implementation.
Note [TH recover with -fexternal-interpreter] describes the correct
behaviour but the implementation doesn't mirror this.
This change restores the correct behaviour by keeping the effects of
putQ in the erroring computation.
This is a breaking change since it modifies the behaviour of programs
that rely on recover ignoring putQ from failling computations when used
with the external interpreter. Although I highly doubt anyone relies on
this behaviour.
This divergence was first introduced in d00c308633fe7d216d31a1087e00e63532d87d6d.
As far as I can tell this was unintentional and tha commit was trying to solve a different bug.
Resolves #27022
- - - - -
16 changed files:
- + changelog.d/T27022
- compiler/GHC/Unit/Module/Deps.hs
- hadrian/src/Settings/Packages.hs
- libraries/ghci/GHCi/TH.hs
- rts/IOManager.h
- rts/Linker.c
- rts/LinkerInternals.h
- rts/RtsSymbols.c
- rts/RtsSymbols.h
- rts/linker/Elf.c
- testsuite/tests/MiniQuickCheck.hs
- testsuite/tests/linters/notes.stdout
- testsuite/tests/numeric/should_run/foundation.hs
- + testsuite/tests/th/T27022.hs
- + testsuite/tests/th/T27022.stdout
- testsuite/tests/th/all.T
Changes:
=====================================
changelog.d/T27022
=====================================
@@ -0,0 +1,11 @@
+section: compiler
+synopsis: Fix a divergence in the interaction between ``recover`` and ``putQ`` between the internal and external interpreter
+description: The ``recover`` method in TemplateHaskell now behaves the same
+ with the internal and external interpreter.
+ In the past, when an error was encountered in a computation in a ``recover`` block,
+ the external interpreter would discard any state changes from ``putQ``,
+ whereas the internal interpreter would not.
+ This was a long-standing error in the implementation of the external interpreter.
+ Both now keep state changes from ``putQ`` in ``recover`` blocks.
+mrs: !15994
+issues: #27022
=====================================
compiler/GHC/Unit/Module/Deps.hs
=====================================
@@ -96,7 +96,7 @@ data Dependencies = Deps
, dep_boot_mods_ :: Set (UnitId, ModuleNameWithIsBoot)
-- ^ All modules which have boot files below this one, and whether we
-- should use the boot file or not.
- -- This information is only used to populate the eps_is_boot field.
+ -- This information is only used to populate the 'eps_is_boot' field.
-- See Note [Structure of dep_boot_mods]
, dep_orphs_ :: [Module]
@@ -605,7 +605,7 @@ hash of the module. The export hash is computed in `GHC.Iface.Recomp.addFingerpr
-}
{-
-Note [Structure of dep_boot_deps]
+Note [Structure of dep_boot_mods]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In `-c` mode we always need to know whether to load the normal or boot version of
=====================================
hadrian/src/Settings/Packages.hs
=====================================
@@ -322,6 +322,7 @@ rtsPackageArgs = package rts ? do
, Profiling `wayUnit` way ? arg "-DPROFILING"
, Threaded `wayUnit` way ? arg "-DTHREADED_RTS"
, notM targetSupportsSMP ? arg "-optc-DNOSMP"
+ , isWinHost ? arg "-optl-Wl,--disable-runtime-pseudo-reloc"
-- See Note [AutoApply.cmm for vectors] in genapply/Main.hs
--
=====================================
libraries/ghci/GHCi/TH.hs
=====================================
@@ -119,7 +119,7 @@ initQState :: Pipe -> QState
initQState p = QState M.empty Nothing p
-- | The monad in which we run TH computations on the server
-newtype GHCiQ a = GHCiQ { runGHCiQ :: QState -> IO (a, QState) }
+newtype GHCiQ a = GHCiQ { runGHCiQ :: IORef QState -> IO a }
-- | The exception thrown by "fail" in the GHCiQ monad
data GHCiQException = GHCiQException QState String
@@ -128,52 +128,54 @@ data GHCiQException = GHCiQException QState String
instance Exception GHCiQException
instance Functor GHCiQ where
- fmap f (GHCiQ s) = GHCiQ $ fmap (\(x,s') -> (f x,s')) . s
+ fmap f (GHCiQ m) = GHCiQ $ fmap f . m
instance Applicative GHCiQ where
f <*> a = GHCiQ $ \s ->
- do (f',s') <- runGHCiQ f s
- (a',s'') <- runGHCiQ a s'
- return (f' a', s'')
- pure x = GHCiQ (\s -> return (x,s))
+ do f' <- runGHCiQ f s
+ a' <- runGHCiQ a s
+ return $ f' a'
+ pure x = GHCiQ $ \_ -> return x
instance Monad GHCiQ where
m >>= f = GHCiQ $ \s ->
- do (m', s') <- runGHCiQ m s
- (a, s'') <- runGHCiQ (f m') s'
- return (a, s'')
+ do m' <- runGHCiQ m s
+ a <- runGHCiQ (f m') s
+ return a
instance MonadFail GHCiQ where
- fail err = GHCiQ $ \s -> throwIO (GHCiQException s err)
+ fail err = GHCiQ $ \sRef -> readIORef sRef >>= \s -> throwIO (GHCiQException s err)
getState :: GHCiQ QState
-getState = GHCiQ $ \s -> return (s,s)
+getState = GHCiQ $ \sRef -> readIORef sRef
noLoc :: TH.Loc
noLoc = TH.Loc "<no file>" "<no package>" "<no module>" (0,0) (0,0)
-- | Send a 'THMessage' to GHC and return the result.
ghcCmd :: Binary a => THMessage (THResult a) -> GHCiQ a
-ghcCmd m = GHCiQ $ \s -> do
+ghcCmd m = GHCiQ $ \sRef -> do
+ s <- readIORef sRef
r <- remoteTHCall (qsPipe s) m
case r of
THException str -> throwIO (GHCiQException s str)
- THComplete res -> return (res, s)
+ THComplete res -> return res
instance MonadIO GHCiQ where
- liftIO m = GHCiQ $ \s -> fmap (,s) m
+ liftIO m = GHCiQ $ \_ -> m
instance TH.Quasi GHCiQ where
qNewName str = ghcCmd (NewName str)
qReport isError msg = ghcCmd (Report isError msg)
-- See Note [TH recover with -fexternal-interpreter] in GHC.Tc.Gen.Splice
- qRecover (GHCiQ h) a = GHCiQ $ \s -> mask $ \unmask -> do
+ qRecover (GHCiQ h) a = GHCiQ $ \sRef -> mask $ \unmask -> do
+ s <- readIORef sRef
remoteTHCall (qsPipe s) StartRecover
- e <- try $ unmask $ runGHCiQ (a <* ghcCmd FailIfErrs) s
+ e <- try $ unmask $ runGHCiQ (a <* ghcCmd FailIfErrs) sRef
remoteTHCall (qsPipe s) (EndRecover (isLeft e))
case e of
- Left GHCiQException{} -> h s
+ Left GHCiQException{} -> h sRef
Right r -> return r
qLookupName isType occ = ghcCmd (LookupName isType occ)
qReify name = ghcCmd (Reify name)
@@ -200,15 +202,16 @@ instance TH.Quasi GHCiQ where
qAddTempFile suffix = ghcCmd (AddTempFile suffix)
qAddTopDecls decls = ghcCmd (AddTopDecls decls)
qAddForeignFilePath lang fp = ghcCmd (AddForeignFilePath lang fp)
- qAddModFinalizer fin = GHCiQ (\s -> mkRemoteRef fin >>= return . (, s)) >>=
+ qAddModFinalizer fin = GHCiQ (\_ -> mkRemoteRef fin) >>=
ghcCmd . AddModFinalizer
qAddCorePlugin str = ghcCmd (AddCorePlugin str)
- qGetQ = GHCiQ $ \s ->
+ qGetQ = do
+ s <- getState
let lookup :: forall a. Typeable a => Map TypeRep Dynamic -> Maybe a
lookup m = fromDynamic =<< M.lookup (typeOf (undefined::a)) m
- in return (lookup (qsMap s), s)
- qPutQ k = GHCiQ $ \s ->
- return ((), s { qsMap = M.insert (typeOf k) (toDyn k) (qsMap s) })
+ return $ lookup (qsMap s)
+ qPutQ k = GHCiQ $ \sRef ->
+ modifyIORef' sRef (\s -> s { qsMap = M.insert (typeOf k) (toDyn k) (qsMap s) })
qIsExtEnabled x = ghcCmd (IsExtEnabled x)
qExtsEnabled = ghcCmd ExtsEnabled
qPutDoc l s = ghcCmd (PutDoc l s)
@@ -231,7 +234,8 @@ runModFinalizerRefs pipe rstate qrefs = do
qs <- mapM localRef qrefs
qstateref <- localRef rstate
qstate <- readIORef qstateref
- _ <- runGHCiQ (TH.runQ $ sequence_ qs) qstate { qsPipe = pipe }
+ qstate' <- newIORef $ qstate { qsPipe = pipe }
+ _ <- runGHCiQ (TH.runQ $ sequence_ qs) qstate'
return ()
-- | The implementation of the 'RunTH' message
@@ -267,8 +271,6 @@ runTHQ
-> IO ByteString
runTHQ pipe rstate mb_loc ghciq = do
qstateref <- localRef rstate
- qstate <- readIORef qstateref
- let st = qstate { qsLocation = mb_loc, qsPipe = pipe }
- (r,new_state) <- runGHCiQ (TH.runQ ghciq) st
- writeIORef qstateref new_state
+ modifyIORef' qstateref (\qstate -> qstate { qsLocation = mb_loc, qsPipe = pipe })
+ r <- runGHCiQ (TH.runQ ghciq) qstateref
return $! LB.toStrict (runPut (put r))
=====================================
rts/IOManager.h
=====================================
@@ -21,6 +21,15 @@
#include "sm/GC.h" // for evac_fn
+#if defined(mingw32_HOST_OS)
+/* Global var (only on Windows) that is exported (hence before BeginPrivate.h)
+ * to be shared with the I/O code in the base library to tell us which style
+ * of I/O manager we are using: one that uses the Windows native API HANDLEs,
+ * or one that uses Posix style fds.
+ */
+extern bool rts_IOManagerIsWin32Native;
+#endif
+
#include "BeginPrivate.h"
/* The ./configure gives us a set of CPP flags, one for each named I/O manager:
@@ -160,14 +169,6 @@ typedef enum {
/* Global var to tell us which I/O manager impl we are using */
extern IOManagerType iomgr_type;
-#if defined(mingw32_HOST_OS)
-/* Global var (only on Windows) that is exported to be shared with the I/O code
- * in the base library to tell us which style of I/O manager we are using: one
- * that uses the Windows native API HANDLEs, or one that uses Posix style fds.
- */
-extern bool rts_IOManagerIsWin32Native;
-#endif
-
/* The CapIOManager is the per-capability data structure belonging to the I/O
* manager. It is defined in full in IOManagerInternals.h. The opaque forward
=====================================
rts/Linker.c
=====================================
@@ -478,16 +478,7 @@ initLinker_ (int retain_cafs)
symhash = allocStrHashTable();
/* populate the symbol table with stuff from the RTS */
- IF_DEBUG(linker, debugBelch("populating linker symbol table with built-in RTS symbols\n"));
- for (const RtsSymbolVal *sym = rtsSyms; sym->lbl != NULL; sym++) {
- IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
- if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
- symhash, sym->lbl, sym->addr,
- sym->strength, sym->type, 0, NULL)) {
- barf("ghciInsertSymbolTable failed");
- }
- }
- IF_DEBUG(linker, debugBelch("done with built-in RTS symbols\n"));
+ initLinkerRtsSyms(symhash);
/* Add extra symbols. rtsExtraSyms() is a weakly defined symbol in the rts,
* that can be overrided by linking in an object with a corresponding
=====================================
rts/LinkerInternals.h
=====================================
@@ -502,4 +502,6 @@ ObjectCode* mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
void initSegment(Segment *s, void *start, size_t size, SegmentProt prot, int n_sections);
void freeSegments(ObjectCode *oc);
+void initLinkerRtsSyms(StrHashTable *symhash);
+
#include "EndPrivate.h"
=====================================
rts/RtsSymbols.c
=====================================
@@ -9,6 +9,8 @@
#include "ghcplatform.h"
#include "Rts.h"
#include "RtsSymbols.h"
+#include "LinkerInternals.h"
+#include "PathUtils.h"
#include "TopHandler.h"
#include "HsFFI.h"
@@ -51,6 +53,20 @@ extern char **environ;
/* -----------------------------------------------------------------------------
* Symbols to be inserted into the RTS symbol table.
+ *
+ * Note [Naming Scheme for Symbol Macros]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * SymI_*: symbol is internal to the RTS. It resides in an object
+ * file/library that is linked into the RTS library (as a static
+ * archive or dynamic shared library).
+ * SymE_*: symbol is external to the RTS library. It might be linked
+ * dynamically.
+ *
+ * Sym*_HasProto : the symbol prototype is imported in an include file
+ * or defined explicitly
+ * Sym*_NeedsProto: the symbol is undefined and we add a dummy
+ * default proto extern void sym(void);
*/
#define Maybe_Stable_Names SymI_HasProto(stg_mkWeakzh) \
@@ -162,7 +178,7 @@ extern char **environ;
SymI_HasProto(stg_asyncWritezh) \
SymI_HasProto(stg_asyncDoProczh) \
SymI_HasProto(rts_InstallConsoleEvent) \
- SymI_HasProto(rts_IOManagerIsWin32Native) \
+ SymI_HasDataProto(rts_IOManagerIsWin32Native) \
SymI_HasProto(rts_ConsoleHandlerDone) \
SymI_NeedsProto(__mingw_module_is_dll) \
RTS_WIN64_ONLY(SymI_NeedsProto(___chkstk_ms)) \
@@ -914,7 +930,7 @@ extern char **environ;
SymI_HasProto(freeExecPage) \
SymI_HasProto(getAllocations) \
SymI_HasProto(revertCAFs) \
- SymI_HasProto(RtsFlags) \
+ SymI_HasDataProto(RtsFlags) \
SymI_NeedsDataProto(rts_breakpoint_io_action) \
SymI_NeedsDataProto(rts_stop_next_breakpoint) \
SymI_NeedsDataProto(rts_stop_on_exception) \
@@ -925,9 +941,9 @@ extern char **environ;
SymI_NeedsProto(rts_enableStopAfterReturn) \
SymI_NeedsProto(rts_disableStopAfterReturn) \
SymI_HasProto(stopTimer) \
- SymI_HasProto(n_capabilities) \
- SymI_HasProto(max_n_capabilities) \
- SymI_HasProto(enabled_capabilities) \
+ SymI_HasDataProto(n_capabilities) \
+ SymI_HasDataProto(max_n_capabilities) \
+ SymI_HasDataProto(enabled_capabilities) \
SymI_HasDataProto(stg_traceEventzh) \
SymI_HasDataProto(stg_traceMarkerzh) \
SymI_HasDataProto(stg_traceBinaryEventzh) \
@@ -1145,12 +1161,27 @@ extern char **environ;
SymI_HasProto(hs_word2float64)
-/* entirely bogus claims about types of these symbols */
-#define SymI_NeedsProto(vvv) extern void vvv(void);
-#define SymI_NeedsDataProto(vvv) extern StgWord vvv[];
-#define SymE_NeedsProto(vvv) SymI_NeedsProto(vvv);
-#define SymE_NeedsDataProto(vvv) SymI_NeedsDataProto(vvv);
-#define SymE_HasProto(vvv) SymI_HasProto(vvv);
+/* Declare prototypes for the symbols that need it, so we can refer
+ * to them in the rtsSyms table below.
+ *
+ * In particular, for the external ones (SymE_*) we use the dllimport attribute
+ * to indicate that (on Windows) they come from external DLLs. This attribute
+ * is ignored on other platforms.
+ *
+ * The claims about the types of these symbols are entirely bogus.
+ */
+#if defined(mingw32_HOST_OS) && defined(DYNAMIC)
+#define DLLIMPORT __attribute__((dllimport))
+#else
+#define DLLIMPORT /**/
+#endif
+
+#define SymI_NeedsProto(vvv) extern void vvv(void);
+#define SymI_NeedsDataProto(vvv) extern StgWord vvv[];
+#define SymE_NeedsProto(vvv) extern DLLIMPORT void vvv(void);
+#define SymE_NeedsDataProto(vvv) extern DLLIMPORT StgWord vvv[];
+
+#define SymE_HasProto(vvv) /**/
#define SymI_HasProto(vvv) /**/
#define SymI_HasDataProto(vvv) /**/
#define SymI_HasProto_redirect(vvv,xxx,strength,ty) /**/
@@ -1179,6 +1210,8 @@ RTS_SYMBOLS_PRIM
#undef SymE_NeedsProto
#undef SymE_NeedsDataProto
+/* See Note [Naming Scheme for Symbol Macros] */
+
#define SymI_HasProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
(void*)(&(vvv)), STRENGTH_NORMAL, SYM_TYPE_CODE },
#define SymI_HasDataProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
@@ -1199,7 +1232,16 @@ RTS_SYMBOLS_PRIM
{ MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
(void*)(&(xxx)), strength, ty },
-RtsSymbolVal rtsSyms[] = {
+
+
+/* Initialize (if not already initialized) and return an array of symbols with stuff from the RTS. */
+void initLinkerRtsSyms (StrHashTable *symhash) {
+ /* The address of data symbols with the dllimport attribute are not
+ * compile-time constants and so cannot be used in constant initialisers.
+ * For this reason, rtsSyms is a local variable within this function
+ * rather than a global constant (as it was historically).
+ */
+ const RtsSymbolVal rtsSyms[] = {
RTS_SYMBOLS
RTS_RET_SYMBOLS
RTS_POSIX_ONLY_SYMBOLS
@@ -1214,7 +1256,20 @@ RtsSymbolVal rtsSyms[] = {
RTS_SYMBOLS_PRIM
SymI_HasDataProto(nonmoving_write_barrier_enabled)
{ 0, 0, STRENGTH_NORMAL, SYM_TYPE_CODE } /* sentinel */
-};
+ };
+
+ IF_DEBUG(linker, debugBelch("populating linker symbol table with built-in RTS symbols\n"));
+ for (const RtsSymbolVal *sym = rtsSyms; sym->lbl != NULL; sym++) {
+ IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
+ if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
+ symhash, sym->lbl, sym->addr,
+ sym->strength, sym->type, 0, NULL)) {
+ barf("ghciInsertSymbolTable failed");
+ }
+ }
+ IF_DEBUG(linker, debugBelch("done with built-in RTS symbols\n"));
+}
+
// Note [Extra RTS symbols]
=====================================
rts/RtsSymbols.h
=====================================
@@ -46,8 +46,6 @@ typedef struct _RtsSymbolVal {
SymType type;
} RtsSymbolVal;
-extern RtsSymbolVal rtsSyms[];
-
extern RtsSymbolVal* __attribute__((weak)) rtsExtraSyms(void);
/* See Note [_iob_func symbol]. */
=====================================
rts/linker/Elf.c
=====================================
@@ -76,18 +76,6 @@
*
* See bug #781
* See thread http://www.haskell.org/pipermail/cvs-ghc/2007-September/038458.html
- *
- * Naming Scheme for Symbol Macros
- *
- * SymI_*: symbol is internal to the RTS. It resides in an object
- * file/library that is statically.
- * SymE_*: symbol is external to the RTS library. It might be linked
- * dynamically.
- *
- * Sym*_HasProto : the symbol prototype is imported in an include file
- * or defined explicitly
- * Sym*_NeedsProto: the symbol is undefined and we add a dummy
- * default proto extern void sym(void);
*/
#define X86_64_ELF_NONPIC_HACK (!RtsFlags.MiscFlags.linkerAlwaysPic)
=====================================
testsuite/tests/MiniQuickCheck.hs
=====================================
@@ -2,6 +2,7 @@
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
-- | A minimal QuickCheck-like property testing framework for use in the GHC
@@ -52,6 +53,8 @@ module MiniQuickCheck
) where
-- base
+import Control.Exception
+ ( SomeException, displayException, evaluate, try )
import Control.Monad.IO.Class
( liftIO )
import Data.Bits
@@ -181,16 +184,39 @@ nest :: String -> ReaderT RunS IO a -> ReaderT RunS IO a
nest c = local (\s -> s { depth = depth s + 1, context = c : context s })
runPropertyCheck :: PropertyCheck -> ReaderT RunS IO Result
-runPropertyCheck (PropertyBinaryOp ok desc s1 s2) =
- if ok
- then return Success
- else do
- ctx <- context <$> ask
- let msg = "Failure: " ++ s1 ++ " " ++ desc ++ " " ++ s2
- putMsg msg
- return (Failure [msg : ctx])
-runPropertyCheck (PropertyAnd a b) =
- (<>) <$> runPropertyCheck a <*> runPropertyCheck b
+runPropertyCheck pcThunk = do
+ -- See Note [Catching exceptions in property evaluation].
+ pcRes <- liftIO $ try @SomeException (evaluate pcThunk)
+ case pcRes of
+ Left e -> reportFailure ("Failure: exception: " ++ displayException e)
+ Right (PropertyAnd a b) ->
+ (<>) <$> runPropertyCheck a <*> runPropertyCheck b
+ Right (PropertyBinaryOp ok desc s1 s2) -> do
+ okRes <- liftIO $ try @SomeException (evaluate ok)
+ case okRes of
+ Right True -> return Success
+ Right False -> reportFailure ("Failure: " ++ s1 ++ " " ++ desc ++ " " ++ s2)
+ Left e -> reportFailure ("Failure: exception: " ++ displayException e)
+
+reportFailure :: String -> ReaderT RunS IO Result
+reportFailure msg = do
+ ctx <- context <$> ask
+ putMsg msg
+ return (Failure [msg : ctx])
+
+-- Note [Catching exceptions in property evaluation]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- A property like `\a b -> let !r = a `div` 0 in r === b` builds a
+-- `PropertyCheck` thunk whose forcing raises an exception -- in this case
+-- already at the `PropertyBinaryOp` constructor, before its `ok` field is
+-- ever inspected. Other properties may force `ok = (s1 == s2)` instead and
+-- raise from there.
+--
+-- To handle both, we `evaluate` first the `PropertyCheck` thunk and then
+-- the `ok` field, each inside `try`, and report any exception through the
+-- normal `reportFailure` path. The surrounding loop then still prints
+-- "With arguments ... (Seed: ...)" and the test driver continues with
+-- subsequent properties instead of aborting.
runProperty :: Iterations -> Property -> ReaderT RunS IO Result
runProperty (Iterations iters) (Prop p) = do
=====================================
testsuite/tests/linters/notes.stdout
=====================================
@@ -27,7 +27,6 @@ ref compiler/GHC/Tc/Solver/Rewrite.hs:1020:7: Note [Stability of rewritin
ref compiler/GHC/Tc/TyCl.hs:1662:6: Note [Unification variables need fresh Names]
ref compiler/GHC/Tc/Types/Constraint.hs:209:9: Note [NonCanonical Semantics]
ref compiler/GHC/Types/Demand.hs:304:25: Note [Preserving Boxity of results is rarely a win]
-ref compiler/GHC/Unit/Module/Deps.hs:97:13: Note [Structure of dep_boot_mods]
ref compiler/GHC/Utils/Monad.hs:415:34: Note [multiShotIO]
ref compiler/Language/Haskell/Syntax/Binds.hs:206:31: Note [fun_id in Match]
ref configure.ac:205:10: Note [Linking ghc-bin against threaded stage0 RTS]
=====================================
testsuite/tests/numeric/should_run/foundation.hs
=====================================
@@ -77,13 +77,42 @@ testMultiplicative _ = Group "Multiplicative"
, Property "a * b == Integer(a) * Integer(b)" $ \(a :: a) (b :: a) -> a * b === fromInteger (toInteger a * toInteger b)
]
-testDividible :: forall a . (Show a, Eq a, Integral a, Num a, Arbitrary a, Typeable a)
+-- | Divisibility test for Bounded Integral types (Int, Int{8,16,32,64},
+-- Word, Word{8,16,32,64}).
+testDivisible :: forall a . (Show a, Eq a, Bounded a, Integral a, Num a, Arbitrary a, Typeable a)
=> Proxy a -> Test
-testDividible _ = Group "Divisible"
+testDivisible _ = Group "Divisible"
+ [ Property "(x `div` y) * y + (x `mod` y) == x" $ \(a :: a) (NonZero b) ->
+ -- See Note [Skipping minBound `div` (-1)].
+ if (minBound :: a) < 0 && a == minBound && b == (-1)
+ then True === True
+ else a === (a `div` b) * b + (a `mod` b)
+ ]
+
+-- | Divisibility test for unbounded Integral types (Integer). No overflow
+-- can occur here, so the property holds without exception for all NonZero b.
+testDivisibleUnbounded :: forall a . (Show a, Eq a, Integral a, Num a, Arbitrary a, Typeable a)
+ => Proxy a -> Test
+testDivisibleUnbounded _ = Group "Divisible"
[ Property "(x `div` y) * y + (x `mod` y) == x" $ \(a :: a) (NonZero b) ->
a === (a `div` b) * b + (a `mod` b)
]
+-- Note [Skipping minBound `div` (-1)]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- For a fixed-width *signed* Integral type, `minBound `div` (-1)` raises
+-- ArithException(Overflow) because `-minBound` is not representable in the
+-- type (e.g., for Int8, `-(-128)` would be 128, out of range). The div/mod
+-- identity property cannot hold there, so we skip exactly that one pair.
+--
+-- We detect "signed Bounded" with `(minBound :: a) < 0`: True for Int{N},
+-- False for Word{N}. This way unsigned Bounded types lose no coverage,
+-- and only the genuine overflow sample is skipped for signed types.
+--
+-- For the unbounded `Integer`, no overflow can occur and we use a separate
+-- 'testDivisibleUnbounded' (without the Bounded constraint or the skip).
+-- See #27222.
+
testOperatorPrecedence :: forall a . (Show a, Eq a, Prelude.Num a, Integral a, Num a, Arbitrary a, Typeable a)
=> Proxy a -> Test
testOperatorPrecedence _ = Group "Precedence"
@@ -101,14 +130,26 @@ testOperatorPrecedence _ = Group "Precedence"
]
-testNumber :: (Show a, Eq a, Prelude.Num a, Integral a, Num a, Arbitrary a, Typeable a)
+testNumber :: (Show a, Eq a, Prelude.Num a, Bounded a, Integral a, Num a, Arbitrary a, Typeable a)
=> String -> Proxy a -> Test
testNumber name proxy = Group name
[ testIntegral proxy
, testEqOrd proxy
, testAdditive proxy
, testMultiplicative proxy
- , testDividible proxy
+ , testDivisible proxy
+ , testOperatorPrecedence proxy
+ ]
+
+-- | Variant of 'testNumber' for unbounded Integral types (e.g., Integer).
+testNumberUnbounded :: (Show a, Eq a, Prelude.Num a, Integral a, Num a, Arbitrary a, Typeable a)
+ => String -> Proxy a -> Test
+testNumberUnbounded name proxy = Group name
+ [ testIntegral proxy
+ , testEqOrd proxy
+ , testAdditive proxy
+ , testMultiplicative proxy
+ , testDivisibleUnbounded proxy
, testOperatorPrecedence proxy
]
@@ -119,7 +160,7 @@ testNumberRefs = Group "ALL"
, testNumber "Int16" (Proxy :: Proxy Int16)
, testNumber "Int32" (Proxy :: Proxy Int32)
, testNumber "Int64" (Proxy :: Proxy Int64)
- , testNumber "Integer" (Proxy :: Proxy Integer)
+ , testNumberUnbounded "Integer" (Proxy :: Proxy Integer)
, testNumber "Word" (Proxy :: Proxy Word)
, testNumber "Word8" (Proxy :: Proxy Word8)
, testNumber "Word16" (Proxy :: Proxy Word16)
@@ -399,7 +440,7 @@ testPrimops = Group "primop"
, testPrimop "-#" (Primop.-#) (Wrapper.-#)
, testPrimop "*#" (Primop.*#) (Wrapper.*#)
, testPrimop "timesInt2#" Primop.timesInt2# Wrapper.timesInt2#
- , testPrimop "mulIntMayOflo#" Primop.mulIntMayOflo# Wrapper.mulIntMayOflo#
+ , testPrimopMayOflo "mulIntMayOflo#" Primop.mulIntMayOflo# Wrapper.mulIntMayOflo#
, testPrimopDivLike "quotInt#" Primop.quotInt# Wrapper.quotInt#
, testPrimopDivLike "remInt#" Primop.remInt# Wrapper.remInt#
, testPrimopDivLike "quotRemInt#" Primop.quotRemInt# Wrapper.quotRemInt#
@@ -497,6 +538,31 @@ instance TestPrimop (Int# -> Int# -> Int#) where
testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt#-> x0) (uInt#-> x1) -> wInt# (l x0 x1) === wInt# (r x0 x1)
testPrimopShift s l r = Property s $ \ (uInt#-> x0) (BoundedShiftAmount @Int shift) -> wInt# (l x0 (uInt# shift)) === wInt# (r x0 (uInt# shift))
+-- | Compare two 'mulIntMayOflo#'-like primops only on whether their result
+-- is zero. See Note [Comparing mulIntMayOflo# results].
+testPrimopMayOflo :: String
+ -> (Int# -> Int# -> Int#)
+ -> (Int# -> Int# -> Int#)
+ -> Test
+testPrimopMayOflo s l r =
+ Property s $ \ (uInt# -> x0) (uInt# -> x1) ->
+ (wInt# (l x0 x1) == 0) === (wInt# (r x0 x1) == 0)
+
+-- Note [Comparing mulIntMayOflo# results]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- The 'mulIntMayOflo#' primop is only specified to return 0 if the signed
+-- multiplication does not overflow, and a non-zero value if it /may/
+-- overflow (see Note [MO_S_MulMayOflo significant width] in
+-- GHC.Cmm.MachOp). The exact non-zero value is unspecified and legitimately
+-- differs between backends and between inlined vs. non-inlined call sites
+-- (e.g., the LLVM backend's `isSMulOK` returns `sext_signbit(low) - high`,
+-- which is some arbitrary non-zero word on overflow).
+--
+-- Comparing the raw Int# results bit-for-bit is therefore too strict and
+-- causes spurious test failures whenever the random arguments happen to
+-- overflow. We compare zero/non-zero instead, which matches the spec.
+-- See #27222.
+
instance TestPrimop (Int# -> Int# -> (# Int#,Int# #)) where
testPrimop s l r = Property s $ \ (uInt#-> x0) (uInt#-> x1) -> WTUP2(wInt#,wInt#, (l x0 x1)) === WTUP2(wInt#,wInt#, (r x0 x1))
testPrimopDivLike s l r = Property s $ twoNonZero $ \ (uInt#-> x0) (uInt#-> x1) -> WTUP2(wInt#,wInt#, (l x0 x1)) === WTUP2(wInt#,wInt#, (r x0 x1))
=====================================
testsuite/tests/th/T27022.hs
=====================================
@@ -0,0 +1,8 @@
+{-# LANGUAGE TemplateHaskell #-}
+-- | This tests the behaviour of TH's recover method.
+-- It should behave the same in the internal and external interperter.
+-- In the past, they have diverged, and the external interpreter would roll back the state of putQ/getQ whereas the internal interpreter would not.
+module Main where
+
+import Language.Haskell.TH.Syntax
+main = print $(putQ "0" >> recover (pure ()) (putQ "42" >> fail "oops") >> getQ @String >>= lift )
=====================================
testsuite/tests/th/T27022.stdout
=====================================
@@ -0,0 +1 @@
+Just "42"
=====================================
testsuite/tests/th/all.T
=====================================
@@ -650,3 +650,4 @@ test('GadtConSigs_th_dump1', normal, compile, ['-v0 -ddump-splices -dsuppress-un
test('T26099', normal, compile_fail, [''])
test('T8306_th', only_ways(['ghci']), ghci_script, ['T8306_th.script'])
test('T26862_th', only_ways(['ghci']), ghci_script, ['T26862_th.script'])
+test('T27022', normal, compile_and_run, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/4441dabbcfa6dda03992fb96d4773b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/4441dabbcfa6dda03992fb96d4773b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/no-ws-32-base-export] 5 commits: Add Bounded instances for Double, Float, CDouble and CFloat
by Teo Camarasu (@teo) 05 May '26
by Teo Camarasu (@teo) 05 May '26
05 May '26
Teo Camarasu pushed to branch wip/no-ws-32-base-export at Glasgow Haskell Compiler / GHC
Commits:
39141343 by Alice Rixte at 2026-05-01T14:09:32+02:00
Add Bounded instances for Double, Float, CDouble and CFloat
- - - - -
5c4c3bf4 by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: fix flaky foundation Divisible / mulIntMayOflo# tests (#27222)
Since the LCG was widened to 64 bits and the seed randomised per CI run
(commit 2d30f7d3400 "Vendor mini-QuickCheck for testsuite"), two latent
bugs in the foundation test surface stochastically:
* The Divisible property `(x `div` y) * y + (x `mod` y) == x` raises
ArithException(Overflow) when (a, b) = (minBound, -1) for fixed-width
signed Integral types. Split testNumber/testDivisible into Bounded and
unbounded variants and skip just that one pair, gated by
`(minBound :: a) < 0` so unsigned types lose no coverage.
* The `mulIntMayOflo#` test compared raw Int# bit-for-bit, but the primop
is only specified to return 0/non-zero -- the exact non-zero indicator
legitimately differs between backends and inlining choices. Add a
dedicated `testPrimopMayOflo` helper that only compares zero / non-zero.
Also fix the long-standing typo "Dividible" -> "Divisible" in identifiers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
e242ce4f by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: catch and display exceptions in MiniQuickCheck
Exceptions raised while evaluating a property are now caught and reported
as a normal failure (with arguments and seed), instead of aborting the
test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
3b75cccd by fendor at 2026-05-02T03:40:14-04:00
Fix name of Note [Structure of dep_boot_mods]
- - - - -
c1788778 by Teo Camarasu at 2026-05-04T21:26:58+01:00
interface-stability/base: don't distinguish ws-32
The interface of base is identical when the Word size is 32bits.
Therefore, there is no need to have another file for this case.
So, we delete it.
Step towards: #26752
- - - - -
11 changed files:
- compiler/GHC/Unit/Module/Deps.hs
- libraries/base/changelog.md
- libraries/ghc-internal/include/CTypes.h
- libraries/ghc-internal/src/GHC/Internal/Float.hs
- testsuite/tests/MiniQuickCheck.hs
- 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/base-exports.stdout-ws-32
- testsuite/tests/linters/notes.stdout
- testsuite/tests/numeric/should_run/foundation.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7ae755bae2a8a5836f704a0446a8ca…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7ae755bae2a8a5836f704a0446a8ca…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/jeltsch/text-read-implementation-into-base] 5 commits: Add Bounded instances for Double, Float, CDouble and CFloat
by Wolfgang Jeltsch (@jeltsch) 05 May '26
by Wolfgang Jeltsch (@jeltsch) 05 May '26
05 May '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/text-read-implementation-into-base at Glasgow Haskell Compiler / GHC
Commits:
39141343 by Alice Rixte at 2026-05-01T14:09:32+02:00
Add Bounded instances for Double, Float, CDouble and CFloat
- - - - -
5c4c3bf4 by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: fix flaky foundation Divisible / mulIntMayOflo# tests (#27222)
Since the LCG was widened to 64 bits and the seed randomised per CI run
(commit 2d30f7d3400 "Vendor mini-QuickCheck for testsuite"), two latent
bugs in the foundation test surface stochastically:
* The Divisible property `(x `div` y) * y + (x `mod` y) == x` raises
ArithException(Overflow) when (a, b) = (minBound, -1) for fixed-width
signed Integral types. Split testNumber/testDivisible into Bounded and
unbounded variants and skip just that one pair, gated by
`(minBound :: a) < 0` so unsigned types lose no coverage.
* The `mulIntMayOflo#` test compared raw Int# bit-for-bit, but the primop
is only specified to return 0/non-zero -- the exact non-zero indicator
legitimately differs between backends and inlining choices. Add a
dedicated `testPrimopMayOflo` helper that only compares zero / non-zero.
Also fix the long-standing typo "Dividible" -> "Divisible" in identifiers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
e242ce4f by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: catch and display exceptions in MiniQuickCheck
Exceptions raised while evaluating a property are now caught and reported
as a normal failure (with arguments and seed), instead of aborting the
test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
3b75cccd by fendor at 2026-05-02T03:40:14-04:00
Fix name of Note [Structure of dep_boot_mods]
- - - - -
73c1672e by Wolfgang Jeltsch at 2026-05-05T15:58:07+03:00
Move the `Text.Read` implementation into `base`
- - - - -
21 changed files:
- compiler/GHC/Unit/Module/Deps.hs
- libraries/base/changelog.md
- libraries/base/src/Data/Functor/Classes.hs
- libraries/base/src/Data/Functor/Compose.hs
- libraries/base/src/Prelude.hs
- libraries/base/src/Text/Read.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/include/CTypes.h
- libraries/ghc-internal/src/GHC/Internal/Float.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding.hs
- − libraries/ghc-internal/src/GHC/Internal/Text/Read.hs
- testsuite/tests/MiniQuickCheck.hs
- 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/base-exports.stdout-ws-32
- testsuite/tests/linters/notes.stdout
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/th/T24111.stdout
- testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
- testsuite/tests/typecheck/should_fail/T21130.stderr
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6b9447fe427f458fa04c76c1eabb76…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6b9447fe427f458fa04c76c1eabb76…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/jeltsch/text-read-implementation-into-base] Move the `Text.Read` implementation into `base`
by Wolfgang Jeltsch (@jeltsch) 05 May '26
by Wolfgang Jeltsch (@jeltsch) 05 May '26
05 May '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/text-read-implementation-into-base at Glasgow Haskell Compiler / GHC
Commits:
6b9447fe by Wolfgang Jeltsch at 2026-05-05T15:56:55+03:00
Move the `Text.Read` implementation into `base`
- - - - -
10 changed files:
- libraries/base/src/Data/Functor/Classes.hs
- libraries/base/src/Data/Functor/Compose.hs
- libraries/base/src/Prelude.hs
- libraries/base/src/Text/Read.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding.hs
- − libraries/ghc-internal/src/GHC/Internal/Text/Read.hs
- testsuite/tests/th/T24111.stdout
- testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
- testsuite/tests/typecheck/should_fail/T21130.stderr
Changes:
=====================================
libraries/base/src/Data/Functor/Classes.hs
=====================================
@@ -85,7 +85,7 @@ import GHC.Internal.Read (expectP, list, paren, readField)
import GHC.Internal.Show (appPrec)
import GHC.Internal.Text.ParserCombinators.ReadPrec (ReadPrec, readPrec_to_S, readS_to_Prec, pfail)
-import GHC.Internal.Text.Read (Read(..), parens, prec, step, reset)
+import Text.Read (Read(..), parens, prec, step, reset)
import GHC.Internal.Text.Read.Lex (Lexeme(..))
import GHC.Internal.Text.Show (showListWith)
import Prelude
=====================================
libraries/base/src/Data/Functor/Compose.hs
=====================================
@@ -35,7 +35,7 @@ import GHC.Internal.Data.Foldable (Foldable(..))
import GHC.Internal.Data.Monoid (Sum(..), All(..), Any(..), Product(..))
import GHC.Internal.Data.Type.Equality (TestEquality(..), (:~:)(..))
import GHC.Generics (Generic, Generic1)
-import GHC.Internal.Text.Read (Read(..), ReadPrec, readListDefault, readListPrecDefault)
+import Text.Read (Read(..), ReadPrec, readListDefault, readListPrecDefault)
import Prelude
infixr 9 `Compose`
=====================================
libraries/base/src/Prelude.hs
=====================================
@@ -179,7 +179,7 @@ import GHC.Internal.Data.Tuple
import GHC.Internal.Base hiding ( foldr, mapM, sequence )
import GHC.Internal.Classes
import GHC.Internal.Err
-import GHC.Internal.Text.Read
+import Text.Read
import GHC.Internal.Enum
import GHC.Internal.Num
import GHC.Internal.Prim (seq)
=====================================
libraries/base/src/Text/Read.hs
=====================================
@@ -39,5 +39,84 @@ module Text.Read
readMaybe
) where
-import GHC.Internal.Text.Read
+import GHC.Err (errorWithoutStackTrace)
+import GHC.Read
+ (
+ ReadS,
+ Read (readsPrec, readList, readPrec, readListPrec),
+ lex,
+ readParen,
+ readListDefault,
+ lexP,
+ parens,
+ readListPrecDefault
+ )
+import Control.Monad (return)
+import Data.Function (id)
+import Data.Maybe (Maybe (Nothing, Just))
+import Data.Either (Either (Left, Right), either)
+import Data.String (String)
+import Text.Read.Lex (Lexeme (Char, String, Punc, Ident, Symbol, Number, EOF))
+import Text.ParserCombinators.ReadP (skipSpaces)
import Text.ParserCombinators.ReadPrec
+
+-- $setup
+-- >>> import Prelude
+
+------------------------------------------------------------------------
+-- utility functions
+
+-- | equivalent to 'readsPrec' with a precedence of 0.
+reads :: Read a => ReadS a
+reads = readsPrec minPrec
+
+-- | Parse a string using the 'Read' instance.
+-- Succeeds if there is exactly one valid result.
+-- A 'Left' value indicates a parse error.
+--
+-- >>> readEither "123" :: Either String Int
+-- Right 123
+--
+-- >>> readEither "hello" :: Either String Int
+-- Left "Prelude.read: no parse"
+--
+-- @since base-4.6.0.0
+readEither :: Read a => String -> Either String a
+readEither s =
+ case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
+ [x] -> Right x
+ [] -> Left "Prelude.read: no parse"
+ _ -> Left "Prelude.read: ambiguous parse"
+ where
+ read' =
+ do x <- readPrec
+ lift skipSpaces
+ return x
+
+-- | Parse a string using the 'Read' instance.
+-- Succeeds if there is exactly one valid result.
+--
+-- >>> readMaybe "123" :: Maybe Int
+-- Just 123
+--
+-- >>> readMaybe "hello" :: Maybe Int
+-- Nothing
+--
+-- @since base-4.6.0.0
+readMaybe :: Read a => String -> Maybe a
+readMaybe s = case readEither s of
+ Left _ -> Nothing
+ Right a -> Just a
+
+-- | The 'read' function reads input from a string, which must be
+-- completely consumed by the input process. 'read' fails with an 'error' if the
+-- parse is unsuccessful, and it is therefore discouraged from being used in
+-- real applications. Use 'readMaybe' or 'readEither' for safe alternatives.
+--
+-- >>> read "123" :: Int
+-- 123
+--
+-- >>> read "hello" :: Int
+-- *** Exception: Prelude.read: no parse
+read :: Read a => String -> a
+read s = either errorWithoutStackTrace id (readEither s)
=====================================
libraries/ghc-internal/ghc-internal.cabal.in
=====================================
@@ -329,7 +329,6 @@ Library
GHC.Internal.System.Posix.Types
GHC.Internal.Text.ParserCombinators.ReadP
GHC.Internal.Text.ParserCombinators.ReadPrec
- GHC.Internal.Text.Read
GHC.Internal.Text.Read.Lex
GHC.Internal.Text.Show
GHC.Internal.Type.Reflection
=====================================
libraries/ghc-internal/src/GHC/Internal/IO/Encoding.hs
=====================================
@@ -46,7 +46,7 @@ import GHC.Internal.IO.Encoding.Types
import qualified GHC.Internal.IO.Encoding.Iconv as Iconv
#else
import qualified GHC.Internal.IO.Encoding.CodePage as CodePage
-import GHC.Internal.Text.Read (reads)
+import GHC.Internal.Read (readsPrec)
#endif
import qualified GHC.Internal.IO.Encoding.Latin1 as Latin1
import qualified GHC.Internal.IO.Encoding.UTF8 as UTF8
@@ -319,7 +319,8 @@ mkTextEncoding' cfm enc =
_ | isAscii -> return (Latin1.mkAscii cfm)
_ | isLatin1 -> return (Latin1.mkLatin1_checked cfm)
#if defined(mingw32_HOST_OS)
- 'C':'P':n | [(cp,"")] <- reads n -> return $ CodePage.mkCodePageEncoding cfm cp
+ 'C':'P':n | [(cp,"")] <- readsPrec 0 n -> return $ CodePage.mkCodePageEncoding cfm cp
+ -- 'readsPrec 0' is the same as 'reads', but 'reads' is only defined in @base@.
_ -> unknownEncodingErr (enc ++ codingFailureModeSuffix cfm)
#else
-- Otherwise, handle other encoding needs via iconv.
=====================================
libraries/ghc-internal/src/GHC/Internal/Text/Read.hs deleted
=====================================
@@ -1,115 +0,0 @@
-{-# LANGUAGE Trustworthy #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
------------------------------------------------------------------------------
--- |
--- Module : GHC.Internal.Text.Read
--- Copyright : (c) The University of Glasgow 2001
--- License : BSD-style (see the file libraries/base/LICENSE)
---
--- Maintainer : libraries(a)haskell.org
--- Stability : provisional
--- Portability : non-portable (uses Text.ParserCombinators.ReadP)
---
--- Converting strings to values.
---
--- The "Text.Read" library is the canonical library to import for
--- 'Read'-class facilities. For GHC only, it offers an extended and much
--- improved 'Read' class, which constitutes a proposed alternative to the
--- Haskell 2010 'Read'. In particular, writing parsers is easier, and
--- the parsers are much more efficient.
---
------------------------------------------------------------------------------
-
-module GHC.Internal.Text.Read (
- -- * The 'Read' class
- Read(..),
- ReadS,
-
- -- * Haskell 2010 functions
- reads,
- read,
- readParen,
- lex,
-
- -- * New parsing functions
- module GHC.Internal.Text.ParserCombinators.ReadPrec,
- L.Lexeme(..),
- lexP,
- parens,
- readListDefault,
- readListPrecDefault,
- readEither,
- readMaybe
-
- ) where
-
-import GHC.Internal.Base (String, id, return)
-import GHC.Internal.Err (errorWithoutStackTrace)
-import GHC.Internal.Maybe (Maybe(..))
-import GHC.Internal.Read
-import GHC.Internal.Data.Either
-import GHC.Internal.Text.ParserCombinators.ReadP as P
-import GHC.Internal.Text.ParserCombinators.ReadPrec
-import qualified GHC.Internal.Text.Read.Lex as L
-
--- $setup
--- >>> import Prelude
-
-------------------------------------------------------------------------
--- utility functions
-
--- | equivalent to 'readsPrec' with a precedence of 0.
-reads :: Read a => ReadS a
-reads = readsPrec minPrec
-
--- | Parse a string using the 'Read' instance.
--- Succeeds if there is exactly one valid result.
--- A 'Left' value indicates a parse error.
---
--- >>> readEither "123" :: Either String Int
--- Right 123
---
--- >>> readEither "hello" :: Either String Int
--- Left "Prelude.read: no parse"
---
--- @since base-4.6.0.0
-readEither :: Read a => String -> Either String a
-readEither s =
- case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
- [x] -> Right x
- [] -> Left "Prelude.read: no parse"
- _ -> Left "Prelude.read: ambiguous parse"
- where
- read' =
- do x <- readPrec
- lift P.skipSpaces
- return x
-
--- | Parse a string using the 'Read' instance.
--- Succeeds if there is exactly one valid result.
---
--- >>> readMaybe "123" :: Maybe Int
--- Just 123
---
--- >>> readMaybe "hello" :: Maybe Int
--- Nothing
---
--- @since base-4.6.0.0
-readMaybe :: Read a => String -> Maybe a
-readMaybe s = case readEither s of
- Left _ -> Nothing
- Right a -> Just a
-
--- | The 'read' function reads input from a string, which must be
--- completely consumed by the input process. 'read' fails with an 'error' if the
--- parse is unsuccessful, and it is therefore discouraged from being used in
--- real applications. Use 'readMaybe' or 'readEither' for safe alternatives.
---
--- >>> read "123" :: Int
--- 123
---
--- >>> read "hello" :: Int
--- *** Exception: Prelude.read: no parse
-read :: Read a => String -> a
-read s = either errorWithoutStackTrace id (readEither s)
=====================================
testsuite/tests/th/T24111.stdout
=====================================
@@ -3,6 +3,6 @@ pattern (:+_0) :: GHC.Internal.Types.Int ->
(GHC.Internal.Types.Int, GHC.Internal.Types.Int)
pattern x_1 :+_0 y_2 = (x_1, y_2)
pattern A_0 :: GHC.Internal.Types.Int -> GHC.Internal.Base.String
-pattern A_0 n_1 <- (GHC.Internal.Text.Read.read -> n_1) where
+pattern A_0 n_1 <- (Text.Read.read -> n_1) where
A_0 0 = "hi"
A_0 1 = "bye"
=====================================
testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
=====================================
@@ -11,14 +11,13 @@ subsumption_sort_hole_fits.hs:2:5: warning: [GHC-88464] [-Wtyped-holes (in -Wdef
words :: String -> [String]
(imported from ‘Prelude’
(and originally defined in ‘GHC.Internal.Data.OldList’))
- read :: forall a. Read a => String -> a
- with read @[String]
- (imported from ‘Prelude’
- (and originally defined in ‘GHC.Internal.Text.Read’))
repeat :: forall a. a -> [a]
with repeat @String
(imported from ‘Prelude’
(and originally defined in ‘GHC.Internal.List’))
+ read :: forall a. Read a => String -> a
+ with read @[String]
+ (imported from ‘Prelude’ (and originally defined in ‘Text.Read’))
mempty :: forall a. Monoid a => a
with mempty @(String -> [String])
(imported from ‘Prelude’
=====================================
testsuite/tests/typecheck/should_fail/T21130.stderr
=====================================
@@ -6,6 +6,9 @@ T21130.hs:10:6: error: [GHC-88464]
In an equation for ‘x’: x = (_ f) :: Int
• Relevant bindings include x :: Int (bound at T21130.hs:10:1)
Valid hole fits include
+ read :: forall a. Read a => String -> a
+ with read @Int
+ (imported from ‘Prelude’ (and originally defined in ‘Text.Read’))
head :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> a
with head @Int
(imported from ‘Prelude’
@@ -14,10 +17,6 @@ T21130.hs:10:6: error: [GHC-88464]
with last @Int
(imported from ‘Prelude’
(and originally defined in ‘GHC.Internal.List’))
- read :: forall a. Read a => String -> a
- with read @Int
- (imported from ‘Prelude’
- (and originally defined in ‘GHC.Internal.Text.Read’))
T21130.hs:10:8: error: [GHC-39999]
• Ambiguous type variable ‘t0’ arising from a use of ‘f’
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6b9447fe427f458fa04c76c1eabb76d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6b9447fe427f458fa04c76c1eabb76d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/supersven/libDir-setting] Add optional config setting for LibDir (#19174)
by Sven Tennie (@supersven) 05 May '26
by Sven Tennie (@supersven) 05 May '26
05 May '26
Sven Tennie pushed to branch wip/supersven/libDir-setting at Glasgow Haskell Compiler / GHC
Commits:
e00627ea by Sven Tennie at 2026-05-05T14:20:35+02:00
Add optional config setting for LibDir (#19174)
Previously, the `libDir` was derived from `topDir`. This won't work for
inplace stage2 cross-compilers where binaries and libraries are in
different stage dirs (`_build/stage1/` for executables and
`_build/stage2` for libraries).
`LibDir`` is set in the inplace `settings` files. For bindists, we
generate a new `settings` file with no `LibDir` entry. GHC then defaults
to use `topDir` as `libDir` again. This keeps the bindist relocatable.
If `LibDir` is a relative path, it is interpreted relatively to
`topDir`.
- - - - -
8 changed files:
- + changelog.d/libdir-setting
- compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/Generate.hs
Changes:
=====================================
changelog.d/libdir-setting
=====================================
@@ -0,0 +1,15 @@
+section: packaging
+synopsis: Added a new optional configuration setting for `LibDir` to support inplace
+ stage2 cross-compilers where binaries and libraries are in different stage
+ directories.
+issues: #19174
+mrs: !15716
+
+description: {
+ Previously, the `libDir` was always derived from `topDir`, which won't work
+ for inplace stage2 cross-compilers where executables are in `_build/stage1/`
+ and libraries are in `_build/stage2/`. Now, `LibDir` can be set, but is by
+ default derived from `topDir`. This facilitates the mentioned behaviour
+ while keeping the binary distribution code relocatable. This is a refactoring
+ step that does not change actual behaviour.
+}
=====================================
compiler/GHC/Driver/Config/Interpreter.hs
=====================================
@@ -17,8 +17,8 @@ import System.Directory
initInterpOpts :: DynFlags -> IO InterpOpts
initInterpOpts dflags = do
- wasm_dyld <- makeAbsolute $ topDir dflags </> "dyld.mjs"
- js_interp <- makeAbsolute $ topDir dflags </> "ghc-interp.js"
+ wasm_dyld <- makeAbsolute $ libDir dflags </> "dyld.mjs"
+ js_interp <- makeAbsolute $ libDir dflags </> "ghc-interp.js"
pure $ InterpOpts
{ interpExternal = gopt Opt_ExternalInterpreter dflags
, interpProg = pgm_i dflags
=====================================
compiler/GHC/Driver/DynFlags.hs
=====================================
@@ -60,7 +60,7 @@ module GHC.Driver.DynFlags (
-- ** System tool settings and locations
programName, projectVersion,
- ghcUsagePath, ghciUsagePath, topDir, toolDir,
+ ghcUsagePath, ghciUsagePath, topDir, libDir, toolDir,
versionedAppDir, versionedFilePath,
extraGccViaCFlags, globalPackageDatabasePath,
@@ -1508,6 +1508,8 @@ ghciUsagePath :: DynFlags -> FilePath
ghciUsagePath dflags = fileSettings_ghciUsagePath $ fileSettings dflags
topDir :: DynFlags -> FilePath
topDir dflags = fileSettings_topDir $ fileSettings dflags
+libDir :: DynFlags -> FilePath
+libDir dflags = fileSettings_libDir $ fileSettings dflags
toolDir :: DynFlags -> Maybe FilePath
toolDir dflags = fileSettings_toolDir $ fileSettings dflags
extraGccViaCFlags :: DynFlags -> [String]
=====================================
compiler/GHC/Driver/Session.hs
=====================================
@@ -3548,9 +3548,9 @@ compilerInfo dflags
("Project name", cProjectName)
-- Next come the settings, so anything else can be overridden
-- in the settings file (as "lookup" uses the first match for the
- -- key)
+ -- key). We filter out LibDir from rawSettings to avoid duplication.
: map (fmap expandDirectories)
- (rawSettings dflags)
+ (filter ((/= "LibDir") . fst) (rawSettings dflags))
++
[("C compiler command", queryCmd $ ccProgram . tgtCCompiler),
("C compiler flags", queryFlags $ ccProgram . tgtCCompiler),
@@ -3651,7 +3651,7 @@ compilerInfo dflags
-- Whether or not GHC was compiled using -prof
("GHC Profiled", showBool hostIsProfiled),
("Debug on", showBool debugIsOn),
- ("LibDir", topDir dflags),
+ ("LibDir", libDir dflags),
-- This is always an absolute path, unlike "Relative Global Package DB" which is
-- in the settings file.
("Global Package DB", globalPackageDatabasePath dflags)
=====================================
compiler/GHC/Settings.hs
=====================================
@@ -184,6 +184,7 @@ data FileSettings = FileSettings
, fileSettings_toolDir :: Maybe FilePath -- ditto
, fileSettings_topDir :: FilePath -- ditto
, fileSettings_globalPackageDatabase :: FilePath
+ , fileSettings_libDir :: FilePath
}
=====================================
compiler/GHC/Settings/IO.hs
=====================================
@@ -28,6 +28,7 @@ import GHC.Toolchain.Program
import GHC.Toolchain
import GHC.Data.Maybe
import Data.Bifunctor (Bifunctor(second))
+import Data.Either (fromRight)
data SettingsError
= SettingsError_MissingData String
@@ -148,6 +149,17 @@ initSettings top_dir = do
baseUnitId <- getSetting_raw "base unit-id"
+ -- LibDir is optional. If not set, derive it from topDir. This allows
+ -- bindists to work without explicitly setting LibDir, but gives us the
+ -- option to override it for inplace test compilers (the "stage2
+ -- cross-compiler" scenario). If LibDir is a relative path, it is
+ -- interpreted relative to topDir.
+ let lib_dir_raw = fromRight top_dir $
+ getRawFilePathSetting top_dir settingsFile mySettings "LibDir"
+ lib_dir = if isRelative lib_dir_raw
+ then top_dir </> lib_dir_raw
+ else lib_dir_raw
+
return $ Settings
{ sGhcNameVersion = GhcNameVersion
{ ghcNameVersion_programName = "ghc"
@@ -159,6 +171,7 @@ initSettings top_dir = do
, fileSettings_ghciUsagePath = ghci_usage_msg_path
, fileSettings_toolDir = mtool_dir
, fileSettings_topDir = top_dir
+ , fileSettings_libDir = lib_dir
, fileSettings_globalPackageDatabase = globalpkgdb_path
}
=====================================
hadrian/src/Rules/BinaryDist.hs
=====================================
@@ -14,6 +14,7 @@ import qualified System.Directory.Extra as IO
import Data.Either
import qualified Data.Set as Set
import Oracles.Flavour
+import Rules.Generate (generateSettings)
{-
Note [Binary distributions]
@@ -218,6 +219,16 @@ bindistRules = do
IO.createFileLink version_prog versioned_runhaskell_path
copyDirectory (ghcBuildDir -/- "lib") bindistFilesDir
+
+ -- Regenerate settings file without LibDir. For bindists, LibDir should
+ -- be derived from topdir at runtime such that the GHC binary is
+ -- relocatable.
+ let bindistSettings = bindistFilesDir -/- "lib" -/- "settings"
+ bindistContext = vanillaContext Stage1 compiler
+ bindistSettingsContent <- interpretInContext bindistContext $
+ generateSettings bindistSettings False (bindistFilesDir -/- "lib" -/- "package.conf.d")
+ writeFile' bindistSettings bindistSettingsContent
+
copyDirectory (rtsIncludeDir) bindistFilesDir
when windowsHost $ createGhcii (bindistFilesDir -/- "bin")
=====================================
hadrian/src/Rules/Generate.hs
=====================================
@@ -1,7 +1,7 @@
module Rules.Generate (
isGeneratedCmmFile, compilerDependencies, generatePackageCode,
generateRules, copyRules, generatedDependencies,
- templateRules
+ templateRules, generateSettings
) where
import Development.Shake.FilePath
@@ -256,8 +256,17 @@ generateRules = do
forM_ allStages $ \stage -> do
let prefix = root -/- stageString stage -/- "lib"
- go gen file = generate file (semiEmptyTarget (succStage stage)) gen
- (prefix -/- "settings") %> \out -> go (generateSettings out) out
+ -- Stage0 compiler builds Stage1, Stage1 -> Stage2, etc.
+ buildStage = succStage stage
+ go gen file = generate file (semiEmptyTarget buildStage) gen
+ (prefix -/- "settings") %> \out -> do
+ let get_pkg_db stg = packageDbPath (PackageDbLoc stg Final)
+ pkgDb <- case buildStage of
+ Stage0 {} -> error "Unable to generate settings for stage0. This should never be reached."
+ Stage1 -> get_pkg_db Stage1
+ Stage2 -> get_pkg_db Stage1
+ Stage3 -> get_pkg_db Stage2
+ go (generateSettings out True pkgDb) out
(prefix -/- "targets" -/- "default.target") %> \out -> go (show <$> expr getTargetTarget) out
where
@@ -459,19 +468,16 @@ ghcWrapper stage = do
return $ unwords $ map show $ [ ghcPath ]
++ [ "$@" ]
-generateSettings :: FilePath -> Expr String
-generateSettings settingsFile = do
+-- | Generate settings file, optionally including @LibDir@.
+--
+-- @pkgDb@: absolute path to the package DB for the @"Relative Global Package
+-- DB"@ setting. Callers determine the correct path (in-tree or bindist). For
+-- bindists, we omit @LibDir@ so it defaults to @topDir@ at runtime.
+generateSettings :: FilePath -> Bool -> FilePath -> Expr String
+generateSettings settingsFile includeLibDir package_db_path = do
ctx <- getContext
stage <- getStage
- package_db_path <- expr $ do
- let get_pkg_db stg = packageDbPath (PackageDbLoc stg Final)
- case stage of
- Stage0 {} -> error "Unable to generate settings for stage0"
- Stage1 -> get_pkg_db Stage1
- Stage2 -> get_pkg_db Stage1
- Stage3 -> get_pkg_db Stage2
-
-- The unit-id of the base package which is always linked against (#25382)
base_unit_id <- expr $ do
case stage of
@@ -481,14 +487,22 @@ generateSettings settingsFile = do
Stage3 -> pkgUnitId Stage2 base
let rel_pkg_db = makeRelativeNoSysLink (dropFileName settingsFile) package_db_path
+ -- E.g. the Stage2 compiler lives in _build/stage1
+ -- So, we need to decrement the stage to get the correct directory
+ stage_dir_stage = predStage stage
+
+ lib_topDir :: FilePath <- expr $ stageLibPath stage_dir_stage
+ let rel_lib_topDir = makeRelativeNoSysLink (dropFileName settingsFile) lib_topDir
settings <- traverse sequence $
- [ ("unlit command", ("$topdir/../bin/" <>) <$> expr (programName (ctx { Context.package = unlit })))
- , ("Use interpreter", expr $ yesNo <$> ghcWithInterpreter (predStage stage))
- , ("RTS ways", escapeArgs . map show . Set.toList <$> getRtsWays)
- , ("Relative Global Package DB", pure rel_pkg_db)
- , ("base unit-id", pure base_unit_id)
- ]
+ [ ("unlit command", ("$topdir/../bin/" <>) <$> expr (programName (ctx { Context.package = unlit })))
+ , ("Use interpreter", expr $ yesNo <$> ghcWithInterpreter (predStage stage))
+ , ("RTS ways", escapeArgs . map show . Set.toList <$> getRtsWays)
+ , ("Relative Global Package DB", pure rel_pkg_db)
+ , ("base unit-id", pure base_unit_id)
+ ]
+ ++ ([("LibDir", pure rel_lib_topDir) | includeLibDir])
+
let showTuple (k, v) = "(" ++ show k ++ ", " ++ show v ++ ")"
pure $ case settings of
[] -> "[]"
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e00627ea30555e63d7fd25dc20b45ce…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e00627ea30555e63d7fd25dc20b45ce…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/dcoutts/windows-rts-dll] 5 commits: Add minimal dlltool support into ./configure
by David Eichmann (@DavidEichmann) 05 May '26
by David Eichmann (@DavidEichmann) 05 May '26
05 May '26
David Eichmann pushed to branch wip/dcoutts/windows-rts-dll at Glasgow Haskell Compiler / GHC
Commits:
832dff15 by Duncan Coutts at 2026-05-05T13:17:13+01:00
Add minimal dlltool support into ./configure
Find dlltool, and hopefully support finding it within the bundled llvm
toolchain on windows.
- - - - -
b25e9f4b by Duncan Coutts at 2026-05-05T13:17:13+01:00
Update the default host and target files for dlltool support
- - - - -
0967ce19 by Duncan Coutts at 2026-05-05T13:17:13+01:00
Add dlltool as a hadrian builder
Optional except on windows.
- - - - -
7e274801 by Duncan Coutts at 2026-05-05T13:17:13+01:00
Update and generate libHSghc-internal.def from .def.in file
The only symbol that the rts imports from the ghc-internal package now
is init_ghc_hs_iface. So the rts only needs an import lib that defines
that one symbol.
Also, remove the libHSghc-prim.def because it is redundant. The rts no
longer imports anything from ghc-prim.
Keep libHSffi.def for now. We may yet need it once it is clear how
libffi is going to be built/used for ghc.
- - - - -
c3ece8f6 by Duncan Coutts at 2026-05-05T13:17:13+01:00
Add rule to build libHSghc-internal.dll.a and link into the rts
On windows only, with dynamic linking.
This is needed because on windows, all symbols in dlls must be resolved.
No dangling symbols allowed. References to external symbols must be
explicit. We resolve this with an import library. We create an import
library for ghc-internal, a .dll.a file. This is a static archive
containing .o files that define the symbols we need, and crucially have
".idata" sections that specifies the symbols the dll imports and from
where.
Note that we do not install this libHSghc-internal.dll.a, and it does
not need to list all the symbols exported by that package. We create a
special purpose import lib and only use it when linking the rts dll, so
it only has to list the symbols that the rts uses from ghc-internal
(which is exactly one symbol: init_ghc_hs_iface).
- - - - -
15 changed files:
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- configure.ac
- distrib/configure.ac.in
- hadrian/cfg/default.host.target.in
- hadrian/cfg/default.target.in
- hadrian/src/Builder.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Rts.hs
- m4/fp_setup_windows_toolchain.m4
- m4/ghc_toolchain.m4
- m4/prep_target_file.m4
- rts/.gitignore
- + rts/win32/libHSghc-internal.def.in
Changes:
=====================================
.gitlab/generate-ci/gen_ci.hs
=====================================
@@ -1305,6 +1305,7 @@ cross_jobs = [
. setVariable "STRINGS" (llvm_prefix ++ "strings")
. setVariable "STRIP" (llvm_prefix ++ "strip")
. setVariable "WindresCmd" (llvm_prefix ++ "windres")
+ . setVariable "DlltoolCmd" (llvm_prefix ++ "llvm-dlltool")
. setVariable "LLVMAS" (llvm_prefix ++ "clang")
. setVariable "LD" (llvm_prefix ++ "ld")
-- Windows target require to make linker merge feature check disabled.
=====================================
.gitlab/jobs.yaml
=====================================
@@ -317,6 +317,7 @@
"CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
"CROSS_TARGET": "aarch64-unknown-mingw32",
"CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+ "DlltoolCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-dlltool",
"HADRIAN_ARGS": "--docs=none",
"INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
"LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
@@ -399,6 +400,7 @@
"CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
"CROSS_TARGET": "aarch64-unknown-mingw32",
"CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+ "DlltoolCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-dlltool",
"HADRIAN_ARGS": "--docs=none",
"INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
"LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
@@ -1111,6 +1113,7 @@
"CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
"CROSS_TARGET": "aarch64-unknown-mingw32",
"CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+ "DlltoolCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-dlltool",
"HADRIAN_ARGS": "--docs=none",
"INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
"LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
@@ -1194,6 +1197,7 @@
"CROSS_EMULATOR": "/opt/wine-arm64ec-msys2-deb12/bin/wine",
"CROSS_TARGET": "aarch64-unknown-mingw32",
"CXX": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-clang++",
+ "DlltoolCmd": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-llvm-dlltool",
"HADRIAN_ARGS": "--docs=none",
"INSTALL_CONFIGURE_ARGS": "--enable-strict-ghc-toolchain-check",
"LD": "/opt/llvm-mingw-linux/bin/aarch64-w64-mingw32-ld",
=====================================
configure.ac
=====================================
@@ -568,6 +568,12 @@ FIND_LLVM_PROG([OPT], [opt], [$LlvmMinVersion], [$LlvmMaxVersion])
OptCmd="$OPT"
AC_SUBST([OptCmd])
+dnl ** Which LLVM llvm-dlltool to use?
+dnl --------------------------------------------------------------
+AC_ARG_VAR(DlltoolCmd,[Use as the path to LLVM's llvm-dlltool [default=autodetect]])
+FIND_LLVM_PROG([DlltoolCmd], [llvm-dlltool], [$LlvmMinVersion], [$LlvmMaxVersion])
+AC_SUBST([DlltoolCmd])
+
dnl ** look to see if we have a C compiler using an llvm back end.
dnl
FP_CC_LLVM_BACKEND
@@ -1080,9 +1086,10 @@ echo "\
libdw : $UseLibdw
Using LLVM tools
- llc : $LlcCmd
- opt : $OptCmd
- llvm-as : $LlvmAsCmd"
+ llc : $LlcCmd
+ opt : $OptCmd
+ llvm-as : $LlvmAsCmd
+ llvm-dlltool : $DlltoolCmd"
if test "$HSCOLOUR" = ""; then
echo "
=====================================
distrib/configure.ac.in
=====================================
@@ -229,6 +229,12 @@ FIND_LLVM_PROG([LLVMAS], [clang], [$LlvmMinVersion], [$LlvmMaxVersion])
LlvmAsCmd="$LLVMAS"
AC_SUBST([LlvmAsCmd])
+dnl ** Which LLVM llvm-dlltool to use?
+dnl --------------------------------------------------------------
+AC_ARG_VAR(DlltoolCmd,[Use as the path to LLVM's llvm-dlltool [default=autodetect]])
+FIND_LLVM_PROG([DlltoolCmd], [llvm-dlltool], [$LlvmMinVersion], [$LlvmMaxVersion])
+AC_SUBST([DlltoolCmd])
+
dnl We know that `clang` supports `--target` and it is necessary to pass it
dnl lest we see #25793.
if test -z "$LlvmAsFlags" && ! test -z "$LlvmTarget"; then
=====================================
hadrian/cfg/default.host.target.in
=====================================
@@ -45,6 +45,7 @@ Target
, tgtOpt = Nothing
, tgtLlvmAs = Nothing
, tgtWindres = Nothing
+, tgtDlltool = Nothing
, tgtOtool = Nothing
, tgtInstallNameTool = Nothing
}
=====================================
hadrian/cfg/default.target.in
=====================================
@@ -45,6 +45,7 @@ Target
, tgtOpt = @OptCmdMaybeProg@
, tgtLlvmAs = @LlvmAsCmdMaybeProg@
, tgtWindres = @WindresCmdMaybeProg@
+, tgtDlltool = @DlltoolCmdMaybeProg@
, tgtOtool = @OtoolCmdMaybeProg@
, tgtInstallNameTool = @InstallNameToolCmdMaybeProg@
}
=====================================
hadrian/src/Builder.hs
=====================================
@@ -17,7 +17,7 @@ import Development.Shake.Classes
import Development.Shake.Command
import Development.Shake.FilePath
import GHC.Generics
-import GHC.Platform.ArchOS (ArchOS(..), Arch(..))
+import GHC.Platform.ArchOS (ArchOS(..), Arch(..), OS(..))
import qualified Hadrian.Builder as H
import Hadrian.Builder hiding (Builder)
import Hadrian.Builder.Ar
@@ -180,6 +180,7 @@ data Builder = Alex
| Objdump
| Python
| Ranlib
+ | Dlltool
| Testsuite TestMode
| Sphinx SphinxMode
| Tar TarMode
@@ -418,6 +419,7 @@ isOptional target = \case
Alex -> True
-- Most ar implemententions no longer need ranlib, but some still do
Ranlib -> not $ Toolchain.arNeedsRanlib (tgtAr target)
+ Dlltool -> archOS_OS (tgtArchOs target) /= OSMinGW32
JsCpp -> not $ (archOS_arch . tgtArchOs) target == ArchJavaScript -- ArchWasm32 too?
_ -> False
@@ -442,6 +444,7 @@ systemBuilderPath builder = case builder of
Objdump -> fromKey "objdump"
Python -> fromKey "python"
Ranlib -> fromTargetTC "ranlib" (maybeProg Toolchain.ranlibProgram . tgtRanlib)
+ Dlltool -> fromTargetTC "dlltool" (maybeProg id . tgtDlltool)
Testsuite _ -> fromKey "python"
Sphinx _ -> fromKey "sphinx-build"
Tar _ -> fromKey "tar"
=====================================
hadrian/src/Rules/Generate.hs
=====================================
@@ -377,6 +377,7 @@ templateRules = do
, interpolateSetting "ProjectPatchLevel1" ProjectPatchLevel1
, interpolateSetting "ProjectPatchLevel2" ProjectPatchLevel2
]
+ templateRule "rts/win32/libHSghc-internal.def" projectVersion
templateRule "docs/index.html" $ packageUnitIds Stage1
templateRule "docs/users_guide/ghc_config.py" $ mconcat
[ projectVersion
=====================================
hadrian/src/Rules/Library.hs
=====================================
@@ -4,6 +4,8 @@ import Hadrian.BuildPath
import Hadrian.Haskell.Cabal
import Hadrian.Haskell.Cabal.Type
import qualified Text.Parsec as Parsec
+import GHC.Platform.ArchOS (ArchOS(archOS_OS), OS(..))
+import GHC.Toolchain.Target (Target(tgtArchOs))
import Base
import Context
@@ -185,9 +187,13 @@ jsObjects context = do
srcs <- interpretInContext context (getContextData jsSrcs)
mapM (objectPath context) srcs
--- | Return extra object files needed to build the given library context. The
--- resulting list is currently non-empty only when the package from the
--- 'Context' is @ghc-internal@ built with in-tree GMP backend.
+-- | Return extra object files needed to build the given library context.
+--
+-- This is non-empty for:
+--
+-- * @ghc-internal@ when built with in-tree GMP backend
+-- * @rts@ on Windows when linking dynamically
+--
extraObjects :: Context -> Action [FilePath]
extraObjects context
| package context == ghcInternal = do
@@ -195,6 +201,13 @@ extraObjects context
"gmp" -> gmpObjects (stage context)
_ -> return []
+ | package context == rts = do
+ target <- interpretInContext context getStagedTarget
+ builddir <- buildPath context
+ return [ builddir -/- "libHSghc-internal.dll.a"
+ | archOS_OS (tgtArchOs target) == OSMinGW32
+ , Dynamic `wayUnit` way context ]
+
| otherwise = return []
-- | Return all the object files to be put into the library we're building for
=====================================
hadrian/src/Rules/Rts.hs
=====================================
@@ -24,6 +24,20 @@ rtsRules = priority 3 $ do
(addRtsDummyVersion $ takeFileName rtsLibFilePath')
rtsLibFilePath'
+ -- Solve the recursive dependency between the rts and ghc-internal
+ -- on Windows by creating an import lib for the ghc-internal dll,
+ -- to be linked into the rts dll.
+ forM_ [Stage1, Stage2, Stage3 ] $ \ stage -> do
+ let buildPath = root -/- buildDir (rtsContext stage)
+ buildPath -/- "libHSghc-internal.dll.a" %> buildGhcInternalImportLib
+
+buildGhcInternalImportLib :: FilePath -> Action ()
+buildGhcInternalImportLib target = do
+ let input = "rts/win32/libHSghc-internal.def"
+ output = target -- the .dll.a import lib
+ need [input]
+ runBuilder Dlltool ["-d", input, "-l", output] [input] [output]
+
-- Need symlinks generated by rtsRules.
needRtsSymLinks :: Stage -> Set.Set Way -> Action ()
needRtsSymLinks stage rtsWays
=====================================
m4/fp_setup_windows_toolchain.m4
=====================================
@@ -131,8 +131,8 @@ AC_DEFUN([FP_SETUP_WINDOWS_TOOLCHAIN],[
AR="${mingwbin}llvm-ar.exe"
RANLIB="${mingwbin}llvm-ranlib.exe"
OBJDUMP="${mingwbin}llvm-objdump.exe"
- DLLTOOL="${mingwbin}llvm-dlltool.exe"
WindresCmd="${mingwbin}llvm-windres.exe"
+ DlltoolCmd="${mingwbin}llvm-dlltool.exe"
LLC="${mingwbin}llc.exe"
OPT="${mingwbin}opt.exe"
LLVMAS="${mingwbin}clang.exe"
=====================================
m4/ghc_toolchain.m4
=====================================
@@ -95,6 +95,7 @@ AC_DEFUN([FIND_GHC_TOOLCHAIN],
echo "--merge-objs=$MergeObjsCmd" >> acargs
echo "--readelf=$READELF" >> acargs
echo "--windres=$WindresCmd" >> acargs
+ echo "--dlltool=$DlltoolCmd" >> acargs
echo "--llc=$LlcCmd" >> acargs
echo "--opt=$OptCmd" >> acargs
echo "--llvm-as=$LlvmAsCmd" >> acargs
=====================================
m4/prep_target_file.m4
=====================================
@@ -191,6 +191,7 @@ AC_DEFUN([PREP_TARGET_FILE],[
PREP_MAYBE_SIMPLE_PROGRAM([OptCmd])
PREP_MAYBE_PROGRAM([LlvmAsCmd], [LlvmAsFlags])
PREP_MAYBE_SIMPLE_PROGRAM([WindresCmd])
+ PREP_MAYBE_SIMPLE_PROGRAM([DlltoolCmd])
PREP_MAYBE_SIMPLE_PROGRAM([OtoolCmd])
PREP_MAYBE_SIMPLE_PROGRAM([InstallNameToolCmd])
PREP_MAYBE_STRING([TargetVendor_CPP])
=====================================
rts/.gitignore
=====================================
@@ -20,3 +20,4 @@
/ghcautoconf.h.autoconf.in
/ghcautoconf.h.autoconf
/include/ghcautoconf.h
+/win32/libHSghc-internal.def
=====================================
rts/win32/libHSghc-internal.def.in
=====================================
@@ -0,0 +1,4 @@
+LIBRARY libHSghc-internal-@ProjectVersionForLib@.0-ghc@ProjectVersion@.dll
+
+EXPORTS
+ init_ghc_hs_iface
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d75a37126cb1a0e9736ac910fd98a2…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d75a37126cb1a0e9736ac910fd98a2…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/andreask/build-opt] 46 commits: NCG: Implement constant folding for vector simd ops (Issue #25030)
by Andreas Klebinger (@AndreasK) 05 May '26
by Andreas Klebinger (@AndreasK) 05 May '26
05 May '26
Andreas Klebinger pushed to branch wip/andreask/build-opt at Glasgow Haskell Compiler / GHC
Commits:
72d6dc74 by aparker at 2026-04-20T20:15:44-04:00
NCG: Implement constant folding for vector simd ops (Issue #25030)
- - - - -
b9cab907 by sheaf at 2026-04-20T20:15:44-04:00
Mark some SIMD tests as broken on i386 optllvm
As seen in #25498, several SIMD tests are broken on i386 in the optllvm
way. This commit marks them as "expect_broken".
- - - - -
76528cc3 by Wolfgang Jeltsch at 2026-04-20T20:16:25-04:00
Move most of the `System.IO` implementation into `base`
This involves a rewrite of the `combine` helper function to avoid the
use of `last`, which would now be flagged as an error.
Metric Decrease:
LinkableUsage01
T3294
Metric Increase:
T12227
T12707
T5642
- - - - -
04d143c0 by Luite Stegeman at 2026-04-21T14:05:33-04:00
rts: add a few missing i386 relocations in the rts linker
- - - - -
014087e7 by Luite Stegeman at 2026-04-21T14:05:34-04:00
CodeOutput: Fix finalizers on multiple platforms
- ELF platforms: emit .fini_array section
- wasm32/Darwin: emit initializer with __cxa_atexit call
- Windows: use -Wl,--whole-archive to prevent dropping finalizer symbols
- rts linker: fix crash/assertion failure unloading objects with finalizers
fixes #27072
- - - - -
915bba6f by Simon Jakobi at 2026-04-21T14:06:16-04:00
Add regression test for #10531
Closes #10531.
- - - - -
86a646a6 by Andreas Klebinger at 2026-04-22T13:00:05-04:00
Revert use of generic instances for compiler time perf reasons.
Revert "Derive Semigroup/Monoid for instances believed could be derived in #25871"
This reverts commit 11a04cbb221cc404fe00d65d7c951558ede4caa9.
Revert "add Ghc.Data.Pair deriving"
This reverts commit 15d9ce449e1be8c01b89fd39bdf1e700ea7d1dce.
- - - - -
bc9ee1cf by Wen Kokke at 2026-04-22T13:00:51-04:00
hadrian: Fix docs to remove static flavour
In 638f6548, the static flavour was turned into into the fully_static
flavour transformer. However, this commit did not update flavours.md.
- - - - -
cc9cc6d5 by Cheng Shao at 2026-04-23T09:40:46+00:00
configure: bump LlvmMaxVersion to 23
This patch bumps `LlvmMaxVersion` to 23 to support LLVM 22.x releases.
- - - - -
2ea7ef8e by Cheng Shao at 2026-04-23T09:46:26+00:00
changelog: add llvm 22.x support
- - - - -
5574ee10 by Cheng Shao at 2026-04-24T08:24:30-04:00
compiler: avoid unused temporary `appendFS` operands
This patch fixes unused temporary `appendFS` operands in the codebase
that are retained in the `FastString` table after concatenation.
Rewrite rules are added so that if an operand is
`fsLit`/`mkFastString`, the `appendFS` application is rewritten to
append the `ShortByteString` operands first. The patch also fixes
`sconcat` behavior to align with `mconcat` for the same reason. Fixes #27205.
- - - - -
4ed78760 by mangoiv at 2026-04-24T08:25:13-04:00
contributing: adjust MR template to be less verbose
- MR template only shows text that is relevant for submissiong
- MR template was rewritten so it's readable from a user's and reviewer's
perspective
Resolves #27165
Co-Authored-By: @sheaf
- - - - -
87db83e2 by Cheng Shao at 2026-04-24T14:37:21-04:00
ci: bump freebsd boot ghc to 9.10.3
This commit bumps freebsd boot ghc to 9.10.3 to align with other
platforms and prevent outdated boot libs in boot ghc to block the
freebsd job.
- - - - -
17e3a0b7 by Cheng Shao at 2026-04-24T14:37:21-04:00
compiler: improve Binary instance of Array
This patch improves the `Binary` instance of `Array`:
- We no longer allocate intermediate lists. When serializing an
`Array`, we iterate over the elements directly; when deserializing
it, we allocate the result `Array` and fill it in a loop.
- Now we only serialize the array bounds tuple; the length field is
not needed.
Closes #27109.
- - - - -
2d30f7d3 by sheaf at 2026-04-24T14:38:23-04:00
Vendor mini-QuickCheck for testsuite
This commit extracts the vendored QuickCheck implementation from the
foundation testsuite to make it more broadly available in the GHC
testsuite, and makes use of it in the simd006 test (which also used
a vendored QuickCheck implementation).
On the way, we update the linear congruential generator to avoid the
shortcoming of only generating 31 bit large numbers.
Fixes #25990 and #25969.
- - - - -
1350271b by sheaf at 2026-04-27T09:32:53-04:00
Ensure TcM plugins are only initialised once
This commit ensures we keep TcM plugins (typechecker plugins,
defaulting plugins and hole fit plugins) running all the way through
desugaring, instead of stopping them at the end of typechecking.
To do this, the "stop" actions of TcPlugin and DefaultingPlugin are
split into two: one for the "post-typecheck" action, and one for the
final shutdown action (after desugaring).
This allows the plugins to be invoked by the pattern match checker
(during desugaring) without having to be repeatedly re-initialised and
stopped, fixing #26839.
In the process, this commit modifies 'initTc' and 'initTcInteractive',
adding an extra argument that describes whether to start/stop the 'TcM'
plugins.
See Note [Stop TcM plugins after desugaring] for an overview.
- - - - -
42549222 by sheaf at 2026-04-27T09:33:50-04:00
Hadrian: add --keep-response-files
This commit adds a Hadrian flag that allows response files to be
retained. This is useful for debugging a failing Hadrian command line.
- - - - -
40564e8d by sheaf at 2026-04-27T09:34:46-04:00
hadrian/build-cabal.bat: fix build on Windows
Commit 8cb99552f6 introduced a warning for a missing package index.
However, the logic was faulty on Windows: the piping was broken, and
"remote-repo-cache:" was being interpreted as a (malformed) drive letter,
leading to the error:
The filename, directory name, or volume label syntax is incorrect.
This commit fixes that by using a temporary file instead of piping.
- - - - -
14bc71e4 by Sven Tennie at 2026-04-28T13:22:47-04:00
ghc: Distinguish between having an interpreter and having an internal one
Actually, these are related but different things:
- ghc can run an interpreter (either internal or external)
- ghc is compiled with an internal interpreter
Splitting the logic solves compiler warnings and expresses the intent
better.
- - - - -
df691563 by Vladislav Zavialov at 2026-04-28T13:23:29-04:00
Refactor HsWildCardTy to use HoleKind (#27111)
The payload of this patch is that the extension fields of HsWildCardTy
and HsHole now match:
type instance XWildCardTy Ghc{Ps,Rn} = HoleKind
type instance XHole Ghc{Ps,Rn} = HoleKind
This is progress towards unification of HsExpr and HsType.
Test case: T25121_status
In addition to that, exact-printing of infix holes is fixed.
Test case: PprInfixHole
- - - - -
f3485446 by fendor at 2026-04-28T13:24:12-04:00
Expose startupHpc as an rts symbol
- - - - -
28f07d70 by fendor at 2026-04-28T13:24:12-04:00
Make HPC work with bytecode interpreter
Add support to generate .tix files from bytecode objects and the
bytecode interpreter.
Conceptually, we insert HPC ticks into the bytecode similar to how we insert
breakpoints.
HPC and breakpoints do not share the same tick array but we use a separate
tick-array for hpc/breakpoint ticks during bytecode generation.
We teach the bytecode interpreter to handle hpc ticks.
The implementation is quite trivial, simply increment the counter in the
global hpc_ticks array for the respective module.
This hpc_ticks array is generated as part of the `CStub`, so we can rely
on it existing.
A tricky bit is "registering" a bytecode object for HPC instrumentation.
In the compiled case, this is achieved via CStub and initializer/finalizers
`.init` sections which are called when the executable is run.
After the initializers have been invoked, which is before `hs_init_ghc`,
we then call `startup_hpc` in `hs_init_ghc` iff any modules were "registered"
for hpc instrumentation via `hs_hpc_module`.
Since bytecode objects are loaded after starting up GHCi, this workflow
doesn't work for supporting `hpc` and the `hpc` run-time is never
started, even if a module is added for instrumentation.
We fix this issue by employing the same technique as is for `SptEntry`s:
* We introduce a new field to `CompiledByteCode`, called `ByteCodeHpcInfo`
which contains enough information to call `hs_hpc_module`, allowing us to
register the module for `hpc` instrumentation`.
* After registering the module, we unconditionally call `startupHpc`, to make
sure the .tix file is written.
Calling `startupHpc` multiple times is safe.
Calling `hs_hpc_module` multiple times for the same module is also safe.
If we didn't register the hpc module in this way, evaluating a bytecode object
instrumented with `-fhpc` without registering it in the `hpc` run-time will
simply not generate any `.tix` files for this bytecode object.
However, this shouldn't happen if everything is set up correctly.
Closes #27036
- - - - -
950879f0 by Vladislav Zavialov at 2026-04-28T13:24:55-04:00
Move NamespaceSpecifier from x-fields into the AST proper (#26678)
This refactoring moves NamespaceSpecifier out of extension fields and into the
AST proper, as it is part of the user-written source, and is not pass-specific.
Summary of changes:
* Move NamespaceSpecifier from GHC/Hs/Basic.hs to Language/Haskell/Syntax/ImpExp.hs
and parameterise it by the compiler pass, creating the necessary extension points
* Move NamespaceSpecifier out of XFixitySig into FixitySig
* Move NamespaceSpecifier out of XIEThingAll (IEThingAllExt) into IEThingAll
* Move NamespaceSpecifier out of XIEWholeNamespace (IEWholeNamespaceExt) into IEWholeNamespace
This is a pure refactoring with no change in behaviour.
- - - - -
9797052b by Simon Peyton Jones at 2026-04-28T13:25:37-04:00
Fix assertion check in checkResultTy
As #27210 shows, the assertion was a little bit too eager.
I refactored a bit by moving some code from GHC.Tc.Gen.App
to GHC.Tc.Utils.Unify; see the new function tcSubTypeApp,
which replaces tcSubTypeDS
- - - - -
9f85f034 by Duncan Coutts at 2026-04-30T04:52:42-04:00
Make cmm 'import "package" name;' syntax use consistent label types
There is a little-used syntactic form in cmm imports:
import "package" foo;
Which means to import foo from the given package (unit id, specified as
a string). This syntax is somewhat reminiscent of GHC's package import
extension.
This syntax form is not used in the rts cmm code, nor any of the boot
libraries. It may not be used at all. Unclear.
Change the kind of CLabel this syntax generates to be consistent with
the others. The other cmm imports use ForeignLabel with
ForeignLabelInExternalPackage. For some reason this form was using
CmmLabel. Change that to also be ForeignLabel but with
ForeignLabelInPackage. This specifies a specific package, rather
than an unnamed external package.
- - - - -
a811f68f by Duncan Coutts at 2026-04-30T04:52:42-04:00
Change default cmm import statements to be internal
Previously a cmm statement like:
import foo;
meant to expect the symbol from a different shared library than the
current one.
Now it means to expect the symbol from the same shared library as the
current one. We'll add explicit syntax to indicate that it's a foreign
import. Most existing uses are in fact intenal (rts to rts), so few
imports will need to be annotated foreign. Examples would include cmm
code in libraries (other than the rts) that need to access RTS APIs.
In practice, this makes no difference whatsoever at the moment on any
platform other than windows (where building Haskell libs as shared libs
does not fully work yet), since the 'labelDynamic' treats all such
labels as foreign, irrespective of the foreign label source.
- - - - -
17fe5d1d by Duncan Coutts at 2026-04-30T04:52:42-04:00
Add cmm import syntax 'import DATA foo;' as better name for CLOSURE
The existing syntax is:
import CLOSURE foo;
The new syntax is
import DATA foo;
This means to interpret the symbol foo as refering to data (i.e. a
global constant or variable) rather than to code (a function). The
historical syntax for this uses CLOSURE, which is rather misleading.
Presumably this was done to avoid introducing new reserved words.
Be less squemish about new reserved words and add DATA and use that.
Keep the existing CLOSURE syntax as an alias for compatibility.
- - - - -
3a530d68 by Duncan Coutts at 2026-04-30T04:52:42-04:00
Add cmm 'import extern name;' syntax
Since the default for cmm imports is now for symbols within the same
shared object, we need a way to indicate we want a symbol from an
external shared object:
import extern foo; -- for a function
import extern DATA foo; -- for data
This adds a new reserved word 'extern'.
We don't expect to have to use this much. Most cmm imports are
intra-DSO.
This makes no difference currently on ELF and MachO platforms, but does
make a difference to the linking conventions on PE (Windows).
In future it's plausible we could take make distinctions on ELF or
MachO, so it's worth trying to get it right. Windows can be the guinea
pig.
- - - - -
2b8e44c7 by Duncan Coutts at 2026-04-30T04:52:42-04:00
Add cmm syntax 'import "package" DATA foo;' for completeness
We already have:
import DATA foo; -- for data imports
import "package" foo; -- for imports from a given unitid
There's no reason not to have both at once:
import "package" DATA foo;
So add that.
- - - - -
ee05e5cc by Duncan Coutts at 2026-04-30T04:52:42-04:00
Improve the commentary for the cmm import grammar.
AFAIK, this is the only place where GHC-style Cmm syntax is documented.
- - - - -
b35946ad by Duncan Coutts at 2026-04-30T04:52:42-04:00
Add a changelog.d entry for the .cmm import syntax changes
- - - - -
d59b7c71 by Wolfgang Jeltsch at 2026-04-30T04:53:25-04:00
Move code that uses `GHC.Internal.Text.Read` into `base`
This contribution serves to remove all dependencies on
`GHC.Internal.Text.Read` from within `ghc-internal`, so that the
implementation of `Text.Read` and ultimately more reading-related code
can be moved to `base` as well.
The following things are moved from `ghc-internal` to `base`:
* I/O-related `Read` instances
* Most of the `Numeric` implementation
* The instance `Read ByteOrder`
* The `parseVersion` operation
* The `readConstr` operation
Metric Increase:
LinkableUsage01
T9198
T12425
T13035
T13820
T18140
- - - - -
5bd6a964 by Rodrigo Mesquita at 2026-04-30T04:54:08-04:00
New rts Message to {set,unset} TSO flags
This commit introduces stg_MSG_SET_TSO_FLAG_info and
stg_MSG_UNSET_TSO_FLAG_info, which allows setting flags of a TSO other
than yourself.
This is especially useful/necessary to set breakpoints and toggle
breakpoints of different threads, which is needed to safely implement
features like pausing, toggling step-out, toggling step-in per thread,
etc.
Fixes #27131
-------------------------
Metric Decrease:
T3294
-------------------------
- - - - -
ce97fd3e by Rodrigo Mesquita at 2026-04-30T04:54:08-04:00
test: Add test setting another TSO's flags
Introduces a test that runs on two capabilities. The main thread running
on Capability 0 sets the flags on a TSO running on Capability 1.
The TSO from Capability 1 itself checks whether its flags were set and
reports that back.
This validates that the RTS messages for setting TSO flags work, even if
it doesn't test a harsher scenario with race conditions to exercise why
the message passing is necessary for safely setting another TSO's flags.
Part of #27131
- - - - -
a4ff6315 by David Eichmann at 2026-04-30T04:54:51-04:00
Hadrian: withResponseFile outputs response file when verbodity is Verbose
At the Verbose verbosity, shake will display full commandlines. With the
use of response files, the full command is hidden. That makes it hard to run
the command manually. This commit outputs the contents of the response
file so that that full command can be recreated and also hints at the
use of the --keep-response-files hadrian flag.
- - - - -
cd732ee3 by Duncan Coutts at 2026-04-30T04:54:51-04:00
Use response files for hadrian linking with ghc (support long command lines)
In future support for windows dynamic linking, we expect long command
lines for linking dll files with ghc. Experiments with dynamic linking the
ghc-internal library yielded a link command well over 32kb. We did not
encounter this before for static libs, since we already use ar's @file
feature (if available, which it is for the llvm toolchain).
Co-authored-by: David Eichmann <davide(a)well-typed.com>
- - - - -
3d41368f by Andreas Klebinger at 2026-04-30T04:55:32-04:00
Split GHC.Driver.Main.hs up into multiple components.
This commit splits GHC.Driver.Main into four components:
* GHC.Driver.Main.Compile
* GHC.Driver.Main.Hsc
* GHC.Driver.Main.Interactive
* GHC.Driver.Main.Passes
We might improve that separation further in the future but this should
hopefully make it easier to reason about and work with this part of the
code.
- - - - -
2128ba85 by Cheng Shao at 2026-04-30T04:56:14-04:00
compiler: avoid unique OccNames for internal Names in bytecode objects
This patch improves bytecode object serialization logic by avoiding
the construction of unique `OccName`s when serializing/deserializing
internal `Name`s. Closes #27213.
-------------------------
Metric Decrease:
LinkableUsage01
-------------------------
- - - - -
e16854c3 by Vladislav Zavialov at 2026-04-30T04:56:57-04:00
Replace GHC 9.16 references with GHC 10.0
- - - - -
39141343 by Alice Rixte at 2026-05-01T14:09:32+02:00
Add Bounded instances for Double, Float, CDouble and CFloat
- - - - -
5c4c3bf4 by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: fix flaky foundation Divisible / mulIntMayOflo# tests (#27222)
Since the LCG was widened to 64 bits and the seed randomised per CI run
(commit 2d30f7d3400 "Vendor mini-QuickCheck for testsuite"), two latent
bugs in the foundation test surface stochastically:
* The Divisible property `(x `div` y) * y + (x `mod` y) == x` raises
ArithException(Overflow) when (a, b) = (minBound, -1) for fixed-width
signed Integral types. Split testNumber/testDivisible into Bounded and
unbounded variants and skip just that one pair, gated by
`(minBound :: a) < 0` so unsigned types lose no coverage.
* The `mulIntMayOflo#` test compared raw Int# bit-for-bit, but the primop
is only specified to return 0/non-zero -- the exact non-zero indicator
legitimately differs between backends and inlining choices. Add a
dedicated `testPrimopMayOflo` helper that only compares zero / non-zero.
Also fix the long-standing typo "Dividible" -> "Divisible" in identifiers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
e242ce4f by Sylvain Henry at 2026-05-02T03:39:28-04:00
testsuite: catch and display exceptions in MiniQuickCheck
Exceptions raised while evaluating a property are now caught and reported
as a normal failure (with arguments and seed), instead of aborting the
test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply(a)anthropic.com>
- - - - -
3b75cccd by fendor at 2026-05-02T03:40:14-04:00
Fix name of Note [Structure of dep_boot_mods]
- - - - -
6657628d by Andreas Klebinger at 2026-05-05T10:11:06+00:00
SOURCE import parseIdentifer to improve parallelism.
- - - - -
65860ded by Andreas Klebinger at 2026-05-05T10:11:06+00:00
CallerCC: Remove CoreM dependency
Pass DynFlags directly, making the dependency graph more parallel.
- - - - -
447b4927 by Andreas Klebinger at 2026-05-05T10:17:57+00:00
Use SOURCE-imports to improve build parallelism.
This commut introduces SOURCE imports to use hs-boot files as a sort of
header file. See Note [hs-boot files as "header" files].
The gist of it is we use SOURCE imports to compile some dependant modules
merely against the interface of their import rather than against the
full implementation. Allowing the brunt of the dependent module to be
compiled in parallel with it's import.
Particular modules for which we did this:
* SOURCE-import HsInstances inside ghc. Fixes #27198 by SOURCE importing
HsInstances unlocking more build paralleism.
* SOURCE import GHC.Types.Error in some places for build parallelism.
* GHC.HsToCore (deSugar)
* GHC.Tc.Deriv.hs-boot
* GHC.Driver.Main.Compile/Passes
- - - - -
319 changed files:
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- .gitlab/merge_request_templates/Default.md
- + changelog.d/T19174.md
- + changelog.d/T27131
- + changelog.d/binary-array-no-list
- + changelog.d/bytecode-interpreter-hpc-support
- + changelog.d/cmm-import-syntax-changes
- + changelog.d/fix-finalizers-27072
- + changelog.d/ghc-api-holes-ast-27111
- + changelog.d/ghc-api-namespace-specifier-26678
- + changelog.d/hadrian-response-files.md
- + changelog.d/llvm-22
- + changelog.d/simd_constant_folding
- + changelog.d/tcplugin_init.md
- + changelog.d/tcplugins-pmc.md
- + changelog.d/typecheckModule-API.md
- + changelog.d/withTcPlugins.md
- compiler/GHC.hs
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Binary.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Cmm/Lexer.x
- compiler/GHC/Cmm/Opt.hs
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/Core/Opt/CallerCC.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/Stats.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Data/Pair.hs
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/CodeOutput.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- + compiler/GHC/Driver/Main/Compile.hs
- compiler/GHC/Driver/Main.hs-boot → compiler/GHC/Driver/Main/Compile.hs-boot
- + compiler/GHC/Driver/Main/Hsc.hs
- + compiler/GHC/Driver/Main/Interactive.hs
- + compiler/GHC/Driver/Main/Passes.hs
- + compiler/GHC/Driver/Main/Passes.hs-boot
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Monad.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs.hs
- compiler/GHC/Hs/Basic.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Expr.hs-boot
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Hs/Instances.hs
- + compiler/GHC/Hs/Instances.hs-boot
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore.hs
- + compiler/GHC/HsToCore.hs-boot
- compiler/GHC/HsToCore/Coverage.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Pmc.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Linker/Executable.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/StgToByteCode.hs
- + compiler/GHC/Tc/Deriv.hs-boot
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Export.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/TyCl/Instance.hs-boot
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Error.hs
- compiler/GHC/Types/Error.hs-boot
- compiler/GHC/Types/ForeignStubs.hs
- compiler/GHC/Types/HpcInfo.hs
- compiler/GHC/Types/Name/Reader.hs
- compiler/GHC/Types/Unique/DSet.hs
- compiler/GHC/Unit/Module/Deps.hs
- compiler/GHC/Unit/Module/ModGuts.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Misc.hs
- compiler/GHC/Utils/Ppr/Colour.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/ImpExp.hs
- compiler/ghc.cabal.in
- configure.ac
- docs/users_guide/debug-info.rst
- docs/users_guide/extending_ghc.rst
- docs/users_guide/exts/explicit_namespaces.rst
- docs/users_guide/exts/linear_types.rst
- docs/users_guide/exts/modifiers.rst
- docs/users_guide/exts/qualified_strings.rst
- docs/users_guide/exts/required_type_arguments.rst
- docs/users_guide/using-warnings.rst
- docs/users_guide/using.rst
- ghc/GHC/Driver/Session/Mode.hs
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Info.hs
- ghc/Main.hs
- ghc/ghc-bin.cabal.in
- hadrian/build-cabal.bat
- hadrian/doc/flavours.md
- hadrian/src/Builder.hs
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Builder.hs
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- hadrian/src/Settings/Builders/Ghc.hs
- hadrian/src/Settings/Packages.hs
- libraries/base/changelog.md
- libraries/base/src/Control/Concurrent.hs
- libraries/base/src/Data/Data.hs
- libraries/base/src/Data/Version.hs
- libraries/base/src/GHC/ByteOrder.hs
- libraries/base/src/GHC/IO/Handle.hs
- libraries/base/src/Numeric.hs
- libraries/base/src/Prelude.hs
- libraries/base/src/System/IO.hs
- libraries/base/src/Text/Printf.hs
- libraries/ghc-internal/include/CTypes.h
- libraries/ghc-internal/src/GHC/Internal/Data/Data.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Version.hs
- libraries/ghc-internal/src/GHC/Internal/Float.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Device.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO/IOMode.hs
- libraries/ghc-internal/src/GHC/Internal/Numeric.hs
- libraries/ghc-internal/src/GHC/Internal/Read.hs
- libraries/ghc-internal/src/GHC/Internal/System/IO.hs
- + libraries/ghci/GHCi/Coverage.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs
- libraries/ghci/ghci.cabal.in
- rts/Disassembler.c
- rts/Hpc.c
- rts/Interpreter.c
- rts/Linker.c
- rts/LinkerInternals.h
- rts/Messages.c
- rts/RtsSymbols.c
- rts/StgMiscClosures.cmm
- rts/Threads.c
- rts/Threads.h
- rts/include/rts/Bytecodes.h
- rts/include/rts/storage/Closures.h
- rts/include/stg/MiscClosures.h
- rts/linker/Elf.c
- testsuite/driver/testlib.py
- + testsuite/tests/MiniQuickCheck.hs
- + testsuite/tests/codeGen/should_run/T27072d.hs
- + testsuite/tests/codeGen/should_run/T27072d.stdout
- + testsuite/tests/codeGen/should_run/T27072d_c.c
- + testsuite/tests/codeGen/should_run/T27072d_check.c
- + testsuite/tests/codeGen/should_run/T27072w.hs
- + testsuite/tests/codeGen/should_run/T27072w.stdout
- + testsuite/tests/codeGen/should_run/T27072w_c.c
- testsuite/tests/codeGen/should_run/all.T
- + testsuite/tests/driver/T10531/A.hs
- + testsuite/tests/driver/T10531/B.hs
- + testsuite/tests/driver/T10531/C.hs
- + testsuite/tests/driver/T10531/Makefile
- + testsuite/tests/driver/T10531/all.T
- testsuite/tests/ghc-api/T25121_status.stdout
- testsuite/tests/ghc-api/T26910.hs
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghci/should_run/tc-plugin-ghci/TcPluginGHCi.hs
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/hpc/Makefile
- testsuite/tests/hpc/T17073.stdout → testsuite/tests/hpc/T17073a.stdout
- + testsuite/tests/hpc/T17073b.stdout
- testsuite/tests/hpc/T20568.stdout → testsuite/tests/hpc/T20568a.stdout
- + testsuite/tests/hpc/T20568b.stdout
- testsuite/tests/hpc/all.T
- testsuite/tests/hpc/fork/Makefile
- testsuite/tests/hpc/function/Makefile
- testsuite/tests/hpc/function/test.T
- + testsuite/tests/hpc/function/tough1.stderr
- + testsuite/tests/hpc/function/tough1.stdout
- testsuite/tests/hpc/function2/test.T
- + testsuite/tests/hpc/function2/tough3.script
- + testsuite/tests/hpc/ghc_ghci/BytecodeMain.hs
- testsuite/tests/hpc/ghc_ghci/Makefile
- + testsuite/tests/hpc/ghc_ghci/hpc_ghc_ghci_bytecode.stdout
- + testsuite/tests/hpc/ghc_ghci/hpc_ghci01.stdout
- + testsuite/tests/hpc/ghc_ghci/hpc_ghci02.stdout
- testsuite/tests/hpc/ghc_ghci/test.T
- testsuite/tests/hpc/simple/Makefile
- + testsuite/tests/hpc/simple/hpc002.hs
- + testsuite/tests/hpc/simple/hpc002.stdout
- + testsuite/tests/hpc/simple/hpc003.hs
- + testsuite/tests/hpc/simple/hpc003.script
- + testsuite/tests/hpc/simple/hpc003.stdout
- testsuite/tests/hpc/simple/test.T
- 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/base-exports.stdout-ws-32
- testsuite/tests/linters/notes.stdout
- testsuite/tests/numeric/should_run/all.T
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/echo-plugin/Echo.hs
- testsuite/tests/plugins/plugins09.stdout
- testsuite/tests/plugins/plugins10.stdout
- testsuite/tests/plugins/plugins11.stdout
- testsuite/tests/plugins/static-plugins.stdout
- testsuite/tests/printer/Makefile
- + testsuite/tests/printer/PprInfixHole.hs
- testsuite/tests/printer/all.T
- testsuite/tests/quasiquotation/T7918.hs
- + testsuite/tests/rts/T27131.hs
- + testsuite/tests/rts/T27131.stdout
- + testsuite/tests/rts/T27131_c.c
- testsuite/tests/rts/all.T
- + testsuite/tests/rts/linker/T27072/Lib.c
- + testsuite/tests/rts/linker/T27072/Makefile
- + testsuite/tests/rts/linker/T27072/T27072.stdout
- + testsuite/tests/rts/linker/T27072/all.T
- + testsuite/tests/rts/linker/T27072/main.c
- + testsuite/tests/simd/should_run/Makefile
- + testsuite/tests/simd/should_run/T25030.hs
- + testsuite/tests/simd/should_run/T25030.stdout
- testsuite/tests/simd/should_run/all.T
- testsuite/tests/simd/should_run/simd006.hs
- testsuite/tests/tcplugins/Common.hs
- testsuite/tests/tcplugins/RewritePerfPlugin.hs
- testsuite/tests/tcplugins/T11462_Plugin.hs
- testsuite/tests/tcplugins/T11525_Plugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.script
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stdout
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs-boot
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode_aux.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.stderr
- testsuite/tests/tcplugins/all.T
- + testsuite/tests/tcplugins/tc-plugin-initstop/Makefile
- + testsuite/tests/tcplugins/tc-plugin-initstop/Setup.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/TcPlugin_InitStop_Plugin.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/tc-plugin-initstop.cabal
- testsuite/tests/th/all.T
- testsuite/tests/typecheck/should_compile/T9497a.stderr
- testsuite/tests/typecheck/should_compile/holes.stderr
- testsuite/tests/typecheck/should_compile/holes3.stderr
- testsuite/tests/typecheck/should_compile/valid_hole_fits.stderr
- + testsuite/tests/typecheck/should_fail/T27210.hs
- + testsuite/tests/typecheck/should_fail/T27210.stderr
- testsuite/tests/typecheck/should_fail/T9497d.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_run/T9497a-run.stderr
- testsuite/tests/typecheck/should_run/T9497b-run.stderr
- testsuite/tests/typecheck/should_run/T9497c-run.stderr
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- utils/check-exact/ExactPrint.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
- utils/haddock/html-test/ref/Bug1004.html
- utils/haddock/html-test/ref/Bug973.html
- utils/haddock/html-test/ref/ConstructorPatternExport.html
- utils/haddock/html-test/ref/DefaultSignatures.html
- utils/haddock/html-test/ref/Hash.html
- utils/haddock/html-test/ref/PatternSyns.html
- utils/haddock/html-test/ref/PatternSyns2.html
- utils/haddock/html-test/ref/QuasiExpr.html
- utils/haddock/html-test/ref/Test.html
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b4b25892e39e9c6c787669ccbaf62c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b4b25892e39e9c6c787669ccbaf62c…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
05 May '26
Magnus pushed new branch wip/mangoiv/ci-backports at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/mangoiv/ci-backports
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/supersven/libDir-setting] WIP: Relative LibDir is relative to topDir
by Sven Tennie (@supersven) 05 May '26
by Sven Tennie (@supersven) 05 May '26
05 May '26
Sven Tennie pushed to branch wip/supersven/libDir-setting at Glasgow Haskell Compiler / GHC
Commits:
67aac579 by Sven Tennie at 2026-05-05T11:29:10+02:00
WIP: Relative LibDir is relative to topDir
- - - - -
2 changed files:
- compiler/GHC/Settings/IO.hs
- hadrian/src/Rules/Generate.hs
Changes:
=====================================
compiler/GHC/Settings/IO.hs
=====================================
@@ -152,9 +152,13 @@ initSettings top_dir = do
-- LibDir is optional. If not set, derive it from topDir. This allows
-- bindists to work without explicitly setting LibDir, but gives us the
-- option to override it for inplace test compilers (the "stage2
- -- cross-compiler" scenario).
- let lib_dir = fromRight top_dir $
- getRawFilePathSetting top_dir settingsFile mySettings "LibDir"
+ -- cross-compiler" scenario). If LibDir is a relative path, it is
+ -- interpreted relative to topDir.
+ let lib_dir_raw = fromRight top_dir $
+ getRawFilePathSetting top_dir settingsFile mySettings "LibDir"
+ lib_dir = if isRelative lib_dir_raw
+ then top_dir </> lib_dir_raw
+ else lib_dir_raw
return $ Settings
{ sGhcNameVersion = GhcNameVersion
=====================================
hadrian/src/Rules/Generate.hs
=====================================
@@ -491,7 +491,8 @@ generateSettings settingsFile includeLibDir package_db_path = do
-- So, we need to decrement the stage to get the correct directory
stage_dir_stage = predStage stage
- rel_lib_topDir :: FilePath <- expr $ stageLibPath stage_dir_stage
+ lib_topDir :: FilePath <- expr $ stageLibPath stage_dir_stage
+ let rel_lib_topDir = makeRelativeNoSysLink (dropFileName settingsFile) lib_topDir
settings <- traverse sequence $
[ ("unlit command", ("$topdir/../bin/" <>) <$> expr (programName (ctx { Context.package = unlit })))
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/67aac57907a85a545a741bca309b7eb…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/67aac57907a85a545a741bca309b7eb…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/supersven/libDir-setting] WIP: Relative LibDir is relative to topDir
by Sven Tennie (@supersven) 05 May '26
by Sven Tennie (@supersven) 05 May '26
05 May '26
Sven Tennie pushed to branch wip/supersven/libDir-setting at Glasgow Haskell Compiler / GHC
Commits:
7792d0a4 by Sven Tennie at 2026-05-05T08:14:22+02:00
WIP: Relative LibDir is relative to topDir
- - - - -
1 changed file:
- compiler/GHC/Settings/IO.hs
Changes:
=====================================
compiler/GHC/Settings/IO.hs
=====================================
@@ -152,9 +152,13 @@ initSettings top_dir = do
-- LibDir is optional. If not set, derive it from topDir. This allows
-- bindists to work without explicitly setting LibDir, but gives us the
-- option to override it for inplace test compilers (the "stage2
- -- cross-compiler" scenario).
- let lib_dir = fromRight top_dir $
- getRawFilePathSetting top_dir settingsFile mySettings "LibDir"
+ -- cross-compiler" scenario). If LibDir is a relative path, it is
+ -- interpreted relative to topDir.
+ let lib_dir_raw = fromRight top_dir $
+ getRawFilePathSetting top_dir settingsFile mySettings "LibDir"
+ lib_dir = if isRelative lib_dir_raw
+ then top_dir </> lib_dir_raw
+ else lib_dir_raw
return $ Settings
{ sGhcNameVersion = GhcNameVersion
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7792d0a446bbffd0aa580c56bb41b1b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7792d0a446bbffd0aa580c56bb41b1b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0