Ben Gamari pushed to branch ghc-9.14 at Glasgow Haskell Compiler / GHC
Commits:
-
4d8eec9a
by Ben Gamari at 2025-09-02T08:58:18-04:00
-
0980f3d6
by Ben Gamari at 2025-09-02T08:58:53-04:00
-
5f9c0b62
by Ben Gamari at 2025-09-02T08:58:53-04:00
7 changed files:
- docs/users_guide/9.14.1-notes.rst
- rts/PrimOps.cmm
- rts/RaiseAsync.c
- rts/STM.c
- − testsuite/tests/lib/stm/T26028.hs
- − testsuite/tests/lib/stm/T26028.stdout
- − testsuite/tests/lib/stm/all.T
Changes:
... | ... | @@ -25,6 +25,14 @@ Language |
25 | 25 | This deprecation is controlled by the newly introduced ``-Wdeprecated-pragmas``
|
26 | 26 | flag in ``-Wdefault``.
|
27 | 27 | |
28 | +* Visible ``GADT`` syntax can now be used in GADT data constructors (:ghc-ticket:`25127`) ::
|
|
29 | + |
|
30 | + data KindVal a where
|
|
31 | + K :: forall k.
|
|
32 | + forall (a::k) -> -- now allowed!
|
|
33 | + k ->
|
|
34 | + KindVal a
|
|
35 | + |
|
28 | 36 | * ``-Wincomplete-record-selectors`` is now part of `-Wall`, as specified
|
29 | 37 | by `GHC Proposal 516: add warning for incomplete record selectors <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0516-incomplete-record-selectors.rst>`_.
|
30 | 38 | Hence, if a library is compiled with ``-Werror``, compilation may now fail. Solution: fix the library.
|
... | ... | @@ -52,7 +60,7 @@ Language |
52 | 60 | |
53 | 61 | That will break the combination of :extension:`OverloadedRecordUpdate` with :extension:`RebindableSyntax`.
|
54 | 62 | |
55 | -* Multiline strings are now accepted in foreign imports. (#25157)
|
|
63 | +* Multiline strings are now accepted in ``foreign import``\ s. (#25157)
|
|
56 | 64 | |
57 | 65 | * GHC now does a better job at inferring types in calls to ``coerce``: instead of
|
58 | 66 | complaining about ambiguous type variables, GHC will consider that such type
|
... | ... | @@ -73,7 +81,7 @@ Language |
73 | 81 | * The ``-Wdata-kinds-tc`` warning has been deprecated, and the use of promoted
|
74 | 82 | data types in kinds is now an error (rather than a warning) unless the
|
75 | 83 | :extension:`DataKinds` extension is enabled. For example, the following code
|
76 | - will be rejected unless :extension:`DataKinds` is on:
|
|
84 | + will be rejected unless :extension:`DataKinds` is on: ::
|
|
77 | 85 | |
78 | 86 | import Data.Kind (Type)
|
79 | 87 | import GHC.TypeNats (Nat)
|
... | ... | @@ -99,6 +107,9 @@ Language |
99 | 107 | |
100 | 108 | See :ref:`visible-forall-in-gadts` for details.
|
101 | 109 | |
110 | +- Explicit level import support, allowing ``import`` declarations to explicitly
|
|
111 | + state which compilation stages they are are visible to.
|
|
112 | + |
|
102 | 113 | Compiler
|
103 | 114 | ~~~~~~~~
|
104 | 115 | |
... | ... | @@ -143,20 +154,27 @@ Compiler |
143 | 154 | were accessed using the generated record selector functions, marking the fields
|
144 | 155 | as covered in coverage reports (:ghc-ticket:`17834`).
|
145 | 156 | |
146 | -- SIMD support in the X86 native code generator has been extended with 128-bit
|
|
157 | +- SIMD support in the x86 native code generator has been extended with 128-bit
|
|
147 | 158 | integer operations. Also, ``shuffleFloatX4#`` and ``shuffleDoubleX2#`` no longer
|
148 | 159 | require ``-mavx``.
|
149 | 160 | |
161 | +- Initial native code generator support for the LoongArch CPU architecture.
|
|
162 | + |
|
163 | + |
|
150 | 164 | GHCi
|
151 | 165 | ~~~~
|
152 | 166 | |
153 | -- :ghci-cmd:`:info` now outputs type declarations with @-binders that are
|
|
167 | +- Multiple home unit support in GHCi
|
|
168 | + |
|
169 | +- :ghci-cmd:`:info` now outputs type declarations with ``@``-binders that are
|
|
154 | 170 | considered semantically significant. See the documentation for :ghci-cmd:`:info`
|
155 | 171 | itself for a more detailed explanation.
|
156 | 172 | |
157 | 173 | - GHCi errors and warnings now have their own numeric error codes that are
|
158 | 174 | displayed alongside the error.
|
159 | 175 | |
176 | +- Many performance and correctness improvements in the bytecode interpreter.
|
|
177 | + |
|
160 | 178 | Runtime system
|
161 | 179 | ~~~~~~~~~~~~~~
|
162 | 180 | |
... | ... | @@ -176,40 +194,40 @@ Cmm |
176 | 194 | ``ghc`` library
|
177 | 195 | ~~~~~~~~~~~~~~~
|
178 | 196 | |
179 | -* The `UnknownDiagnostic` constructor now takes an additional type argument
|
|
197 | +* The ``UnknownDiagnostic`` constructor now takes an additional type argument
|
|
180 | 198 | for the type of hints corresponding to the diagnostic, and an additional
|
181 | 199 | value-level argument used for existential wrapping of the hints of the inner
|
182 | 200 | diagnostic.
|
183 | 201 | |
184 | 202 | * Changes to the HPT and HUG interface:
|
185 | 203 | |
186 | - - `addToHpt` and `addListToHPT` were moved from `GHC.Unit.Home.ModInfo` to `GHC.Unit.Home.PackageTable` and deprecated in favour of `addHomeModInfoToHpt` and `addHomeModInfosToHpt`.
|
|
187 | - - `UnitEnvGraph` and operations `unitEnv_lookup_maybe`, `unitEnv_foldWithKey, `unitEnv_singleton`, `unitEnv_adjust`, `unitEnv_insert`, `unitEnv_new` were moved from `GHC.Unit.Env` to `GHC.Unit.Home.Graph`.
|
|
188 | - - The HomePackageTable (HPT) is now exported from `GHC.Unit.Home.PackageTable`,
|
|
204 | + - ``addToHpt`` and ``addListToHPT`` were moved from ``GHC.Unit.Home.ModInfo`` to ``GHC.Unit.Home.PackageTable`` and deprecated in favour of ``addHomeModInfoToHpt`` and ``addHomeModInfosToHpt``.
|
|
205 | + - ``UnitEnvGraph`` and operations ``unitEnv_lookup_maybe``, ``unitEnv_foldWithKey, ``unitEnv_singleton``, ``unitEnv_adjust``, ``unitEnv_insert``, ``unitEnv_new`` were moved from ``GHC.Unit.Env`` to ``GHC.Unit.Home.Graph``.
|
|
206 | + - The HomePackageTable (HPT) is now exported from ``GHC.Unit.Home.PackageTable``,
|
|
189 | 207 | and is now backed by an IORef to avoid by construction very bad memory leaks.
|
190 | 208 | This means the API to the HPT now is for the most part in IO. For instance,
|
191 | - `emptyHomePackageTable` and `addHomeModInfoToHpt` are now in IO.
|
|
192 | - - `mkHomeUnitEnv` was moved to `GHC.Unit.Home.PackageTable`, and now takes two
|
|
193 | - extra explicit arguments. To restore previous behaviour, pass `emptyUnitState`
|
|
194 | - and `Nothing` as the first two arguments additionally.
|
|
195 | - - `hugElts` was removed. Users should prefer `allUnits` to get the keys of the
|
|
196 | - HUG (the typical use case), or `traverse` or `unitEnv_foldWithKey` in other
|
|
209 | + ``emptyHomePackageTable`` and ``addHomeModInfoToHpt`` are now in IO.
|
|
210 | + - ``mkHomeUnitEnv`` was moved to ``GHC.Unit.Home.PackageTable``, and now takes two
|
|
211 | + extra explicit arguments. To restore previous behaviour, pass ``emptyUnitState``
|
|
212 | + and ``Nothing`` as the first two arguments additionally.
|
|
213 | + - ``hugElts`` was removed. Users should prefer ``allUnits`` to get the keys of the
|
|
214 | + HUG (the typical use case), or ``traverse`` or ``unitEnv_foldWithKey`` in other
|
|
197 | 215 | cases.
|
198 | 216 | |
199 | -* Changes to `Language.Haskell.Syntax.Expr`
|
|
217 | +* Changes to ``Language.Haskell.Syntax.Expr``
|
|
200 | 218 | |
201 | - - The `ParStmtBlock` list argument of the `ParStmt` constructor of `StmtLR` is now `NonEmpty`.
|
|
219 | + - The ``ParStmtBlock`` list argument of the ``ParStmt`` constructor of ``StmtLR`` is now ``NonEmpty``.
|
|
202 | 220 | |
203 | -* As part of the implementation of `GHC proposal 493 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0493-specialise-expressions.rst>`_,
|
|
204 | - the `SpecSig` constructor of `Sig` has been deprecated. It is replaced by
|
|
205 | - the constructor `SpecSigE` which supports expressions at the head, rather than
|
|
221 | +* As part of the implementation of ``GHC proposal 493 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0493-specialise-expressions.rst>``_,
|
|
222 | + the ``SpecSig`` constructor of ``Sig`` has been deprecated. It is replaced by
|
|
223 | + the constructor ``SpecSigE`` which supports expressions at the head, rather than
|
|
206 | 224 | a lone variable.
|
207 | 225 | |
208 | 226 | ``ghc-heap`` library
|
209 | 227 | ~~~~~~~~~~~~~~~~~~~~
|
210 | 228 | |
211 | -* The functions `getClosureInfoTbl_maybe`, `getClosureInfoTbl`,
|
|
212 | - `getClosurePtrArgs` and `getClosurePtrArgs_maybe` have been added to allow
|
|
229 | +* The functions ``getClosureInfoTbl_maybe``, ``getClosureInfoTbl``,
|
|
230 | + ``getClosurePtrArgs`` and ``getClosurePtrArgs_maybe`` have been added to allow
|
|
213 | 231 | reading of the relevant Closure attributes without reliance on incomplete
|
214 | 232 | selectors.
|
215 | 233 | |
... | ... | @@ -225,7 +243,6 @@ Cmm |
225 | 243 | ``ghc-experimental`` versions.
|
226 | 244 | |
227 | 245 | |
228 | - |
|
229 | 246 | ``template-haskell`` library
|
230 | 247 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
231 | 248 |
... | ... | @@ -1210,27 +1210,16 @@ INFO_TABLE_RET(stg_catch_retry_frame, CATCH_RETRY_FRAME, |
1210 | 1210 | gcptr trec, outer, arg;
|
1211 | 1211 | |
1212 | 1212 | trec = StgTSO_trec(CurrentTSO);
|
1213 | - if (running_alt_code != 1) {
|
|
1214 | - // When exiting the lhs code of catchRetry# lhs rhs, we need to cleanup
|
|
1215 | - // the nested transaction.
|
|
1216 | - // See Note [catchRetry# implementation]
|
|
1217 | - outer = StgTRecHeader_enclosing_trec(trec);
|
|
1218 | - (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
|
|
1219 | - if (r != 0) {
|
|
1220 | - // Succeeded in first branch
|
|
1221 | - StgTSO_trec(CurrentTSO) = outer;
|
|
1222 | - return (ret);
|
|
1223 | - } else {
|
|
1224 | - // Did not commit: abort and restart.
|
|
1225 | - StgTSO_trec(CurrentTSO) = outer;
|
|
1226 | - jump stg_abort();
|
|
1227 | - }
|
|
1228 | - }
|
|
1229 | - else {
|
|
1230 | - // nothing to do in the rhs code of catchRetry# lhs rhs, it's already
|
|
1231 | - // using the parent transaction (not a nested one).
|
|
1232 | - // See Note [catchRetry# implementation]
|
|
1233 | - return (ret);
|
|
1213 | + outer = StgTRecHeader_enclosing_trec(trec);
|
|
1214 | + (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
|
|
1215 | + if (r != 0) {
|
|
1216 | + // Succeeded (either first branch or second branch)
|
|
1217 | + StgTSO_trec(CurrentTSO) = outer;
|
|
1218 | + return (ret);
|
|
1219 | + } else {
|
|
1220 | + // Did not commit: abort and restart.
|
|
1221 | + StgTSO_trec(CurrentTSO) = outer;
|
|
1222 | + jump stg_abort();
|
|
1234 | 1223 | }
|
1235 | 1224 | }
|
1236 | 1225 | |
... | ... | @@ -1463,26 +1452,21 @@ retry_pop_stack: |
1463 | 1452 | outer = StgTRecHeader_enclosing_trec(trec);
|
1464 | 1453 | |
1465 | 1454 | if (frame_type == CATCH_RETRY_FRAME) {
|
1466 | - // The retry reaches a CATCH_RETRY_FRAME before the ATOMICALLY_FRAME
|
|
1467 | - |
|
1455 | + // The retry reaches a CATCH_RETRY_FRAME before the atomic frame
|
|
1456 | + ASSERT(outer != NO_TREC);
|
|
1457 | + // Abort the transaction attempting the current branch
|
|
1458 | + ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
|
|
1459 | + ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
|
|
1468 | 1460 | if (!StgCatchRetryFrame_running_alt_code(frame) != 0) {
|
1469 | - // Retrying in the lhs of catchRetry# lhs rhs, i.e. in a nested
|
|
1470 | - // transaction. See Note [catchRetry# implementation]
|
|
1471 | - |
|
1472 | - // check that we have a parent transaction
|
|
1473 | - ASSERT(outer != NO_TREC);
|
|
1474 | - |
|
1475 | - // Abort the nested transaction
|
|
1476 | - ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
|
|
1477 | - ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
|
|
1478 | - |
|
1479 | - // As we are retrying in the lhs code, we must now try the rhs code
|
|
1480 | - StgTSO_trec(CurrentTSO) = outer;
|
|
1461 | + // Retry in the first branch: try the alternative
|
|
1462 | + ("ptr" trec) = ccall stmStartTransaction(MyCapability() "ptr", outer "ptr");
|
|
1463 | + StgTSO_trec(CurrentTSO) = trec;
|
|
1481 | 1464 | StgCatchRetryFrame_running_alt_code(frame) = 1 :: CInt; // true;
|
1482 | 1465 | R1 = StgCatchRetryFrame_alt_code(frame);
|
1483 | 1466 | jump stg_ap_v_fast [R1];
|
1484 | 1467 | } else {
|
1485 | - // Retry in the rhs code: propagate the retry
|
|
1468 | + // Retry in the alternative code: propagate the retry
|
|
1469 | + StgTSO_trec(CurrentTSO) = outer;
|
|
1486 | 1470 | Sp = Sp + SIZEOF_StgCatchRetryFrame;
|
1487 | 1471 | goto retry_pop_stack;
|
1488 | 1472 | }
|
... | ... | @@ -1043,7 +1043,8 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception, |
1043 | 1043 | }
|
1044 | 1044 | |
1045 | 1045 | case CATCH_STM_FRAME:
|
1046 | - // CATCH_STM frame within an atomically block: abort the
|
|
1046 | + case CATCH_RETRY_FRAME:
|
|
1047 | + // CATCH frames within an atomically block: abort the
|
|
1047 | 1048 | // inner transaction and continue. Eventually we will
|
1048 | 1049 | // hit the outer transaction that will get frozen (see
|
1049 | 1050 | // above).
|
... | ... | @@ -1055,40 +1056,14 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception, |
1055 | 1056 | {
|
1056 | 1057 | StgTRecHeader *trec = tso -> trec;
|
1057 | 1058 | StgTRecHeader *outer = trec -> enclosing_trec;
|
1058 | - debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_STM frame");
|
|
1059 | + debugTraceCap(DEBUG_stm, cap,
|
|
1060 | + "found atomically block delivering async exception");
|
|
1059 | 1061 | stmAbortTransaction(cap, trec);
|
1060 | 1062 | stmFreeAbortedTRec(cap, trec);
|
1061 | 1063 | tso -> trec = outer;
|
1062 | 1064 | break;
|
1063 | 1065 | };
|
1064 | 1066 | |
1065 | - case CATCH_RETRY_FRAME:
|
|
1066 | - // CATCH_RETY frame within an atomically block: if we're executing
|
|
1067 | - // the lhs code, abort the inner transaction and continue; if we're
|
|
1068 | - // executing thr rhs, continue (no nested transaction to abort. See
|
|
1069 | - // Note [catchRetry# implementation]). Eventually we will hit the
|
|
1070 | - // outer transaction that will get frozen (see above).
|
|
1071 | - //
|
|
1072 | - // As for the CATCH_STM_FRAME case above, we do not care
|
|
1073 | - // whether the transaction is valid or not because its
|
|
1074 | - // possible validity cannot have caused the exception
|
|
1075 | - // and will not be visible after the abort.
|
|
1076 | - {
|
|
1077 | - if (!((StgCatchRetryFrame *)frame) -> running_alt_code) {
|
|
1078 | - debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (lhs)");
|
|
1079 | - StgTRecHeader *trec = tso -> trec;
|
|
1080 | - StgTRecHeader *outer = trec -> enclosing_trec;
|
|
1081 | - stmAbortTransaction(cap, trec);
|
|
1082 | - stmFreeAbortedTRec(cap, trec);
|
|
1083 | - tso -> trec = outer;
|
|
1084 | - }
|
|
1085 | - else
|
|
1086 | - {
|
|
1087 | - debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (rhs)");
|
|
1088 | - }
|
|
1089 | - break;
|
|
1090 | - };
|
|
1091 | - |
|
1092 | 1067 | default:
|
1093 | 1068 | // see Note [Update async masking state on unwind] in Schedule.c
|
1094 | 1069 | if (*frame == (W_)&stg_unmaskAsyncExceptionszh_ret_info) {
|
... | ... | @@ -1505,30 +1505,3 @@ void stmWriteTVar(Capability *cap, |
1505 | 1505 | }
|
1506 | 1506 | |
1507 | 1507 | /*......................................................................*/ |
1508 | - |
|
1509 | - |
|
1510 | - |
|
1511 | -/*
|
|
1512 | - |
|
1513 | -Note [catchRetry# implementation]
|
|
1514 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
1515 | -catchRetry# creates a nested transaction for its lhs:
|
|
1516 | -- if the lhs transaction succeeds:
|
|
1517 | - - the lhs transaction is committed
|
|
1518 | - - its read-variables are merged with those of the parent transaction
|
|
1519 | - - the rhs code is ignored
|
|
1520 | -- if the lhs transaction retries:
|
|
1521 | - - the lhs transaction is aborted
|
|
1522 | - - its read-variables are merged with those of the parent transaction
|
|
1523 | - - the rhs code is executed directly in the parent transaction (see #26028).
|
|
1524 | - |
|
1525 | -So note that:
|
|
1526 | -- lhs code uses a nested transaction
|
|
1527 | -- rhs code doesn't use a nested transaction
|
|
1528 | - |
|
1529 | -We have to take which case we're in into account (using the running_alt_code
|
|
1530 | -field of the catchRetry frame) in catchRetry's entry code, in retry#
|
|
1531 | -implementation, and also when an async exception is received (to cleanup the
|
|
1532 | -right number of transactions).
|
|
1533 | - |
|
1534 | -*/ |
1 | -module Main where
|
|
2 | - |
|
3 | -import GHC.Conc
|
|
4 | - |
|
5 | -forever :: IO String
|
|
6 | -forever = delay 10 >> forever
|
|
7 | - |
|
8 | -terminates :: IO String
|
|
9 | -terminates = delay 1 >> pure "terminates"
|
|
10 | - |
|
11 | -delay s = threadDelay (1000000 * s)
|
|
12 | - |
|
13 | -async :: IO a -> IO (STM a)
|
|
14 | -async a = do
|
|
15 | - var <- atomically (newTVar Nothing)
|
|
16 | - forkIO (a >>= atomically . writeTVar var . Just)
|
|
17 | - pure (readTVar var >>= maybe retry pure)
|
|
18 | - |
|
19 | -main :: IO ()
|
|
20 | -main = do
|
|
21 | - x <- mapM async $ terminates : replicate 50000 forever
|
|
22 | - r <- atomically (foldr1 orElse x)
|
|
23 | - print r |
1 | -"terminates" |
1 | -test('T26028', only_ways(['threaded1']), compile_and_run, ['-O2']) |