[Git][ghc/ghc][wip/fendor/ghc-ghci-mhu-27640] GHCi: Fix order of `PackageDBFlag`s for interactive home unit
by Hannes Siebenhandl (@fendor) 25 Aug '26
by Hannes Siebenhandl (@fendor) 25 Aug '26
25 Aug '26
Hannes Siebenhandl pushed to branch wip/fendor/ghc-ghci-mhu-27640 at Glasgow Haskell Compiler / GHC
Commits:
d71f262c by fendor at 2026-08-25T21:10:26+02:00
GHCi: Fix order of `PackageDBFlag`s for interactive home unit
`PackageDBFlag`s are stored in reverse order of cli specification.
When sorting the `PackageDBFlag`s by longest common prefix, we need thus
to reverse the package db stacks before calculating the prefix.
We make sure to reverse the package db stack for the interactive home
unit to uphold that later specified package dbs overwrite earlier ones.
Resolved and adds regression test for #27640
- - - - -
13 changed files:
- ghc/GHCi/UI.hs
- + testsuite/tests/ghci/prog-mhu007/Makefile
- + testsuite/tests/ghci/prog-mhu007/a/A.hs
- + testsuite/tests/ghci/prog-mhu007/all.T
- + testsuite/tests/ghci/prog-mhu007/b/B.hs
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.script
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg
- + testsuite/tests/ghci/prog-mhu007/unitA
- + testsuite/tests/ghci/prog-mhu007/unitB
Changes:
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -148,6 +148,7 @@ import Data.Version ( showVersion )
import qualified Data.Semigroup as S
import GHC.Prelude
+import GHC.Utils.Trace
import GHC.Utils.Exception as Exception hiding (catch, mask, handle)
import Foreign hiding (void)
import GHC.Stack hiding (SrcLoc(..))
@@ -864,8 +865,14 @@ installInteractiveHomeUnits dflags = do
pure (HUG.mkHomeUnitEnv unit_state dflags hpt (Just home_unit))
concatPackageDbStacksUsingLongestCommonPrefix :: [[PackageDBFlag]] -> [PackageDBFlag]
- concatPackageDbStacksUsingLongestCommonPrefix stacks =
+ concatPackageDbStacksUsingLongestCommonPrefix stacks' =
let
+ -- Package DB stacks are accumulated from the cli right to left.
+ -- E.g., @-clear-package-db -global-package-db@ is stored as
+ -- @[GlobalPackageDb, ClearPackageDb]@.
+ -- Hence, we reverse the stacks, before computing the longest common prefix,
+ -- otherwise the prefix won't match at all.
+ stacks = map List.reverse stacks'
-- O (m * n)
-- m ... Number of PackageDBFlag stacks
-- n ... Size of the stacks
@@ -873,8 +880,22 @@ installInteractiveHomeUnits dflags = do
map List.head . List.takeWhile ((List.all . (==) . List.head) <*> List.tail) . List.transpose
prefix =
longestCommonPrefix stacks
+
+ -- We reverse each individual stack segment to maintain the relative order.
+ -- There should be no 'ClearPackageDb' in here, otherwise we are going to overwrite
+ -- the longest common prefix stacks.
+ unmergableStack =
+ nubOrd (concatMap (List.reverse . List.drop (length prefix)) stacks)
in
- prefix ++ nubOrd (concatMap (List.drop (length prefix)) stacks)
+ -- We reverse the final common package db stack again to match the expectation of 'packageDBFlags' that they are
+ -- stord in reverse order.
+ unmergableStack ++ reverse prefix
+
+-- [[d, b, a], [c, b, a]]
+-- [[a, b, d], [a, b, c]]
+-- [a, b], [[d], [c]]
+-- [d, c,]
+-- [d, c, b, a]
reportError :: GhciMonad m => GhciCommandMessage -> m ()
reportError err = do
=====================================
testsuite/tests/ghci/prog-mhu007/Makefile
=====================================
@@ -0,0 +1,33 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+PKGCONF_FOO=local-foo.package.conf
+PKGCONF_BAR=local-bar.package.conf
+LOCAL_GHC_PKG_FOO = '$(GHC_PKG)' --no-user-package-db -f $(PKGCONF_FOO)
+LOCAL_GHC_PKG_BAR = '$(GHC_PKG)' --no-user-package-db -f $(PKGCONF_BAR)
+
+# Finds both packages in different unit databases
+.PHONY: prog-mhu007
+prog-mhu007:
+ cd testpkg-foo && \
+ '$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
+ -v0 -fno-code -fwrite-interface -hidir dist-testpkg-foo-0.1.0.0 -this-unit-id testpkg-foo-0.1.0.0-XXX \
+ -i. Foo
+ cd testpkg-bar && \
+ '$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
+ -v0 -fno-code -fwrite-interface -hidir dist-testpkg-bar-0.1.0.0 -this-unit-id testpkg-bar-0.1.0.0-XXX \
+ -i. Bar
+
+ $(LOCAL_GHC_PKG_FOO) init $(PKGCONF_FOO) 2>/dev/null
+ $(LOCAL_GHC_PKG_FOO) register --force testpkg-foo/testpkg-foo.pkg 2>/dev/null
+ $(LOCAL_GHC_PKG_FOO) hide testpkg-foo
+ $(LOCAL_GHC_PKG_FOO) list
+
+ $(LOCAL_GHC_PKG_BAR) init $(PKGCONF_BAR) 2>/dev/null
+ $(LOCAL_GHC_PKG_BAR) register --force testpkg-bar/testpkg-bar.pkg 2>/dev/null
+ $(LOCAL_GHC_PKG_BAR) hide testpkg-bar
+ $(LOCAL_GHC_PKG_BAR) list
+
+ '$(TEST_HC)' $(TEST_HC_OPTS_INTERACTIVE) $(WAY_FLAGS) $(ghciWayFlags) \
+ -no-user-package-db -fno-code -unit @unitA -unit @unitB < prog-mhu007.script
=====================================
testsuite/tests/ghci/prog-mhu007/a/A.hs
=====================================
@@ -0,0 +1,3 @@
+module A where
+
+import Bar
=====================================
testsuite/tests/ghci/prog-mhu007/all.T
=====================================
@@ -0,0 +1,8 @@
+
+proj_files = extra_files(['a/', 'b/', 'unitA', 'unitB', 'testpkg-bar/', 'testpkg-foo/'])
+
+test('prog-mhu007',
+ [proj_files,
+ cmd_prefix('ghciWayFlags=' + config.ghci_way_flags),
+ req_interp],
+ makefile_test, ['prog-mhu007'])
=====================================
testsuite/tests/ghci/prog-mhu007/b/B.hs
=====================================
@@ -0,0 +1,3 @@
+module B where
+
+import Foo
=====================================
testsuite/tests/ghci/prog-mhu007/prog-mhu007.script
=====================================
@@ -0,0 +1,5 @@
+:m + A B
+"Loaded A and B"
+import Foo
+import Bar
+"Loaded dependencies Foo and Bar"
=====================================
testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout
=====================================
@@ -0,0 +1,10 @@
+Reading package info from "testpkg-foo/testpkg-foo.pkg" ... done.
+local-foo.package.conf
+ (testpkg-foo-0.1.0.0)
+
+Reading package info from "testpkg-bar/testpkg-bar.pkg" ... done.
+local-bar.package.conf
+ (testpkg-bar-0.1.0.0)
+
+"Loaded A and B"
+"Loaded dependencies Foo and Bar"
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs
=====================================
@@ -0,0 +1 @@
+module Bar where
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg
=====================================
@@ -0,0 +1,11 @@
+name: testpkg-bar
+version: 0.1.0.0
+id: testpkg-bar-0.1.0.0-XXX
+key: testpkg-bar-0.1.0.0-XXX
+exposed: True
+exposed-modules: Bar
+hidden-modules:
+import-dirs: ${pkgroot}/testpkg-bar/dist-testpkg-bar-0.1.0.0
+library-dirs:
+include-dirs:
+hs-libraries:
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs
=====================================
@@ -0,0 +1 @@
+module Foo where
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg
=====================================
@@ -0,0 +1,11 @@
+name: testpkg-foo
+version: 0.1.0.0
+id: testpkg-foo-0.1.0.0-XXX
+key: testpkg-foo-0.1.0.0-XXX
+exposed: True
+exposed-modules: Foo
+hidden-modules:
+import-dirs: ${pkgroot}/testpkg-foo/dist-testpkg-foo-0.1.0.0
+library-dirs:
+include-dirs:
+hs-libraries:
=====================================
testsuite/tests/ghci/prog-mhu007/unitA
=====================================
@@ -0,0 +1,11 @@
+-i
+-ia/
+A
+-this-unit-id a-0.0.0
+-this-package-name a
+-clear-package-db
+-global-package-db
+-no-user-package-db
+-package-db local-bar.package.conf
+-package base
+-package-id testpkg-bar-0.1.0.0-XXX
=====================================
testsuite/tests/ghci/prog-mhu007/unitB
=====================================
@@ -0,0 +1,11 @@
+-i
+-ib/
+B
+-this-unit-id b-0.0.0
+-this-package-name b
+-clear-package-db
+-global-package-db
+-no-user-package-db
+-package-db local-foo.package.conf
+-package base
+-package-id testpkg-foo-0.1.0.0-XXX
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d71f262c340c6847159de00895a06c2…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d71f262c340c6847159de00895a06c2…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/ak/spec-loop] Specialise: Stop looping on recursive dictionaries in interestingDict
by Andreas Klebinger (@AndreasK) 25 Aug '26
by Andreas Klebinger (@AndreasK) 25 Aug '26
25 Aug '26
Andreas Klebinger pushed to branch wip/ak/spec-loop at Glasgow Haskell Compiler / GHC
Commits:
b4f2c4b2 by Andreas Klebinger at 2026-08-25T21:05:01+02:00
Specialise: Stop looping on recursive dictionaries in interestingDict
interestingDict now doesn't look through loopbreaker unfoldings.
Doing so would cause infinite loops on certain dictionaries.
Fixes #27705.
- - - - -
6 changed files:
- + changelog.d/T27705
- compiler/GHC/Core/Opt/Specialise.hs
- + testsuite/tests/simplCore/should_run/T27705.hs
- + testsuite/tests/simplCore/should_run/T27705.stdout
- + testsuite/tests/simplCore/should_run/T27705_Inst.hs
- testsuite/tests/simplCore/should_run/all.T
Changes:
=====================================
changelog.d/T27705
=====================================
@@ -0,0 +1,5 @@
+section: ghc
+synopsis: Prevent the specializer from looping on recursive dictionary superclasses.
+issues: #27705
+mrs: !16559
+
=====================================
compiler/GHC/Core/Opt/Specialise.hs
=====================================
@@ -3120,8 +3120,8 @@ interestingDict :: SpecEnv -> CoreExpr -> Bool
-- This is a subtle and important function
-- See Note [Interesting dictionary arguments]
interestingDict env (Var v) -- See (ID3) and (ID5)
+ -- (ID6.a) Might fail for loop breaker dicts but that seems fine.
| Just rhs <- maybeUnfoldingTemplate (idUnfolding v)
- -- Might fail for loop breaker dicts but that seems fine.
= interestingDict env rhs
interestingDict env arg -- Main Plan: use exprIsConApp_maybe
@@ -3152,7 +3152,8 @@ interestingDict env arg -- Main Plan: use exprIsConApp_maybe
where
arg_ty = exprType arg
definitely_not_ip_like = not (couldBeIPLike arg_ty)
- in_scope_env = ISE (substInScopeSet $ se_subst env) realIdUnfolding
+ -- idUnfolding rather than realIdUnfolding: See (ID6.a)
+ in_scope_env = ISE (substInScopeSet $ se_subst env) idUnfolding
{- Note [Ticks on applications]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3268,6 +3269,24 @@ case we can clearly specialise. But there are wrinkles:
(Remember: a constraint tuple is just a class with N superclasses and no methods.)
See discussion on #26831.
+(ID6.a) If we deal with a recursive dictionary as in #27705 we want to avoid
+ infinite recursion while recursing into superclasses.
+
+ For example we might have:
+
+ class D1 a => D2 a
+ class D2 a => D1 a
+
+ The primary concern is that we want to avoid looping on recursive instances.
+ We can achieve this by simply not looking through loop breakers by using idUnfolding
+ rather than readIdUnfolding.
+
+ It's possible that this prevents specialization of edge cases that have loop breakers
+ in their recursive loop. But even if we can find a dictionary like this the simplifier
+ won't look through loopbreaker dictionaries either killing any potential benefit.
+ So while we could handle this case via a already-seen set or fuel we simply don't bother
+ for now.
+
(ID7) A unary (single-method) class is currently represented by (meth |> co). We
will unwrap the cast (see (ID5)) and then want to reply "yes" if the method
has any struture. We rather arbitrarily use `exprIsHNF` for this. (We plan a
=====================================
testsuite/tests/simplCore/should_run/T27705.hs
=====================================
@@ -0,0 +1,9 @@
+module Main where
+
+import T27705_Inst
+
+-- The dictionaries (D1/D2) are mutually recursive. We have to watch
+-- out for the specializer looping on them. This was first detected in #22802
+-- but no test was added, which caused it to break again #27705 :(
+main :: IO ()
+main = print (b (3 :: Int))
=====================================
testsuite/tests/simplCore/should_run/T27705.stdout
=====================================
@@ -0,0 +1 @@
+42
=====================================
testsuite/tests/simplCore/should_run/T27705_Inst.hs
=====================================
@@ -0,0 +1,13 @@
+{-# LANGUAGE UndecidableInstances, UndecidableSuperClasses, FlexibleInstances #-}
+module T27705_Inst where
+
+-- The two dictionaries are mutually recursive, and we have to ensure the specialiser
+-- doesn't loop when it's peaking through their unfoldings.
+class D2 a => D1 a
+class D1 a => D2 a
+instance D2 Int => D1 Int
+instance D1 Int => D2 Int
+
+{-# NOINLINE b #-}
+b :: D1 a => a -> Int
+b _ = 42
=====================================
testsuite/tests/simplCore/should_run/all.T
=====================================
@@ -123,3 +123,5 @@ test('T24359b', normal, compile_and_run, ['-O'])
test('T23429', normal, compile_and_run, ['-O'])
test('T27071', normal, compile_and_run, ['-O -fworker-wrapper-cbv'])
test('T27005', [], multimod_compile_and_run, ['T27005', '-O'])
+test('T27705', [extra_hc_opts('+RTS -M500M -RTS')], multimod_compile_and_run,
+ ['T27705', '-O2 -fexpose-all-unfoldings'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b4f2c4b23cdbb919e8efeb349d19780…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b4f2c4b23cdbb919e8efeb349d19780…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/romes/27514] 2 commits: Driver: structured concurrent worker abstraction
by sheaf (@sheaf) 25 Aug '26
by sheaf (@sheaf) 25 Aug '26
25 Aug '26
sheaf pushed to branch wip/romes/27514 at Glasgow Haskell Compiler / GHC
Commits:
41815394 by sheaf at 2026-08-25T19:40:20+02:00
Driver: structured concurrent worker abstraction
This commits introduces a structured concurrency framework in the style
of the 'ki' library: a collection of threads within a scope.
We implement two kind of concurrent workers on top of this framework:
- Independent workers cannot wait for one another at all. The only
scheduling operation is to wait for quiescence.
- Coordinating workers declare an STM readiness condition (waiting on
other workers to complete) which gates their start.
See Note [Deterministic concurrent workers] in GHC.Driver.Concurrency.
This commit ports upsweep to this new framework, with downsweep being
left as subsequent work.
Further changes along the way:
- Refactoring of how concurrency is acquired to avoid the footgun of
trying to use a no-op 'AbstractSem' as a lock in the serial case.
- The "re-run with -j1" logic for semaphore opening errors no longer
triggers on late semaphore failures (part-way through a lengthy
computation).
- Logger threads are properly cleaned up on exception, with each
concurrent worker's log queue and local TmpFs properly bracketed.
- The 'GhcMessage -> AnyGhcDiagnostic' and 'Maybe Messager'
arguments of 'depanalE', 'depanalPartial' and 'downsweep', which
were all dead in practice, have been dropped.
- - - - -
125e4419 by sheaf at 2026-08-25T19:40:40+02:00
Rule-based deterministic concurrent downsweep
This commit rewrites downsweep as a single query-answering rule
(see 'DownsweepRule') that can be executed by concurrent worker threads.
The design allows every expensive operation (preprocessing files with CPP,
parsing headers, reading interfaces) to be performed concurrently
according to the -j<N>/-jsem flags.
See Note [Rules-based downsweep] in GHC.Driver.Downsweep.
To achieve this, the finder cache was slightly restructured in order to
account for modules whose source files are directly specified as targets;
see the new Note [Known home modules] in GHC.Unit.Finder.Types. This
allowed us to remove 'addModuleToFinder', 'addHomeModuleToFinder' and
a few brittle hacks (e.g. in Backpack).
Fixes #27514
- - - - -
47 changed files:
- + changelog.d/parallel-downsweep
- compiler/GHC/Builtin.hs
- + compiler/GHC/Data/Dependent.hs
- compiler/GHC/Driver/Backpack.hs
- + compiler/GHC/Driver/Concurrency.hs
- + compiler/GHC/Driver/Config/Concurrency.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/LogQueue.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Runtime/Interpreter/JS.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- + compiler/GHC/Utils/Concurrent/Scope.hs
- compiler/GHC/Utils/TmpFs.hs
- compiler/ghc.cabal.in
- ghc/GHCi/UI.hs
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/driver/T27461/Makefile
- + testsuite/tests/driver/T27461/T27461c.stderr
- testsuite/tests/driver/T27461/all.T
- + testsuite/tests/driver/T27461/src/Wrong.hs
- testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/splice-imports/SI35.hs
- utils/check-ppr/Main.hs
- utils/haddock/haddock-api/src/Haddock/Interface.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/48393d72c19fcc650e1b05921a675c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/48393d72c19fcc650e1b05921a675c…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/romes/27514] 2 commits: Driver: structured concurrent worker abstraction
by sheaf (@sheaf) 25 Aug '26
by sheaf (@sheaf) 25 Aug '26
25 Aug '26
sheaf pushed to branch wip/romes/27514 at Glasgow Haskell Compiler / GHC
Commits:
87961ad0 by sheaf at 2026-08-25T19:39:49+02:00
Driver: structured concurrent worker abstraction
This commits introduces a structured concurrency framework in the style
of the 'ki' library: a collection of threads within a scope.
We implement two kind of concurrent workers on top of this framework:
- Independent workers cannot wait for one another at all. The only
scheduling operation is to wait for quiescence.
- Coordinating workers declare an STM readiness condition (waiting on
other workers to complete) which gates their start.
See Note [Deterministic concurrent workers] in GHC.Driver.Concurrency.
This commit ports upsweep to this new framework, with downsweep being
left as subsequent work.
Further changes along the way:
- Refactoring of how concurrency is acquired to avoid the footgun of
trying to use a no-op 'AbstractSem' as a lock in the serial case.
- The "re-run with -j1" logic for semaphore opening errors no longer
triggers on late semaphore failures (part-way through a lengthy
computation).
- Logger threads are properly cleaned up on exception, with each
concurrent worker's log queue and local TmpFs properly bracketed.
- The 'GhcMessage -> AnyGhcDiagnostic' and 'Maybe Messager'
arguments of 'depanalE', 'depanalPartial' and 'downsweep', which
were all dead in practice, have been dropped.
- - - - -
48393d72 by sheaf at 2026-08-25T19:39:50+02:00
Rule-based deterministic concurrent downsweep
This commit rewrites downsweep as a single query-answering rule
(see 'DownsweepRule') that can be executed by concurrent worker threads.
The design allows every expensive operation (preprocessing files with CPP,
parsing headers, reading interfaces) to be performed concurrently
according to the -j<N>/-jsem flags.
See Note [Rules-based downsweep] in GHC.Driver.Downsweep.
To achieve this, the finder cache was slightly restructured in order to
account for modules whose source files are directly specified as targets;
see the new Note [Known home modules] in GHC.Unit.Finder.Types. This
allowed us to remove 'addModuleToFinder', 'addHomeModuleToFinder' and
a few brittle hacks (e.g. in Backpack).
Fixes #27514
- - - - -
47 changed files:
- + changelog.d/parallel-downsweep
- compiler/GHC/Builtin.hs
- + compiler/GHC/Data/Dependent.hs
- compiler/GHC/Driver/Backpack.hs
- + compiler/GHC/Driver/Concurrency.hs
- + compiler/GHC/Driver/Config/Concurrency.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/LogQueue.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Runtime/Interpreter/JS.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- + compiler/GHC/Utils/Concurrent/Scope.hs
- compiler/GHC/Utils/TmpFs.hs
- compiler/ghc.cabal.in
- ghc/GHCi/UI.hs
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/driver/T27461/Makefile
- + testsuite/tests/driver/T27461/T27461c.stderr
- testsuite/tests/driver/T27461/all.T
- + testsuite/tests/driver/T27461/src/Wrong.hs
- testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/splice-imports/SI35.hs
- utils/check-ppr/Main.hs
- utils/haddock/haddock-api/src/Haddock/Interface.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d7e35a0ecf042a6f9323147f1ace67…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d7e35a0ecf042a6f9323147f1ace67…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
25 Aug '26
Andreas Klebinger pushed new branch wip/apk/win-configure at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/apk/win-configure
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/romes/27514] 32 commits: testsuite: Expect length001 failure in nonmoving_thr_sanity
by sheaf (@sheaf) 25 Aug '26
by sheaf (@sheaf) 25 Aug '26
25 Aug '26
sheaf pushed to branch wip/romes/27514 at Glasgow Haskell Compiler / GHC
Commits:
db959f83 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Expect length001 failure in nonmoving_thr_sanity
length001 relies on an optimization rule to avoid excessive stack use.
The nonmoving_thr_sanity way does not enable optimization, so classify
its stack overflow as an expected failure, as is already done for the
other unoptimized nonmoving ways.
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
4f2b7d90 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Omit T22859 in nonmoving threaded ways
T22859 checks allocation-limit handlers with output that depends on
precise allocation behaviour. The nonmoving threaded ways change where
these limits are reached, just as the already-omitted LLVM ways do.
Omit these ways instead of treating their incidental output differences
as test failures.
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
c4abddcb by Simon Jakobi at 2026-08-14T15:16:44-04:00
rts/js: Implement eq_thread, and test Eq/Ord ThreadId (#16761)
Since d1f3c63701, Eq ThreadId is implemented via the RTS function
eq_thread, but the JS RTS never provided it, so comparing ThreadIds
for equality on the JS backend crashed with
ReferenceError: h$eq_thread is not defined
Like the C implementation, h$eq_thread uses pointer equality: The JS
RTS has exactly one thread object per thread.
Since previously no test exercised eq_thread directly, this commit
adds a test covering equality, its stability across GC, and agreement
with Ord.
Assisted-by: Claude Fable 5
- - - - -
4a7defa1 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Make listThreads1 insensitive to the RTS's own threads
listThreads1 expected `listThreads` to return exactly [ThreadId 1]. That
holds only under a non-threaded RTS. Under a threaded RTS however there
are more threads present, so we change the test to simply check that
`myThreadId` is present in the list.
Assisted-by: Claude Opus 5
- - - - -
b757727a by Vladislav Zavialov at 2026-08-14T15:17:27-04:00
Fix tcLookupId panic with RequiredTypeArguments and PatternSynonyms (#27586)
The arguments declared on the left-hand side of a pattern synonym are looked up
as term variables bound by its right-hand side. Prior to this patch, that lookup
panicked with RequiredTypeArguments:
data T a where
MkT :: forall a -> T a
pattern P :: Int -> T Int
pattern P x = MkT x
On the RHS, `x` looks like a term argument, so the renamer binds it in the term
namespace. Only during type checking does it turn out to be a type variable, so
the lookup on the LHS finds an ATyVar rather than an ATcId. As the lookup was
done with tcLookupId, it resulted in a panic.
Now the arguments are looked up with tcLookupPatSynArg, which reports an illegal
term-level use of `x`, just as an ordinary function definition `f (MkT x) = x`
does.
Test cases: T27586a T27586b T27586c
Assisted-by: Claude Opus 5
- - - - -
c130188d by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
loopImports: Don't dup ms_uid in summary imports
We were writing the ms_unitid of the mod summary with every single
import of that module
That complicated the code (as though the UnitId in that list could ever
be something else) and also allocates unnecessarily per every mod
import. Very slight allocation decrease measured locally in a few tests:
(MultiComponentModulesRecomp: -0.06%; MultiComponentModulesRecomp100: -0.05%)
Purely a clean up.
- - - - -
c71166a8 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
downsweep: make control flow simpler and cache correct
This refactor extracts the control flow of downsweep into a single
function `dfsBuild`, which takes care of iteratively expanding and
traversing all nodes of the in-construction module graph necessary to
build a full `ModuleGraph`.
There are three levels of caching going on, all of which are necessary
to make sure we don't do repeated work (notably, NEVER summarise the
same module twice).
1. `dfsBuild` accumulates the final module graph and never revisits the
same node of the module graph. Cache is keyed by the final
`ModuleGraph`s `NodeKey`s.
2. For Module A in home-unit u1, each import in the list of imports
needs to be *found* (call to `findImportedModuleWithIsBoot`): at this
point, we only have the `ModuleName` of the import, not the `Module`.
This *finding* is somewhat expensive, so we cache it as well
(`ImportsCache`). The cache key is the home-unit to which the module
belongs~[1], the import package qualifier, and the ModuleName.
[1] Different home-units will have different package flags, which means
potentially different `Module` resolution for the same `ModuleName`.
3. The most expensive operation we want to avoid is summarising a
`Module` into a `ModSummary`, which notably involves parsing the
module header from scratch.
The third cache, in essence, maps a `Module` to its `ModSummary`
(named `ModSummaryCache`). This cache upholds the invariant: we NEVER
summarise the same module twice. In practice, the cache key is the
Module's UnitId and the Source path; the reason is we need to
distinguish between `.hs` and `.hs-boot` files, as their summaries
will differ.
Note that (2) can't guarantee this alone: Two ModuleName imports in
separate units can (and likely do) map to the same `Module`.
Note that the previous implementation failed to achieve the
no-duplicate-work summarisation invariant, and we ended up doing a
quadratic amount of processing in scenarios like test
`MultiComponentModules100`.
See also Note [Downsweep Control Flow and Caching]
Fixes #27461
Perf changes:
MultiComponentModules(normal) ghc/alloc 2,097,389,264 1,992,186,736 -5.0% GOOD
MultiComponentModules100(normal) ghc/alloc 24,310,173,770 21,293,867,360 -12.4% GOOD
MultiComponentModulesRecomp(normal) ghc/alloc 602,761,394 498,543,984 -17.3% GOOD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,968,240 8,895,404,864 -25.2% GOOD
-------------------------
Metric Decrease:
MultiComponentModules
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
-------------------------
- - - - -
ebc4047b by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
implicitRequirementsShallow can never reach HoleUnit
findImportedModule will never return `HoleUnit` for a `ModuleName`
(a `HoleUnit` can only be found as a signature instantiation, never as a
directly *imported* thing)
Therefore, we can drop `[ModuleName]` returned by
`implicitRequirementsShallow`, which makes many things dead code.
Namely, the call to `implicitRequirementsShallow` from
GHC.Driver.Downsweep which was a performance bottleneck (for doing lots
of duplicate work in findImportedModule) is now entirely gone.
Fixes #27053
In an MR with this patch and the downsweep refactor (previous commit), CI says:
MultiComponentModules(normal) ghc/alloc 2,097,396,728 1,943,662,304 -7.3% GOOD
MultiComponentModules100(normal) ghc/alloc 24,310,182,136 17,227,574,440 -29.1% GOOD
MultiComponentModulesRecomp(normal) ghc/alloc 602,769,518 449,973,656 -25.3% GOOD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,976,408 4,828,894,160 -59.4% GOOD
-------------------------
Metric Decrease:
MultiComponentModules
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
-------------------------
- - - - -
85a6ab01 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
downsweep: Cache negative results
When traversing a module graph structure, a uniquely identified node
should always expand to the same thing.
I don't see how visiting the same node which failed to be expanded a
first time would ever successfully expand the second time we try to
expand it (eg. when coming from a different edge to it -- it is still
the same node!). The node expansion is local, based just based on the
node itself, not on the path to get there.
Therefore, this patch removes the weird behavior and commentary of
`dfsBuild` wrt to `Nothing` not being cached and being potentially
expanded a second time around to something different, which was
misleading and, ultimately, incorrect.
Now, we have a `MGRes`, which is more explicit about a node being
Skipped just being a node that is ignored whenever it is found (and that
skip is cached) -- and we may want to do this due to failures or due to
just trying nodes which might not work on purpose, like hs-boots.
We uniformly cache positive and negative results and remove the
assumption that there might be an ordering in which the same node
visited at a later time might be expanded differently.
This makes it possible to traverse the module nodes in parallel without
a change in behavior, since there's no longer a hidden ordering
requirement.
- - - - -
56747c3f by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
Organize and clean-up GHC.Driver.Downsweep
Simply some cosmetic changes, moving definitions around to structure the
module better into its relevant sections
(In go (ns ++ ss), it's not a problem to use ++ because it's a good
producer and we won't have to append fully before processing the next
item in go)
- - - - -
12f64118 by Wolfgang Jeltsch at 2026-08-15T06:31:12-04:00
Add support for textual output of bytecode file content
- - - - -
a737df91 by Brandon Chinn at 2026-08-15T12:40:25-04:00
Add law in qualified strings doc
- - - - -
e3188581 by Zubin Duggal at 2026-08-15T12:41:06-04:00
DmdAnal: Fix maxDmdType
We need to eta expand the smaller DmdType using defaultArgDmd, like in lubDmdType.
Introduce zipDmdType as a common combinator to implement both maxDmdType and lubDmdType
uniformly.
fixes #27626
- - - - -
ca9b0b22 by mangoiv at 2026-08-15T12:41:47-04:00
hadrian: set the executable bit for hie-bios.bat
- - - - -
1aac7095 by sheaf at 2026-08-16T04:37:16-04:00
Avoid wasteful allocations in mkTyConAppCo
The idiom "traverse isReflCo_maybe" followed by "map fst" used in
'GHC.Core.Coercion.mkTyConAppCo' was allocating a lot of waste.
This commit uses 'GHC.Data.Unboxed.traverseMaybeUB' to avoid all these
unnecessary intermediate allocations.
In a quick microbenchmark for 'mkTyConAppCo', this change resulted in:
- refl case (all argument coercions are reflexive):
- -60% runtime
- -80% allocations
- non-refl case:
- from 0% to -12% runtime (depending on which argument is non-refl)
- from 0% to -70% allocations ( -- '' -- )
Fixes #27648
-------------------------
Metric Decrease:
FamAppCachePerf
SimplCastPerf
T12425
T15703
T26426
T3064
T9872a
T9872b
T9872b_defer
T9872c
T9872d
T5321Fun
T9020
T9630
TcPlugin_RewritePerf
Metric Increase:
LinkableUsage02
-------------------------
- - - - -
3915e982 by Alan Zimmerman at 2026-08-16T04:37:58-04:00
EPA: Remove al_trailing from AnnList
It was not being used
- - - - -
fed942ac by Andreas Klebinger at 2026-08-17T12:11:57-04:00
testsuite: Use sigkill in process009.
SIGHUB might have been blocked by a (grand)*parent of the test.
In such cases the test would fail as the python process would simply
exist gracefully instead of committing to a premature end.
By using SIGKILL we can rely on the signal not being blocked, fixing #27578
in the process.
- - - - -
574c875f by Andreas Klebinger at 2026-08-17T12:12:39-04:00
Simplify comparison in DFM.hs
Fixes #27669
- - - - -
d8f1a2a3 by Alan Zimmerman at 2026-08-17T12:13:18-04:00
TTG: Add extension points to BooleanFormula
They are currently unused, but will be used for exact print
annotations next, allowing us to get rid of LocatedBF / SrcSpanAnnBF
- - - - -
93a2b20f by Andreas Klebinger at 2026-08-18T04:31:04-04:00
Fix a number of incorrect module references:
Fix module reference in Note [DataCon wrappers are conlike].
Fix module reference in Note [Detailed InertCans Invariants].
Fix module reference in Note [GHC's data format representations].
Fix module reference in Note [Grand plan for static forms].
Fix module reference in Note [How tuples work].
Fix module reference in Note [Solved dictionaries].
Fix module reference in Note [Stacktraces from Info Table Provenance Entries (IPE based stack unwinding)].
Fix module reference in Note [The VarBndr type and its uses].
Found the incorrect references with a llm.
- - - - -
eb0dfb01 by Simon Jakobi at 2026-08-18T04:31:44-04:00
ci: Run stack-hadrian-build only in full-ci pipelines
The job exists to catch changes that break hadrian/build-stack (#18726),
but nothing in the pipeline depends on it, and it can only break when
hadrian's dependencies change. Restricting it to full-ci (like
hadrian-multi) still covers marge-bot merge batches, so such breakage
cannot reach master unnoticed, while ordinary validate pipelines skip
the job.
Assisted-by: Claude Fable 5
- - - - -
b9160962 by Simon Jakobi at 2026-08-20T14:57:52-04:00
testsuite: Show baseline sample count and range in perf failures
A perf baseline is the mean of all samples recorded for a commit, and
it prints as a single number, hiding how far the samples spread. When
the spread is wide, this can indicate an unstable metric that isn't
actually useful as a signal for the perf tests.
For example, in #27602, T27336's peak_megabytes_allocated baseline
showed as 757 when the underlying samples were 605 and 909.
When the baseline is averaged from more than one sample, say so in the
failure output: the one-line stat-failure reason shows the sample
range, and the detail block lists the raw samples. Single-sample
baselines print exactly as before.
Context: #27602
Assisted-by: Claude Fable 5
- - - - -
a4979877 by Simon Jakobi at 2026-08-20T14:57:52-04:00
testsuite: Fold Baseline into CommitMetric
A Baseline was just a CommitMetric plus the commit it came from, built
by copying fields across. Since get_commit_metric already knows that
commit, record it on CommitMetric itself and drop Baseline. This also
collapses both branches of find_baseline into plain returns.
Assisted-by: Claude Fable 5
- - - - -
99fb8d68 by Simon Jakobi at 2026-08-20T14:57:52-04:00
ci: Clarify comment on pushing perf notes after failures
Context: #27602
Assisted-by: Claude Fable 5
- - - - -
2ca87972 by Alan Zimmerman at 2026-08-20T14:58:36-04:00
EPA: Remove LocatedBC / SrcSpanBF
The custom annotations are now in the BooleanFormula TTG extension
points, so LBooleanFormula can now use the standard LocatedA.
- - - - -
d2bc32aa by Simon Peyton Jones at 2026-08-21T12:59:26-04:00
Better handling of serialisation of wired-in names
Fixes #27501
- - - - -
d2795ffc by Alan Zimmerman at 2026-08-21T13:00:05-04:00
EPA: Remove NoEpTok/NoEpUniTok, using an unhelpful SrcSpan instead
Also introduce helper functions noEpTok and noEpUniTok to serve
as simple replacements in code inserting an token annotation without
location information.
- - - - -
44af8d88 by Rodrigo Mesquita at 2026-08-25T19:26:26+02:00
Refactor GHC.Driver.MakeAction
Pull out of 'runParPipelines' the logic for creating a 'MakeEnv' ready
to be used by multiple threads, as that will be useful for downsweep as
well (which doesn't fit the 'runPipelines' flow), rather than being just
for upsweep.
The code is moved and re-structured to match the export list, simplify
the sequentiality checks previously both in 'runPipelines' and
'runAllPipelines', which were weirdly similar and confusing; into the
two part step where we need these checks: (1) to construct the MakeEnv,
(2) to run the MakeActions in parallel. These two steps are separate and
used to be too mixed up.
Some additional little simplifications or clean ups here and there.
- - - - -
23c13075 by Rodrigo Mesquita at 2026-08-25T19:26:26+02:00
Refactor GHC.Driver.Downsweep in preparation for parallel downsweep
Pure refactor to improve the code to facilitate implementing parallel
downsweep in the next commit.
This commit puts a MakeEnv into the DownsweepEnv, gives the fields
proper names and uses RecordWildcards to simplify, rather than passing
around all diagnostic wrappers, driver-message-things and using 10s of
positional fields.
No behavior changes here!
- - - - -
4decefa4 by sheaf at 2026-08-25T19:26:26+02:00
2-phase Cache/Search Finder monad
This commit restructures the finder abstraction by introducing the
'FinderM' monad, which splits module lookup operations into two phases:
- a cache-only phase, performing no filesystem access,
- from the first cache miss onwards, a search action which may access
the filesystem.
This allows consumers to distinguish between quick cached results versus
more expensive filesystem search operations.
- - - - -
44f0a00f by sheaf at 2026-08-25T19:26:27+02:00
Driver: structured concurrent worker abstraction
This commits introduces a structured concurrency framework in the style
of the 'ki' library: a collection of threads within a scope.
We implement two kind of concurrent workers on top of this framework:
- Independent workers cannot wait for one another at all. The only
scheduling operation is to wait for quiescence.
- Coordinating workers declare an STM readiness condition (waiting on
other workers to complete) which gates their start.
See Note [Deterministic concurrent workers] in GHC.Driver.Concurrency.
This commit ports upsweep to this new framework, with downsweep being
left as subsequent work.
Further changes along the way:
- Refactoring of how concurrency is acquired to avoid the footgun of
trying to use a no-op 'AbstractSem' as a lock in the serial case.
- The "re-run with -j1" logic for semaphore opening errors no longer
triggers on late semaphore failures (part-way through a lengthy
computation).
- Logger threads are properly cleaned up on exception, with each
concurrent worker's log queue and local TmpFs properly bracketed.
- The 'GhcMessage -> AnyGhcDiagnostic' and 'Maybe Messager'
arguments of 'depanalE', 'depanalPartial' and 'downsweep', which
were all dead in practice, have been dropped.
- - - - -
d7e35a0e by sheaf at 2026-08-25T19:26:28+02:00
Rule-based deterministic concurrent downsweep
This commit rewrites downsweep as a single query-answering rule
(see 'DownsweepRule') that can be executed by concurrent worker threads.
The design allows every expensive operation (preprocessing files with CPP,
parsing headers, reading interfaces) to be performed concurrently
according to the -j<N>/-jsem flags.
See Note [Rules-based downsweep] in GHC.Driver.Downsweep.
To achieve this, the finder cache was slightly restructured in order to
account for modules whose source files are directly specified as targets;
see the new Note [Known home modules] in GHC.Unit.Finder.Types. This
allowed us to remove 'addModuleToFinder', 'addHomeModuleToFinder' and
a few brittle hacks (e.g. in Backpack).
Fixes #27514
- - - - -
176 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- + changelog.d/27626
- + changelog.d/T27586
- + changelog.d/downsweep-refactor
- + changelog.d/parallel-downsweep
- + changelog.d/show-byte-code
- compiler/GHC.hs
- compiler/GHC/Builtin.hs
- compiler/GHC/Builtin/WiredIn/Types.hs
- compiler/GHC/ByteCode/Serialize.hs
- + compiler/GHC/ByteCode/Show.hs
- compiler/GHC/CmmToAsm/Format.hs
- compiler/GHC/Core/Class.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/Data/BooleanFormula.hs
- + compiler/GHC/Data/Dependent.hs
- compiler/GHC/Data/Unboxed.hs
- compiler/GHC/Data/Word64Map/Internal.hs
- compiler/GHC/Data/Word64Map/Lazy.hs
- compiler/GHC/Data/Word64Map/Strict.hs
- compiler/GHC/Data/Word64Map/Strict/Internal.hs
- compiler/GHC/Driver/Backpack.hs
- + compiler/GHC/Driver/Concurrency.hs
- + compiler/GHC/Driver/Config/Concurrency.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/GenerateCgIPEStub.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/LogQueue.hs
- compiler/GHC/Hs.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Runtime/Interpreter/JS.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Plugin.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/TyCl/Class.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/Unique/DFM.hs
- compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- + compiler/GHC/Utils/Concurrent/Scope.hs
- compiler/GHC/Utils/TmpFs.hs
- compiler/Language/Haskell/Syntax/BooleanFormula.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/ghc.cabal.in
- docs/users_guide/exts/qualified_strings.rst
- docs/users_guide/using.rst
- ghc/GHC/Driver/Session/Mode.hs
- ghc/GHCi/UI.hs
- ghc/Main.hs
- hadrian/hie-bios.bat
- libraries/base/tests/all.T
- libraries/base/tests/listThreads1.hs
- libraries/base/tests/listThreads1.stdout
- linters/lint-codes/LintCodes/Static.hs
- rts/js/thread.js
- testsuite/driver/perf_notes.py
- testsuite/driver/testglobals.py
- + testsuite/tests/concurrent/should_run/T16761.hs
- + testsuite/tests/concurrent/should_run/T16761.stdout
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/diagnostic-codes/codes.stdout
- + testsuite/tests/dmdanal/should_run/M2.hs
- + testsuite/tests/dmdanal/should_run/T27626.hs
- + testsuite/tests/dmdanal/should_run/T27626.stdout
- testsuite/tests/dmdanal/should_run/all.T
- + testsuite/tests/driver/T27461/Main1.hs
- + testsuite/tests/driver/T27461/Main2.hs
- + testsuite/tests/driver/T27461/Makefile
- + testsuite/tests/driver/T27461/T27461a.stderr
- + testsuite/tests/driver/T27461/T27461b.script
- + testsuite/tests/driver/T27461/T27461b.stderr
- + testsuite/tests/driver/T27461/T27461b.stdout
- + testsuite/tests/driver/T27461/T27461c.stderr
- + testsuite/tests/driver/T27461/all.T
- + testsuite/tests/driver/T27461/src/Bar.hs
- + testsuite/tests/driver/T27461/src/Wrong.hs
- testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/exactprint/T22919.stderr
- testsuite/tests/ghc-api/exactprint/Test20239.stderr
- testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T24221.stderr
- testsuite/tests/module/mod185.stderr
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- testsuite/tests/parser/should_compile/T15279.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/parser/should_compile/T20452.stderr
- testsuite/tests/parser/should_compile/T20718.stderr
- testsuite/tests/parser/should_compile/T20718b.stderr
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/parser/should_compile/T23315/T23315.stderr
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/printer/AnnotationNoListTuplePuns.stdout
- testsuite/tests/printer/T18791.stderr
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- testsuite/tests/process/process009.hs
- testsuite/tests/process/process009.stdout
- testsuite/tests/rts/all.T
- + testsuite/tests/show-bytecode/Example.hs
- + testsuite/tests/show-bytecode/Makefile
- + testsuite/tests/show-bytecode/all.T
- + testsuite/tests/show-bytecode/normalize
- + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout
- + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout-javascript-unknown-ghcjs
- + testsuite/tests/show-bytecode/show-bytecode-hpc.stdout
- + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout
- + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout-javascript-unknown-ghcjs
- testsuite/tests/splice-imports/SI35.hs
- + testsuite/tests/vdq-rta/should_fail/T27586a.hs
- + testsuite/tests/vdq-rta/should_fail/T27586a.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586b.hs
- + testsuite/tests/vdq-rta/should_fail/T27586b.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586c.hs
- + testsuite/tests/vdq-rta/should_fail/T27586c.stderr
- testsuite/tests/vdq-rta/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/check-ppr/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Interface.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/845046b13ab8e7fc64d4a62b541258…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/845046b13ab8e7fc64d4a62b541258…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/romes/27514] Rule-based deterministic concurrent downsweep
by sheaf (@sheaf) 25 Aug '26
by sheaf (@sheaf) 25 Aug '26
25 Aug '26
sheaf pushed to branch wip/romes/27514 at Glasgow Haskell Compiler / GHC
Commits:
845046b1 by sheaf at 2026-08-25T19:25:53+02:00
Rule-based deterministic concurrent downsweep
This commit rewrites downsweep as a single query-answering rule
(see 'DownsweepRule') that can be executed by concurrent worker threads.
The design allows every expensive operation (preprocessing files with CPP,
parsing headers, reading interfaces) to be performed concurrently
according to the -j<N>/-jsem flags.
See Note [Rules-based downsweep] in GHC.Driver.Downsweep.
To achieve this, the finder cache was slightly restructured in order to
account for modules whose source files are directly specified as targets;
see the new Note [Known home modules] in GHC.Unit.Finder.Types. This
allowed us to remove 'addModuleToFinder', 'addHomeModuleToFinder' and
a few brittle hacks (e.g. in Backpack).
Fixes #27514
- - - - -
40 changed files:
- + changelog.d/parallel-downsweep
- compiler/GHC/Builtin.hs
- + compiler/GHC/Data/Dependent.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Concurrency.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Runtime/Interpreter/JS.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- compiler/ghc.cabal.in
- ghc/GHCi/UI.hs
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/driver/T27461/Makefile
- + testsuite/tests/driver/T27461/T27461c.stderr
- testsuite/tests/driver/T27461/all.T
- + testsuite/tests/driver/T27461/src/Wrong.hs
- testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/splice-imports/SI35.hs
- utils/check-ppr/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/845046b13ab8e7fc64d4a62b5412588…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/845046b13ab8e7fc64d4a62b5412588…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/romes/27514] 3 commits: 2-phase Cache/Search Finder monad
by sheaf (@sheaf) 25 Aug '26
by sheaf (@sheaf) 25 Aug '26
25 Aug '26
sheaf pushed to branch wip/romes/27514 at Glasgow Haskell Compiler / GHC
Commits:
1a5108eb by sheaf at 2026-08-25T18:53:54+02:00
2-phase Cache/Search Finder monad
This commit restructures the finder abstraction by introducing the
'FinderM' monad, which splits module lookup operations into two phases:
- a cache-only phase, performing no filesystem access,
- from the first cache miss onwards, a search action which may access
the filesystem.
This allows consumers to distinguish between quick cached results versus
more expensive filesystem search operations.
- - - - -
efe55b84 by sheaf at 2026-08-25T19:17:22+02:00
Driver: structured concurrent worker abstraction
This commits introduces a structured concurrency framework in the style
of the 'ki' library: a collection of threads within a scope.
We implement two kind of concurrent workers on top of this framework:
- Independent workers cannot wait for one another at all. The only
scheduling operation is to wait for quiescence.
- Coordinating workers declare an STM readiness condition (waiting on
other workers to complete) which gates their start.
See Note [Deterministic concurrent workers] in GHC.Driver.Concurrency.
This commit ports upsweep to this new framework, with downsweep being
left as subsequent work.
Further changes along the way:
- Refactoring of how concurrency is acquired to avoid the footgun of
trying to use a no-op 'AbstractSem' as a lock in the serial case.
- The "re-run with -j1" logic for semaphore opening errors no longer
triggers on late semaphore failures (part-way through a lengthy
computation).
- Logger threads are properly cleaned up on exception, with each
concurrent worker's log queue and local TmpFs properly bracketed.
- The 'GhcMessage -> AnyGhcDiagnostic' and 'Maybe Messager'
arguments of 'depanalE', 'depanalPartial' and 'downsweep', which
were all dead in practice, have been dropped.
- - - - -
d4a8eecc by sheaf at 2026-08-25T19:25:12+02:00
Rule-based deterministic concurrent downsweep
This commit rewrites downsweep as a single query-answering rule
(see 'DownsweepRule') that can be executed by concurrent worker threads.
The design allows every expensive operation (preprocessing files with CPP,
parsing headers, reading interfaces) to be performed concurrently
according to the -j<N>/-jsem flags.
See Note [Rules-based downsweep] in GHC.Driver.Downsweep.
To achieve this, the finder cache was slightly restructured in order to
account for modules whose source files are directly specified as targets;
see the new Note [Known home modules] in GHC.Unit.Finder.Types. This
allowed us to remove 'addModuleToFinder', 'addHomeModuleToFinder' and
a few brittle hacks (e.g. in Backpack).
Fixes #27514
- - - - -
58 changed files:
- + changelog.d/parallel-downsweep
- compiler/GHC.hs
- compiler/GHC/Builtin.hs
- + compiler/GHC/Data/Dependent.hs
- compiler/GHC/Driver/Backpack.hs
- + compiler/GHC/Driver/Concurrency.hs
- + compiler/GHC/Driver/Config/Concurrency.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/LogQueue.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Runtime/Interpreter/JS.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Plugin.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- + compiler/GHC/Utils/Concurrent/Scope.hs
- compiler/GHC/Utils/TmpFs.hs
- compiler/ghc.cabal.in
- ghc/GHCi/UI.hs
- ghc/Main.hs
- linters/lint-codes/LintCodes/Static.hs
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/driver/T27461/Makefile
- + testsuite/tests/driver/T27461/T27461c.stderr
- testsuite/tests/driver/T27461/all.T
- + testsuite/tests/driver/T27461/src/Wrong.hs
- testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- testsuite/tests/ghc-api/downsweep/OldModLocation.hs
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/splice-imports/SI35.hs
- utils/check-ppr/Main.hs
- utils/haddock/haddock-api/src/Haddock/Interface.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/81cdb258b37044ed30a246fd319393…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/81cdb258b37044ed30a246fd319393…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 6 commits: Add Data.RealFloat and Infinity/NegInfinity/NaN pattern synonyms (#26961)
by Marge Bot (@marge-bot) 25 Aug '26
by Marge Bot (@marge-bot) 25 Aug '26
25 Aug '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
ca7a8e7f by Brandon Chinn at 2026-08-25T13:21:35-04:00
Add Data.RealFloat and Infinity/NegInfinity/NaN pattern synonyms (#26961)
- - - - -
95884a75 by Andreas Klebinger at 2026-08-25T13:21:38-04:00
rts linker: Fix pointer arithmetic issue in flushInstructionCacheRISCV64
We accidentally operated over `uint64_t*` when we should use `uint8_t`.
Fixes #27569
- - - - -
7e6dabb4 by Zubin Duggal at 2026-08-25T13:21:40-04:00
ghc-internal: annotateSTM should use catchSTM# rather than catch#
A catch# frame inside a transaction breaks retry and async exception
delivery.
Fixes #27657
- - - - -
ee8a334d by Rodrigo Mesquita at 2026-08-25T13:21:41-04:00
rts: refactor to reduce THREADED_RTS in MSG_UPD_TSO_FLAGS
- No behavior change in this commit (well, a small optimization here
makes us do less work if the target TSO owned by the curr. capability)
- Move all THREADED_RTS CPP needed into `updThreadFlag`
- Merge MSG_SET_TSO_FLAGS and MSG_UNSET_TSO_FLAGS into MSG_UPD_TSO_FLAGS
plus a `set` bool field in the MessageUpdTSOFlag struct
Towards #27729
- - - - -
bd7a24fb by Rodrigo Mesquita at 2026-08-25T13:21:41-04:00
rts: Fix race condition in MSG_UPD_TSO_FLAGS execution
The code for processing the MSG_UPD_TSO_FLAGS message was not taking
into consideration that the TSO's owner might have moved in between that
capability receiving the message (since it was its previous owner) and
starting to process its inbox (a point at which it was no longer the
owner)
Added Note [TSO owner may change in between Msg being sent and received]
to explain this race and the pattern used to fix this, where we just
forward the message to the new owner.
Fixes #27729
- - - - -
51021cd3 by Alan Zimmerman at 2026-08-25T13:21:41-04:00
EPA: Uses Parsers.parseModule for exactprint tests
Parsers.parseModule is the advertised way to parse for use for exact
printing in the ghc-exactprint library. This commit updates the GHC
exact print testing to use it.
This requires moving the comment balancing that was occurring
only in the test path into the advertising parser path, so it moves
from Transforms.hs to Utils.hs.
Also update the comment adding to honour trailing annotations
- - - - -
27 changed files:
- + changelog.d/T27657
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- + libraries/base/src/Data/RealFloat.hs
- libraries/ghc-internal/src/GHC/Internal/STM.hs
- rts/CloneStack.c
- rts/Interpreter.c
- rts/Messages.c
- rts/StgMiscClosures.cmm
- rts/Threads.c
- rts/Threads.h
- rts/include/rts/storage/Closures.h
- rts/include/stg/MiscClosures.h
- rts/linker/elf_reloc_riscv64.c
- + testsuite/tests/concurrent/should_run/T27657a.hs
- + testsuite/tests/concurrent/should_run/T27657a.stdout
- + testsuite/tests/concurrent/should_run/T27657b.hs
- + testsuite/tests/concurrent/should_run/T27657b.stdout
- testsuite/tests/concurrent/should_run/all.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
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
Changes:
=====================================
changelog.d/T27657
=====================================
@@ -0,0 +1,9 @@
+section: base
+issues: #27657
+mrs: !16508
+synopsis:
+ Fix ``retry`` and async exception delivery inside a ``catchSTM`` handler
+description:
+ ``catchSTM``\'s ``WhileHandling`` annotation used ``catch#``, leaving an IO
+ ``CATCH_FRAME`` inside the transaction. Use ``catchSTM#``, which is the
+ correct way to catch exceptions inside STM.
=====================================
libraries/base/base.cabal.in
=====================================
@@ -117,6 +117,7 @@ Library
, Data.Monoid
, Data.Ord
, Data.Proxy
+ , Data.RealFloat
, Data.STRef
, Data.STRef.Strict
, Data.String
=====================================
libraries/base/changelog.md
=====================================
@@ -9,6 +9,8 @@
* Introduce `Data.Double` and `Data.Float` modules. ([CLC proposal #378](https://github.com/haskell/core-libraries-committee/issues/378))
* Change `Generically a`'s `Monoid` definition to require a `Semigroup` constraint, and define its `mconcat` using `(<>)` from that constraint. ([CLC proposal #413](https://github.com/haskell/core-libraries-committee/issues/413))
* Add `withEmptyCallStack` to `GHC.Stack`. ([CLC proposal #428](https://github.com/haskell/core-libraries-committee/issues/428))
+ * Add new `Data.RealFloat` module re-exporting `RealFloat` from `GHC.Float` ([CLC proposal #394](https://github.com/haskell/core-libraries-committee/issues/394))
+ * Add `Infinity`, `NegInfinity`, and `NaN` pattern synonyms to `Data.RealFloat` ([CLC proposal #394](https://github.com/haskell/core-libraries-committee/issues/394))
## 4.23.0.0 *TBA*
* Add `System.IO.hGetNewlineMode`. ([CLC proposal #370](https://github.com/haskell/core-libraries-committee/issues/370))
=====================================
libraries/base/src/Data/RealFloat.hs
=====================================
@@ -0,0 +1,59 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE Safe #-}
+{-# LANGUAGE ViewPatterns #-}
+
+-- |
+--
+-- Module : Data.RealFloat
+-- Copyright : (c) The University of Glasgow 2026
+-- License : BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer : libraries(a)haskell.org
+-- Stability : stable
+-- Portability : portable
+--
+
+module Data.RealFloat (
+ RealFloat (..),
+
+ -- * Infinity + NaN
+ pattern Infinity,
+ pattern NegInfinity,
+ pattern NaN,
+) where
+
+import Data.Bool (Bool (..), (&&))
+import GHC.Internal.Data.Ord ((<), (>))
+import GHC.Internal.Float (RealFloat (..))
+import GHC.Internal.Real ((/))
+#if __GLASGOW_HASKELL__ >= 1001
+import qualified GHC.Essentials as Rebindable
+#endif
+
+pattern Infinity :: (RealFloat a) => a
+pattern Infinity <- ((\x -> isInfinite x && x > 0) -> True) where Infinity = 1/0
+
+-- | Negative infinity
+--
+-- Provided for convenience. Could also use the following instead:
+-- * Pattern matching: @(negate -> Infinity)@
+-- * Expressions: @-Infinity@
+pattern NegInfinity :: (RealFloat a) => a
+pattern NegInfinity <- ((\x -> isInfinite x && x < 0) -> True) where NegInfinity = -1/0
+
+-- | A pattern synonym for NaN values.
+--
+-- Note: Per IEEE 754, NaN is never equal to itself, thus these two snippets
+-- have different behavior:
+--
+-- @
+-- -- foo1 NaN == "a"
+-- foo1 NaN = "a"
+-- foo1 _ = "b"
+--
+-- -- foo2 NaN == "b"
+-- foo2 x = if x == NaN then "a" else "b"
+-- @
+pattern NaN :: (RealFloat a) => a
+pattern NaN <- (isNaN -> True) where NaN = 0/0
=====================================
libraries/ghc-internal/src/GHC/Internal/STM.hs
=====================================
@@ -31,7 +31,7 @@ import GHC.Internal.Exception.Context (ExceptionAnnotation)
import GHC.Internal.Exception.Type (WhileHandling(..))
import GHC.Internal.Maybe (Maybe(..))
import GHC.Internal.Prim (
- RealWorld, State#, TVar#, atomically#, catch#, catchRetry#, catchSTM#,
+ RealWorld, State#, TVar#, atomically#, catchRetry#, catchSTM#,
newTVar#, raiseIO#, readTVar#, readTVarIO#, retry#, writeTVar#,
)
import GHC.Internal.Prim.PtrEq (sameTVar#)
@@ -213,7 +213,7 @@ catchSTM (STM m) handler = STM $ catchSTM# m handler'
-- | Execute an 'STM' action, adding the given 'ExceptionContext'
-- to any thrown synchronous exceptions.
annotateSTM :: forall e a. ExceptionAnnotation e => e -> STM a -> STM a
-annotateSTM ann (STM io) = STM (catch# io handler)
+annotateSTM ann (STM io) = STM (catchSTM# io handler) -- not catch#, see #27657
where
handler se = raiseIO# (addExceptionContext ann se)
=====================================
rts/CloneStack.c
=====================================
@@ -88,6 +88,7 @@ void sendCloneStackMessage(StgTSO *tso, HsStablePtr mvar) {
void handleCloneStackMessage(Capability *cap, MessageCloneStack *msg){
// We must check that the current owner of the thread we want to clone the stack for
// is still this capability.
+ // See Note [TSO owner may change in between Msg being sent and received]
Capability *owner = RELAXED_LOAD(&msg->tso->cap);
if (owner != cap) {
// The target TSO may have migrated after the message was queued on the old
=====================================
rts/Interpreter.c
=====================================
@@ -416,22 +416,14 @@ void rts_disableStopNextBreakpointAll(void)
void rts_enableStopNextBreakpoint(StgTSO* tso)
{
-#if defined(THREADED_RTS)
Capability* cap = rts_unsafeGetMyCapability();
setThreadFlag(cap, tso, TSO_STOP_NEXT_BREAKPOINT);
-#else
- tso->flags |= TSO_STOP_NEXT_BREAKPOINT;
-#endif
}
void rts_disableStopNextBreakpoint(StgTSO* tso)
{
-#if defined(THREADED_RTS)
Capability* cap = rts_unsafeGetMyCapability();
unsetThreadFlag(cap, tso, TSO_STOP_NEXT_BREAKPOINT);
-#else
- tso->flags &= ~TSO_STOP_NEXT_BREAKPOINT;
-#endif
}
/* ---------------------------------------------------------------------------
@@ -440,22 +432,14 @@ void rts_disableStopNextBreakpoint(StgTSO* tso)
void rts_enableStopAfterReturn(StgTSO* tso)
{
-#if defined(THREADED_RTS)
Capability* cap = rts_unsafeGetMyCapability();
setThreadFlag(cap, tso, TSO_STOP_AFTER_RETURN);
-#else
- tso->flags |= TSO_STOP_AFTER_RETURN;
-#endif
}
void rts_disableStopAfterReturn(StgTSO* tso)
{
-#if defined(THREADED_RTS)
Capability* cap = rts_unsafeGetMyCapability();
unsetThreadFlag(cap, tso, TSO_STOP_AFTER_RETURN);
-#else
- tso->flags &= ~TSO_STOP_AFTER_RETURN;
-#endif
}
/*
=====================================
rts/Messages.c
=====================================
@@ -36,8 +36,7 @@ void sendMessage(Capability *from_cap, Capability *to_cap, Message *msg)
i != &stg_IND_info && // can happen if a MSG_BLACKHOLE is revoked
i != &stg_WHITEHOLE_info &&
i != &stg_MSG_CLONE_STACK_info &&
- i != &stg_MSG_SET_TSO_FLAG_info &&
- i != &stg_MSG_UNSET_TSO_FLAG_info) {
+ i != &stg_MSG_UPD_TSO_FLAG_info) {
barf("sendMessage: %p", i);
}
}
@@ -67,6 +66,62 @@ void sendMessage(Capability *from_cap, Capability *to_cap, Message *msg)
Handle a message
------------------------------------------------------------------------- */
+/*
+Note [TSO owner may change in between Msg being sent and received]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When a message is sent from Capability (C1) to a target TSO (T2) (e.g.
+MessageUpdTSOFlag, MessageCloneStack, ...), it is queued on the TSO's owner
+Capability (C3) inbox (inboxes are owned by Capabilities, not TSOs).
+
+At a later point, the Capability (C3) will process its inbox. Upon receiving
+the message meant for a specific TSO (T2), it must first always check that the
+TSO's owner is *still* itself (C3).
+
+The target TSO (T2) may have migrated after the message was queued on its old
+capability (C3). In that case we must forward the request to the new owner
+(say, C4); otherwise the Capability C3 could be modifying a TSO it no longer
+owns, racing with its actual owner mutating it, since it is no longer the owner.
+
+The message meant for a TSO should only be executed when the receiving
+Capability is still the owner of that TSO. Otherwise, it must be forwarded to
+the new owner.
+
+The general pattern is one where there's a top-level function which assumes it
+can be called by capabilities other than the TSO's owner. The function checks
+whether the current capability is the TSO owner. If yes, execute the action. If
+not, then it sends a message to the current TSO's owner. On receiving the
+message, the new capability will just call that top-level function, which will
+ensure the message is forwarded again if the TSO owner changed.
+It will look something like:
+
+ runMyMsg(Capability *from, StgTSO *target, ...) {
+
+#if defined(THREADED_RTS)
+ Capability *owner = RELAXED_LOAD(&target->cap)
+ if (owner != from) {
+ MessageMyMsg* msg = ...
+ sendMessage(cap, owner, msg)
+ return
+ }
+#endif
+
+ actuallyDoTheWork(...)
+ }
+
+ executeMessage(...) {
+
+ if (i == &stg_MY_MSG_info) {
+
+ MessageMyMsg* msg = (MessageMyMsg*) m
+ runMyMsg(cap, m->tso, ...)
+
+ }
+ }
+
+See example `updThreadFlag` and `executeMessage`'s `stg_MSG_UPD_TSO_FLAG_info`,
+or `tryWakeUpThread` and `stg_MSG_TRY_WAKEUP_info` for two live examples.
+*/
+
#if defined(THREADED_RTS)
void
@@ -141,15 +196,11 @@ loop:
MessageCloneStack *cloneStackMessage = (MessageCloneStack*) m;
handleCloneStackMessage(cap, cloneStackMessage);
}
- else if(i == &stg_MSG_SET_TSO_FLAG_info){
+ else if(i == &stg_MSG_UPD_TSO_FLAG_info){
MessageUpdTSOFlag *u = (MessageUpdTSOFlag*) m;
- u->tso->flags |= u->flag;
- return;
- }
- else if(i == &stg_MSG_UNSET_TSO_FLAG_info){
- MessageUpdTSOFlag *u = (MessageUpdTSOFlag*) m;
- u->tso->flags &= ~u->flag;
- return;
+
+ StgTSO *tso = RELAXED_LOAD(&u->tso);
+ updThreadFlag(cap, tso, u->flag, u->set);
}
else
{
=====================================
rts/StgMiscClosures.cmm
=====================================
@@ -855,11 +855,8 @@ INFO_TABLE_CONSTR(stg_MSG_NULL,1,0,0,PRIM,"MSG_NULL","MSG_NULL")
INFO_TABLE_CONSTR(stg_MSG_CLONE_STACK,3,0,0,PRIM,"MSG_CLONE_STACK","MSG_CLONE_STACK")
{ ccall pbarf("stg_MSG_CLONE_STACK object (%p) entered!", R1 "ptr") never returns; }
-INFO_TABLE_CONSTR(stg_MSG_SET_TSO_FLAG,2,1,0,PRIM,"MSG_SET_TSO_FLAG","MSG_SET_TSO_FLAG")
-{ foreign "C" barf("stg_MSG_SET_TSO_FLAG object (%p) entered!", R1) never returns; }
-
-INFO_TABLE_CONSTR(stg_MSG_UNSET_TSO_FLAG,2,1,0,PRIM,"MSG_UNSET_TSO_FLAG","MSG_UNSET_TSO_FLAG")
-{ foreign "C" barf("stg_MSG_UNSET_TSO_FLAG object (%p) entered!", R1) never returns; }
+INFO_TABLE_CONSTR(stg_MSG_UPD_TSO_FLAG,2,2,0,PRIM,"MSG_UPD_TSO_FLAG","MSG_UPD_TSO_FLAG")
+{ foreign "C" barf("stg_MSG_UPD_TSO_FLAG object (%p) entered!", R1) never returns; }
/* ----------------------------------------------------------------------------
END_TSO_QUEUE
=====================================
rts/Threads.c
=====================================
@@ -379,32 +379,46 @@ migrateThread (Capability *from, StgTSO *tso, Capability *to)
sets or unsets a flag in a given TSO
------------------------------------------------------------------------- */
-#if defined(THREADED_RTS)
-static void
-updThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag, const StgInfoTable* info);
-
void setThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag)
{
- updThreadFlag(from, tso, flag, &stg_MSG_SET_TSO_FLAG_info);
+ updThreadFlag(from, tso, flag, true);
}
void unsetThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag)
{
- updThreadFlag(from, tso, flag, &stg_MSG_UNSET_TSO_FLAG_info);
+ updThreadFlag(from, tso, flag, false);
}
-static void
-updThreadFlag(Capability *from, StgTSO *tso, StgWord32 flag, const StgInfoTable* info)
+void
+updThreadFlag(Capability *from USED_IF_THREADS, StgTSO *tso, StgWord32 flag, StgBool set /* true=set, false=unset */)
{
- MessageUpdTSOFlag *msg;
- msg = (MessageUpdTSOFlag *)allocate(from,sizeofW(MessageUpdTSOFlag));
- msg->tso = tso;
- msg->flag = flag;
- SET_HDR_RELEASE(msg, info, CCS_SYSTEM);
- sendMessage(from, tso->cap, (Message*)msg);
-}
+#if defined(THREADED_RTS)
+ // If we're the current owner of the thread we want to modify, do it.
+ // Otherwise, we must forward the message to the actual owner.
+ // When executing the upd message, we check again that we're still the TSO
+ // owner (which may have changed since the message was queued on this cap.)
+ // See Note [TSO owner may change in between Msg being sent and received]
+ Capability *tso_owner = RELAXED_LOAD(&tso->cap);
+ if (from != tso_owner) {
+ MessageUpdTSOFlag *msg;
+ msg = (MessageUpdTSOFlag *)allocate(from,sizeofW(MessageUpdTSOFlag));
+ msg->tso = tso;
+ msg->flag = flag;
+ msg->set = set;
+ SET_HDR_RELEASE(msg, &stg_MSG_UPD_TSO_FLAG_info, CCS_SYSTEM);
+ sendMessage(from, tso_owner, (Message*)msg);
+ return;
+ }
#endif
+ if (set) {
+ tso->flags |= flag;
+ }
+ else {
+ tso->flags &= ~flag;
+ }
+}
+
/* ----------------------------------------------------------------------------
awakenBlockedQueue
=====================================
rts/Threads.h
=====================================
@@ -19,10 +19,9 @@ void checkBlockingQueues (Capability *cap, StgTSO *tso);
void tryWakeupThread (Capability *cap, StgTSO *tso);
void migrateThread (Capability *from, StgTSO *tso, Capability *to);
-#if defined(THREADED_RTS)
void setThreadFlag (Capability *from, StgTSO *tso, StgWord32 flag);
void unsetThreadFlag (Capability *from, StgTSO *tso, StgWord32 flag);
-#endif
+void updThreadFlag (Capability *from, StgTSO *tso, StgWord32 flag, StgBool set);
// Wakes up a thread on a Capability (probably a different Capability
// from the one held by the current Task).
=====================================
rts/include/rts/storage/Closures.h
=====================================
@@ -625,6 +625,7 @@ typedef struct MessageUpdTSOFlag_ {
Message *link;
StgTSO *tso;
StgWord flag;
+ StgWord set; // bool: true=SET; false=UNSET
} MessageUpdTSOFlag;
/* ----------------------------------------------------------------------------
=====================================
rts/include/stg/MiscClosures.h
=====================================
@@ -151,8 +151,7 @@ RTS_ENTRY(stg_MSG_TRY_WAKEUP);
RTS_ENTRY(stg_MSG_THROWTO);
RTS_ENTRY(stg_MSG_BLACKHOLE);
RTS_ENTRY(stg_MSG_CLONE_STACK);
-RTS_ENTRY(stg_MSG_SET_TSO_FLAG);
-RTS_ENTRY(stg_MSG_UNSET_TSO_FLAG);
+RTS_ENTRY(stg_MSG_UPD_TSO_FLAG);
RTS_ENTRY(stg_MSG_NULL);
RTS_ENTRY(stg_MVAR_TSO_QUEUE);
RTS_ENTRY(stg_catch);
=====================================
rts/linker/elf_reloc_riscv64.c
=====================================
@@ -679,7 +679,7 @@ void flushInstructionCacheRISCV64(ObjectCode *oc) {
/* The main object code */
void *codeBegin = oc->image + oc->misalignment;
- __builtin___clear_cache(codeBegin, (void*) ((uint64_t*) codeBegin + oc->fileSize));
+ __builtin___clear_cache(codeBegin, (void*) ((uint8_t*) codeBegin + oc->fileSize));
/* Jump Islands */
__builtin___clear_cache((void *)oc->symbol_extras,
=====================================
testsuite/tests/concurrent/should_run/T27657a.hs
=====================================
@@ -0,0 +1,15 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- A retry escaping a catchSTM handler must reach the enclosing orElse. An IO
+-- CATCH_FRAME in the way trips an assertion in findRetryFrameHelper.
+
+import Control.Exception
+import GHC.Conc
+
+main :: IO ()
+main = do
+ r <- atomically $
+ catchSTM (throwSTM (ErrorCall "boom"))
+ (\(_ :: SomeException) -> retry)
+ `orElse` pure "T27657a: completed"
+ putStrLn r
=====================================
testsuite/tests/concurrent/should_run/T27657a.stdout
=====================================
@@ -0,0 +1 @@
+T27657a: completed
=====================================
testsuite/tests/concurrent/should_run/T27657b.hs
=====================================
@@ -0,0 +1,40 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- An async exception delivered while a catchSTM handler runs must abort the
+-- transaction, not be swallowed by a restart of the invalidated one.
+
+import Control.Concurrent.MVar
+import Control.Exception
+import GHC.Conc
+
+waitParked :: ThreadId -> IO ()
+waitParked t = do
+ s <- threadStatus t
+ case s of
+ ThreadBlocked BlockedOnMVar -> pure ()
+ _ -> threadDelay 1000 >> waitParked t
+
+main :: IO ()
+main = do
+ tv <- newTVarIO (0 :: Int)
+ park <- newEmptyMVar
+ result <- newEmptyMVar
+ t <- forkIO $ do
+ r <- try $ atomically $ do
+ v <- readTVar tv
+ catchSTM (throwSTM (ErrorCall "boom"))
+ (\(_ :: SomeException) ->
+ if v == 0
+ then do unsafeIOToSTM (takeMVar park)
+ pure "handler resumed"
+ else pure "transaction restarted, exception dropped")
+ putMVar result (r :: Either SomeException String)
+ -- parked in the handler, so t cannot revalidate its trec before delivery
+ waitParked t
+ atomically (writeTVar tv 1)
+ killThread t
+ r <- takeMVar result
+ putStrLn $ case r of
+ Left e | Just ThreadKilled <- fromException e -> "T27657b: killThread delivered"
+ | otherwise -> "T27657b: unexpected exception: " ++ displayException e
+ Right s -> "T27657b: FAILED, " ++ s
=====================================
testsuite/tests/concurrent/should_run/T27657b.stdout
=====================================
@@ -0,0 +1 @@
+T27657b: killThread delivered
=====================================
testsuite/tests/concurrent/should_run/all.T
=====================================
@@ -340,3 +340,6 @@ test('T27105_fail',
extra_run_opts('+RTS -C0.2 -RTS'), expect_fail,
run_timeout_multiplier(0.05)],
multimod_compile_and_run, ['T27105.hs', ''])
+
+test('T27657a', normal, compile_and_run, [''])
+test('T27657b', normal, compile_and_run, [''])
=====================================
testsuite/tests/interface-stability/base-exports.stdout
=====================================
@@ -1626,6 +1626,29 @@ module Data.Ratio where
denominator :: forall a. Ratio a -> a
numerator :: forall a. Ratio a -> a
+module Data.RealFloat where
+ -- Safety: Safe
+ pattern Infinity :: forall a. RealFloat a => a
+ pattern NaN :: forall a. RealFloat a => a
+ pattern NegInfinity :: forall a. RealFloat a => a
+ type RealFloat :: * -> Constraint
+ class (GHC.Internal.Real.RealFrac a, GHC.Internal.Float.Floating a) => RealFloat a where
+ floatRadix :: a -> GHC.Internal.Bignum.Integer.Integer
+ floatDigits :: a -> GHC.Internal.Types.Int
+ floatRange :: a -> (GHC.Internal.Types.Int, GHC.Internal.Types.Int)
+ decodeFloat :: a -> (GHC.Internal.Bignum.Integer.Integer, GHC.Internal.Types.Int)
+ encodeFloat :: GHC.Internal.Bignum.Integer.Integer -> GHC.Internal.Types.Int -> a
+ exponent :: a -> GHC.Internal.Types.Int
+ significand :: a -> a
+ scaleFloat :: GHC.Internal.Types.Int -> a -> a
+ isNaN :: a -> GHC.Internal.Types.Bool
+ isInfinite :: a -> GHC.Internal.Types.Bool
+ isDenormalized :: a -> GHC.Internal.Types.Bool
+ isNegativeZero :: a -> GHC.Internal.Types.Bool
+ isIEEE :: a -> GHC.Internal.Types.Bool
+ atan2 :: a -> a -> a
+ {-# MINIMAL floatRadix, floatDigits, floatRange, decodeFloat, encodeFloat, isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE #-}
+
module Data.STRef where
-- Safety: Safe
type role STRef nominal representational
=====================================
testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
=====================================
@@ -1626,6 +1626,29 @@ module Data.Ratio where
denominator :: forall a. Ratio a -> a
numerator :: forall a. Ratio a -> a
+module Data.RealFloat where
+ -- Safety: Safe
+ pattern Infinity :: forall a. RealFloat a => a
+ pattern NaN :: forall a. RealFloat a => a
+ pattern NegInfinity :: forall a. RealFloat a => a
+ type RealFloat :: * -> Constraint
+ class (GHC.Internal.Real.RealFrac a, GHC.Internal.Float.Floating a) => RealFloat a where
+ floatRadix :: a -> GHC.Internal.Bignum.Integer.Integer
+ floatDigits :: a -> GHC.Internal.Types.Int
+ floatRange :: a -> (GHC.Internal.Types.Int, GHC.Internal.Types.Int)
+ decodeFloat :: a -> (GHC.Internal.Bignum.Integer.Integer, GHC.Internal.Types.Int)
+ encodeFloat :: GHC.Internal.Bignum.Integer.Integer -> GHC.Internal.Types.Int -> a
+ exponent :: a -> GHC.Internal.Types.Int
+ significand :: a -> a
+ scaleFloat :: GHC.Internal.Types.Int -> a -> a
+ isNaN :: a -> GHC.Internal.Types.Bool
+ isInfinite :: a -> GHC.Internal.Types.Bool
+ isDenormalized :: a -> GHC.Internal.Types.Bool
+ isNegativeZero :: a -> GHC.Internal.Types.Bool
+ isIEEE :: a -> GHC.Internal.Types.Bool
+ atan2 :: a -> a -> a
+ {-# MINIMAL floatRadix, floatDigits, floatRange, decodeFloat, encodeFloat, isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE #-}
+
module Data.STRef where
-- Safety: Safe
type role STRef nominal representational
=====================================
testsuite/tests/interface-stability/base-exports.stdout-mingw32
=====================================
@@ -1626,6 +1626,29 @@ module Data.Ratio where
denominator :: forall a. Ratio a -> a
numerator :: forall a. Ratio a -> a
+module Data.RealFloat where
+ -- Safety: Safe
+ pattern Infinity :: forall a. RealFloat a => a
+ pattern NaN :: forall a. RealFloat a => a
+ pattern NegInfinity :: forall a. RealFloat a => a
+ type RealFloat :: * -> Constraint
+ class (GHC.Internal.Real.RealFrac a, GHC.Internal.Float.Floating a) => RealFloat a where
+ floatRadix :: a -> GHC.Internal.Bignum.Integer.Integer
+ floatDigits :: a -> GHC.Internal.Types.Int
+ floatRange :: a -> (GHC.Internal.Types.Int, GHC.Internal.Types.Int)
+ decodeFloat :: a -> (GHC.Internal.Bignum.Integer.Integer, GHC.Internal.Types.Int)
+ encodeFloat :: GHC.Internal.Bignum.Integer.Integer -> GHC.Internal.Types.Int -> a
+ exponent :: a -> GHC.Internal.Types.Int
+ significand :: a -> a
+ scaleFloat :: GHC.Internal.Types.Int -> a -> a
+ isNaN :: a -> GHC.Internal.Types.Bool
+ isInfinite :: a -> GHC.Internal.Types.Bool
+ isDenormalized :: a -> GHC.Internal.Types.Bool
+ isNegativeZero :: a -> GHC.Internal.Types.Bool
+ isIEEE :: a -> GHC.Internal.Types.Bool
+ atan2 :: a -> a -> a
+ {-# MINIMAL floatRadix, floatDigits, floatRange, decodeFloat, encodeFloat, isNaN, isInfinite, isDenormalized, isNegativeZero, isIEEE #-}
+
module Data.STRef where
-- Safety: Safe
type role STRef nominal representational
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -1465,7 +1465,7 @@ instance ExactPrint (HsModule GhcPs) where
Just exps -> do
let (op,cp,tcs) = am_exports $ anns an0
op' <- markEpToken op
- exps' <- mapM markAnnotated exps
+ exps' <- mapM markAnnotated (filter notIEDoc exps)
tcs' <- mapM markEpToken tcs
cp' <- markEpToken cp
return (Just exps', an0 { anns = (anns an0) { am_exports = (op',cp',tcs')}})
=====================================
utils/check-exact/Main.hs
=====================================
@@ -183,7 +183,8 @@ _tt = testOneFile changers "/home/alanz/mysrc/git.haskell.org/ghc/_build/stage1/
-- "../../testsuite/tests/printer/Test17519.hs" Nothing
-- "../../testsuite/tests/printer/InTreeAnnotations1.hs" Nothing
-- "../../testsuite/tests/printer/Test19798.hs" Nothing
- "../../testsuite/tests/printer/Test10309.hs" Nothing
+ -- "../../testsuite/tests/printer/Test10309.hs" Nothing
+ "../../testsuite/tests/printer/Haddock1.hs" Nothing
-- "../../testsuite/tests/qualifieddo/should_compile/qdocompile001.hs" Nothing
-- "../../testsuite/tests/typecheck/should_fail/StrictBinds.hs" Nothing
@@ -304,7 +305,7 @@ writeBinFile fpath x = withBinaryFile fpath WriteMode (\h -> hSetEncoding h utf8
testOneFile :: [(String, Changer)] -> FilePath -> String -> Maybe Changer -> IO ()
testOneFile _ libdir fileName mchanger = do
- (p,_toks) <- parseOneFile libdir fileName
+ p <- parseOneFile libdir fileName
let
origAst = ppAst p
pped = exactPrint p
@@ -333,7 +334,7 @@ testOneFile _ libdir fileName mchanger = do
changedSource <- readFile newFile
return (expectedSource == changedSource, expectedSource, changedSource)
- (p',_) <- parseOneFile libdir newFile
+ p' <- parseOneFile libdir newFile
let newAstStr :: String
newAstStr = ppAst p'
writeBinFile newAstFile newAstStr
@@ -364,15 +365,12 @@ testOneFile _ libdir fileName mchanger = do
ppAst :: Data a => a -> String
ppAst ast = showSDocUnsafe $ showAstData BlankSrcSpanFile NoBlankEpAnnotations ast
-
-parseOneFile :: FilePath -> FilePath -> IO (ParsedSource, [Located Token])
+parseOneFile :: FilePath -> FilePath -> IO ParsedSource
parseOneFile libdir fileName = do
- res <- parseModuleEpAnnsWithCpp libdir defaultCppOptions fileName
+ res <- Parsers.parseModule libdir fileName
case res of
Left m -> error (internalDebugShowMessages m)
- Right (injectedComments, _dflags, pmod) -> do
- let !pmodWithComments = insertCppComments pmod injectedComments
- return (pmodWithComments, [])
+ Right pmod -> return pmod
-- ---------------------------------------------------------------------
@@ -519,8 +517,7 @@ changeLocalDecls libdir (L l p) = do
replaceLocalBinds :: LMatch GhcPs (LHsExpr GhcPs)
-> Transform (LMatch GhcPs (LHsExpr GhcPs))
replaceLocalBinds (L lm (Match an mln pats (GRHSs _ rhs (HsValBinds (van,w) (ValBinds _ bs))))) = do
- let (oldDecls) = map unWrapValBind bs
- -- let decls = s:d:oldDecls
+ let oldDecls = map unWrapValBind bs
let oldDecls' = captureLineSpacing oldDecls
let (VbSig o:oldBinds) = map wrapValBind oldDecls'
o' = setEntryDP o (DifferentLine 2 0)
=====================================
utils/check-exact/Parsers.hs
=====================================
@@ -46,6 +46,7 @@ module Parsers (
) where
import Preprocess
+import Utils
import Data.Functor (void)
@@ -270,7 +271,10 @@ postParseTransform
-> Either a (GHC.ParsedSource)
postParseTransform parseRes = fmap mkAnns parseRes
where
- mkAnns (_cs, _, m) = fixModuleComments m
+ mkAnns (cs, _, m) = fixModuleComments (insertCppComments (noIEDoc m) cs)
+ noIEDoc (GHC.L l m) = case GHC.hsmodExports m of
+ Nothing -> GHC.L l m
+ Just exps -> GHC.L l m { GHC.hsmodExports = Just $ filter notIEDoc exps }
fixModuleComments :: GHC.ParsedSource -> GHC.ParsedSource
fixModuleComments p = fixModuleHeaderComments $ fixModuleTrailingComments p
=====================================
utils/check-exact/Transform.hs
=====================================
@@ -93,7 +93,6 @@ import qualified Control.Monad.Fail as Fail
import GHC hiding (parseModule, parsedSource)
import GHC.Parser.PostProcess ( wrapValBind )
import GHC.Data.FastString
-import GHC.Types.SrcLoc
import Data.Data
import Data.List (unsnoc)
@@ -402,6 +401,14 @@ balanceCommentsList' (a:b:ls) = (a':r)
(a',b') = balanceComments a b
r = balanceCommentsList' (b':ls)
+balanceCommentsListA :: [LocatedA a ] -> [LocatedA a]
+balanceCommentsListA [] = []
+balanceCommentsListA [x] = [x]
+balanceCommentsListA (a:b:ls) = (a':r)
+ where
+ (a',b') = balanceCommentsA a b
+ r = balanceCommentsListA (b':ls)
+
-- |The GHC parser puts all comments appearing between the end of one AST
-- item and the beginning of the next as 'annPriorComments' for the second one.
-- This function takes two adjacent AST items and moves any 'annPriorComments'
@@ -507,15 +514,6 @@ pushTrailingComments w cs lb@(HsValBinds (an,wt) _) = (True, HsValBinds (an',wt)
(HsValBinds _ vb') -> vb'
_ -> ValBinds noExtField []
-
-balanceCommentsListA :: [LocatedA a] -> [LocatedA a]
-balanceCommentsListA [] = []
-balanceCommentsListA [x] = [x]
-balanceCommentsListA (a:b:ls) = (a':r)
- where
- (a',b') = balanceCommentsA a b
- r = balanceCommentsListA (b':ls)
-
-- |Prior to moving an AST element, make sure any trailing comments belonging to
-- it are attached to it, and not the following element. Of necessity this is a
-- heuristic process, to be tuned later. Possibly a variant should be provided
@@ -591,59 +589,6 @@ priorCommentsDeltas r cs = go r (sortEpaComments cs)
-- ---------------------------------------------------------------------
--- | Split comments into ones occurring before the end of the reference
--- span, and those after it.
-splitComments :: RealSrcSpan -> EpAnnComments -> ([LEpaComment], [LEpaComment], [LEpaComment])
-splitComments p cs = (before, middle, after)
- where
- cmpe (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
- cmpe (L _ _) = True
-
- cmpb (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2pos p
- cmpb (L _ _) = True
-
- (beforeEnd, after) = break cmpe ((priorComments cs) ++ (getFollowingComments cs))
- (before, middle) = break cmpb beforeEnd
-
-
--- | Split comments into ones occurring before the end of the reference
--- span, and those after it.
-splitCommentsEnd :: RealSrcSpan -> EpAnnComments -> EpAnnComments
-splitCommentsEnd p (EpaComments cs) = cs'
- where
- cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
- cmp (L _ _) = True
- (before, after) = break cmp cs
- cs' = case after of
- [] -> EpaComments cs
- _ -> epaCommentsBalanced before after
-splitCommentsEnd p (EpaCommentsBalanced cs ts) = epaCommentsBalanced cs' ts'
- where
- cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
- cmp (L _ _) = True
- (before, after) = break cmp cs
- cs' = before
- ts' = after <> ts
-
--- | Split comments into ones occurring before the start of the reference
--- span, and those after it.
-splitCommentsStart :: RealSrcSpan -> EpAnnComments -> EpAnnComments
-splitCommentsStart p (EpaComments cs) = cs'
- where
- cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
- cmp (L _ _) = True
- (before, after) = break cmp cs
- cs' = case after of
- [] -> EpaComments cs
- _ -> epaCommentsBalanced before after
-splitCommentsStart p (EpaCommentsBalanced cs ts) = epaCommentsBalanced cs' ts'
- where
- cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
- cmp (L _ _) = True
- (before, after) = break cmp cs
- cs' = before
- ts' = after <> ts
-
moveLeadingComments :: (Data t, Data u, NoAnn t, NoAnn u)
=> LocatedAn t a -> EpAnn u -> (LocatedAn t a, EpAnn u)
moveLeadingComments (L la a) lb = (L la' a, lb')
@@ -680,19 +625,6 @@ addCommentOrigDeltasAnn (EpAnn e a cs) = EpAnn e a (addCommentOrigDeltas cs)
anchorFromLocatedA :: LocatedA a -> RealSrcSpan
anchorFromLocatedA (L (EpAnn anc _ _) _) = epaLocationRealSrcSpan anc
--- | Get the full span of interest for comments from a LocatedA.
--- This extends up to the last TrailingAnn
-fullSpanFromLocatedA :: LocatedA a -> RealSrcSpan
-fullSpanFromLocatedA (L (EpAnn anc tas _) _) = rr
- where
- r = epaLocationRealSrcSpan anc
- trailing_loc ta = case ta_location ta of
- EpaSpan (RealSrcSpan s _) -> [s]
- _ -> []
- rr = case reverse (concatMap trailing_loc tas) of
- [] -> r
- (s:_) -> combineRealSrcSpans r s
-
-- ---------------------------------------------------------------------
balanceSameLineComments :: LMatch GhcPs (LHsExpr GhcPs) -> (LMatch GhcPs (LHsExpr GhcPs))
=====================================
utils/check-exact/Utils.hs
=====================================
@@ -228,7 +228,7 @@ insertCppComments (L l p) cs0 = insertRemainingCppComments (L l p2) remaining
(p2, remaining) = insertTopLevelCppComments p1 toplevel
addCommentsListItem :: EpAnn [TrailingAnn] -> State [LEpaComment] (EpAnn [TrailingAnn])
- addCommentsListItem = addComments
+ addCommentsListItem = addCommentsA
addCommentsList :: EpAnn AnnList -> State [LEpaComment] (EpAnn AnnList)
addCommentsList = addComments
@@ -249,6 +249,20 @@ insertCppComments (L l p) cs0 = insertRemainingCppComments (L l p2) remaining
_ -> return $ EpAnn anc an ocs
+ addCommentsA :: EpAnn [TrailingAnn] -> State [LEpaComment] (EpAnn [TrailingAnn])
+ addCommentsA ann@(EpAnn anc an ocs) = do
+ case anc of
+ EpaSpan (RealSrcSpan s _) -> do
+ unAllocated <- get
+ let
+ (rest, these) = GHC.Parser.Lexer.allocateComments (fullSpanFromEpAnnA ann) unAllocated
+ balanced = splitCommentsEnd s (EpaComments these)
+ cs' = sortEpAnnComments (ocs <> balanced)
+ put rest
+ return $ EpAnn anc an cs'
+
+ _ -> return $ EpAnn anc an ocs
+
workInComments :: EpAnnComments -> [LEpaComment] -> EpAnnComments
workInComments ocs [] = ocs
workInComments ocs new = cs'
@@ -264,9 +278,14 @@ workInComments ocs new = cs'
= break (\(L ll _) -> (ss2pos $ epaLocationRealSrcSpan ll) > (ss2pos $ epaLocationRealSrcSpan ac) )
new
+sortEpAnnComments :: EpAnnComments -> EpAnnComments
+sortEpAnnComments (EpaComments cs) = EpaComments (sortEpaComments cs)
+sortEpAnnComments (EpaCommentsBalanced pc fc)
+ = EpaCommentsBalanced (sortEpaComments pc) (sortEpaComments fc)
+
insertTopLevelCppComments :: HsModule GhcPs -> [LEpaComment] -> (HsModule GhcPs, [LEpaComment])
insertTopLevelCppComments (HsModule (XModulePs an lo mdeprec mbDoc) mmn mexports imports decls) cs
- = (HsModule (XModulePs an4 lo mdeprec mbDoc) mmn mexports' imports' decls', cs3)
+ = (HsModule (XModulePs an4 lo mdeprec mbDoc) mmn mexports imports' decls', cs3)
-- `debug` ("insertTopLevelCppComments: (cs2,cs3,hc0,hc1,hc_cs)" ++ showAst (cs2,cs3,hc0,hc1,hc_cs))
-- `debug` ("insertTopLevelCppComments: (cs2,cs3,hc0i,hc0,hc1,hc_cs)" ++ showAst (cs2,cs3,hc0i,hc0,hc1,hc_cs))
where
@@ -297,24 +316,7 @@ insertTopLevelCppComments (HsModule (XModulePs an lo mdeprec mbDoc) mmn mexports
cs' = workInComments (comments an1) stay
_ -> (an1,cs0a)
- (mexports', an3, cs1) =
- case mexports of
- Nothing -> (Nothing, an2, cs0b)
- Just exports -> (Just exports', an3', cse)
- where
- (csh', cs0b') = case am_exports $ anns an2 of
- (tokOP, _tokCP, _tokCommas) ->
- case tokOP of
- (EpTok (EpaSpan (RealSrcSpan s _))) -> (h, n)
- where
- (h,n) = break (\(L ll _) -> (ss2pos $ epaLocationRealSrcSpan ll) > (ss2pos s) )
- cs0b
-
- _ -> ([], cs0b)
- hc1' = workInComments (comments an2) csh'
- an3' = an2 { comments = hc1' }
- (exports', cse) = allocPreceding exports cs0b'
- (imports0, cs2) = allocPreceding imports cs1
+ (imports0, cs2) = allocPreceding imports cs0b
(imports', hc0i) = balanceFirstLocatedAComments imports0
(decls0, cs3) = allocPreceding decls cs2
@@ -323,9 +325,9 @@ insertTopLevelCppComments (HsModule (XModulePs an lo mdeprec mbDoc) mmn mexports
-- Either hc0i or hc0d should have comments. Combine them
hc0 = hc0i ++ hc0d
- (hc1,hc_cs) = splitOnWhere After (am_where $ anns an3) hc0
- hc2 = workInComments (comments an3) hc1
- an4 = an3 { anns = (anns an3) {am_cs = hc_cs}, comments = hc2 }
+ (hc1,hc_cs) = splitOnWhere After (am_where $ anns an2) hc0
+ hc2 = workInComments (comments an2) hc1
+ an4 = an2 { anns = (anns an2) {am_cs = hc_cs}, comments = hc2 }
allocPreceding :: [LocatedA a] -> [LEpaComment] -> ([LocatedA a], [LEpaComment])
allocPreceding [] cs' = ([], cs')
@@ -346,7 +348,6 @@ annListBracketsLocs (ListSquare o c) = (getEpTokenLoc o, getEpTokenLoc c)
annListBracketsLocs (ListBanana o c) = (getEpUniTokenLoc o, getEpUniTokenLoc c)
annListBracketsLocs ListNone = (noAnn, noAnn)
-
data SplitWhere = Before | After
splitOnWhere :: SplitWhere -> EpToken "where" -> [LEpaComment] -> ([LEpaComment], [LEpaComment])
@@ -430,6 +431,79 @@ insertRemainingCppComments (L l p) cs = L l p'
-- ---------------------------------------------------------------------
+-- | Get the full span of interest for comments from a LocatedA.
+-- This extends up to the last TrailingAnn
+fullSpanFromLocatedA :: LocatedA a -> RealSrcSpan
+fullSpanFromLocatedA (L ann _) = fullSpanFromEpAnnA ann
+
+-- | Get the full span of interest for comments from a LocatedA.
+-- This extends up to the last TrailingAnn
+fullSpanFromEpAnnA :: EpAnn [TrailingAnn] -> RealSrcSpan
+fullSpanFromEpAnnA (EpAnn anc tas _) = rr
+ where
+ r = epaLocationRealSrcSpan anc
+ trailing_loc ta = case ta_location ta of
+ EpaSpan (RealSrcSpan s _) -> [s]
+ _ -> []
+ rr = case reverse (concatMap trailing_loc tas) of
+ [] -> r
+ (s:_) -> combineRealSrcSpans r s
+
+-- | Split comments into ones occurring before the end of the reference
+-- span, and those after it.
+splitComments :: RealSrcSpan -> EpAnnComments -> ([LEpaComment], [LEpaComment], [LEpaComment])
+splitComments p cs = (before, middle, after)
+ where
+ cmpe (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
+ cmpe (L _ _) = True
+
+ cmpb (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2pos p
+ cmpb (L _ _) = True
+
+ (beforeEnd, after) = break cmpe ((priorComments cs) ++ (getFollowingComments cs))
+ (before, middle) = break cmpb beforeEnd
+
+
+-- | Split comments into ones occurring before the end of the reference
+-- span, and those after it.
+splitCommentsEnd :: RealSrcSpan -> EpAnnComments -> EpAnnComments
+splitCommentsEnd p (EpaComments cs) = cs'
+ where
+ cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
+ cmp (L _ _) = True
+ (before, after) = break cmp cs
+ cs' = case after of
+ [] -> EpaComments cs
+ _ -> epaCommentsBalanced before after
+splitCommentsEnd p (EpaCommentsBalanced cs ts) = epaCommentsBalanced cs' ts'
+ where
+ cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
+ cmp (L _ _) = True
+ (before, after) = break cmp cs
+ cs' = before
+ ts' = after <> ts
+
+-- | Split comments into ones occurring before the start of the reference
+-- span, and those after it.
+splitCommentsStart :: RealSrcSpan -> EpAnnComments -> EpAnnComments
+splitCommentsStart p (EpaComments cs) = cs'
+ where
+ cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
+ cmp (L _ _) = True
+ (before, after) = break cmp cs
+ cs' = case after of
+ [] -> EpaComments cs
+ _ -> epaCommentsBalanced before after
+splitCommentsStart p (EpaCommentsBalanced cs ts) = epaCommentsBalanced cs' ts'
+ where
+ cmp (L (EpaSpan (RealSrcSpan l _)) _) = ss2pos l > ss2posEnd p
+ cmp (L _ _) = True
+ (before, after) = break cmp cs
+ cs' = before
+ ts' = after <> ts
+
+-- ---------------------------------------------------------------------
+
ghcCommentText :: LEpaComment -> String
ghcCommentText (L _ (GHC.EpaComment (EpaDocComment s) _)) = exactPrintHsDocString s
ghcCommentText (L _ (GHC.EpaComment (EpaDocOptions s) _)) = s
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1b3be33c377e2e712865d247351603…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1b3be33c377e2e712865d247351603…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc] Pushed new branch wip/fendor/ghc-ghci-mhu-27640
by Hannes Siebenhandl (@fendor) 25 Aug '26
by Hannes Siebenhandl (@fendor) 25 Aug '26
25 Aug '26
Hannes Siebenhandl pushed new branch wip/fendor/ghc-ghci-mhu-27640 at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/fendor/ghc-ghci-mhu-27640
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0